Compare commits
45 Commits
Author | SHA1 | Date | |
---|---|---|---|
|
864414f8fd | ||
|
cdce02607a | ||
|
7d00f47c5e | ||
|
608383ec84 | ||
|
f3fb038587 | ||
|
a652fb1697 | ||
|
a9775d486e | ||
|
0ec72a122d | ||
|
3e5bbac5a1 | ||
|
82faf2e557 | ||
|
2f0b2f9839 | ||
|
9c1f778e79 | ||
|
5115f640c2 | ||
|
d8760dee6a | ||
|
e1ff3b8dbe | ||
|
8538a57be0 | ||
|
8656655bb1 | ||
|
e3b156bd96 | ||
|
52f06f757f | ||
|
f248fefe06 | ||
|
e55e619328 | ||
|
d017955946 | ||
|
63450b662e | ||
|
518f7234f7 | ||
|
959a66d839 | ||
|
55748d7d1a | ||
|
9de19ff7a1 | ||
|
eafb03ad38 | ||
|
93025c95f2 | ||
|
45f52709a6 | ||
|
ed3d5a9f7f | ||
|
c697aaf656 | ||
|
40851682ce | ||
|
e90795b616 | ||
|
cc220928bd | ||
|
4780a7134d | ||
|
1e2be72e5e | ||
|
9b39b43e90 | ||
|
d2bd58287c | ||
|
f782903587 | ||
|
4f174f1c0b | ||
|
09dc3a5592 | ||
|
de1f082e75 | ||
|
e15d4c0d4a | ||
|
54aee70e68 |
@ -3,6 +3,9 @@
|
|||||||
if [ "$TARGET" = "appimage" ]; then
|
if [ "$TARGET" = "appimage" ]; then
|
||||||
# Compile the AppImage we distribute with Clang.
|
# Compile the AppImage we distribute with Clang.
|
||||||
export EXTRA_CMAKE_FLAGS=(-DCMAKE_CXX_COMPILER=clang++ -DCMAKE_C_COMPILER=clang -DCMAKE_LINKER=/etc/bin/ld.lld)
|
export EXTRA_CMAKE_FLAGS=(-DCMAKE_CXX_COMPILER=clang++ -DCMAKE_C_COMPILER=clang -DCMAKE_LINKER=/etc/bin/ld.lld)
|
||||||
|
# Bundle required QT wayland libraries
|
||||||
|
export EXTRA_QT_PLUGINS="waylandcompositor"
|
||||||
|
export EXTRA_PLATFORM_PLUGINS="libqwayland-egl.so;libqwayland-generic.so"
|
||||||
else
|
else
|
||||||
# For the linux-fresh verification target, verify compilation without PCH as well.
|
# For the linux-fresh verification target, verify compilation without PCH as well.
|
||||||
export EXTRA_CMAKE_FLAGS=(-DCITRA_USE_PRECOMPILED_HEADERS=OFF)
|
export EXTRA_CMAKE_FLAGS=(-DCITRA_USE_PRECOMPILED_HEADERS=OFF)
|
||||||
|
@ -235,7 +235,7 @@ find_package(Threads REQUIRED)
|
|||||||
|
|
||||||
if (ENABLE_QT)
|
if (ENABLE_QT)
|
||||||
if (NOT USE_SYSTEM_QT)
|
if (NOT USE_SYSTEM_QT)
|
||||||
download_qt(6.6.0)
|
download_qt(6.7.2)
|
||||||
endif()
|
endif()
|
||||||
|
|
||||||
find_package(Qt6 REQUIRED COMPONENTS Widgets Multimedia Concurrent)
|
find_package(Qt6 REQUIRED COMPONENTS Widgets Multimedia Concurrent)
|
||||||
|
@ -1 +1,3 @@
|
|||||||
ñ
|
# Citra "PabloMK7 fork"
|
||||||
|
|
||||||
|
This fork has stopped development. A new more serious Citra continuation project will soon follow.
|
||||||
|
16
dist/citra.6
vendored
16
dist/citra.6
vendored
@ -1,4 +1,4 @@
|
|||||||
.Dd November 22 2016
|
.Dd September 13 2024
|
||||||
.Dt citra 6
|
.Dt citra 6
|
||||||
.Os
|
.Os
|
||||||
.Sh NAME
|
.Sh NAME
|
||||||
@ -12,6 +12,20 @@
|
|||||||
.Bl -tag -width Ds
|
.Bl -tag -width Ds
|
||||||
.It Fl g Ar port , Fl Fl gdbport Ar port
|
.It Fl g Ar port , Fl Fl gdbport Ar port
|
||||||
Starts the GDB stub on the specified port
|
Starts the GDB stub on the specified port
|
||||||
|
.It Fl i , Fl Fl install Ar FILE
|
||||||
|
Installs a specified CIA file
|
||||||
|
.It Fl m , Fl Fl multiplayer Ar nick:password@address:port
|
||||||
|
Nickname, password, address and port for multiplayer
|
||||||
|
.It Fl r , Fl Fl movie-record Ar file
|
||||||
|
Record a movie (game inputs) to the given file
|
||||||
|
.It Fl a , Fl Fl movie-record-author Ar AUTHOR
|
||||||
|
Sets the author of the movie to be recorded
|
||||||
|
.It Fl p , Fl Fl movie-play Ar file
|
||||||
|
Playback the movie (game inputs) from the given file
|
||||||
|
.It Fl d , Fl Fl dump-video Ar file
|
||||||
|
Dumps audio and video to the given video file
|
||||||
|
.It Fl f , Fl Fl fullscreen
|
||||||
|
Start in fullscreen mode
|
||||||
.It Fl h , Fl Fl help
|
.It Fl h , Fl Fl help
|
||||||
Shows syntax help and exits
|
Shows syntax help and exits
|
||||||
.It Fl v , Fl Fl version
|
.It Fl v , Fl Fl version
|
||||||
|
2
externals/discord-rpc
vendored
2
externals/discord-rpc
vendored
@ -1 +1 @@
|
|||||||
Subproject commit 20cc99aeffa08a4834f156b6ab49ed68618cf94a
|
Subproject commit 54eb03c20351f94850bfca3955cb87465a860ef6
|
2
externals/dynarmic
vendored
2
externals/dynarmic
vendored
@ -1 +1 @@
|
|||||||
Subproject commit 30f1a3c6289075ef4af08f5ec502be2fc8627a0c
|
Subproject commit a41c380246d3d9f9874f0f792d234dc0cc17c180
|
2
externals/fmt
vendored
2
externals/fmt
vendored
@ -1 +1 @@
|
|||||||
Subproject commit 2dd4fa8742fdac36468f8d8ea3e06e78215551f8
|
Subproject commit fcd3e1e19c8d2df94bb6cb40d7f1c97a9872cf2b
|
2
externals/library-headers
vendored
2
externals/library-headers
vendored
@ -1 +1 @@
|
|||||||
Subproject commit 3b3e28dbe6d033395ce2967fa8030825e7b89de7
|
Subproject commit 9fb99108ee5c630ca365c8fa4a11087b84e1f58b
|
2
externals/vma
vendored
2
externals/vma
vendored
@ -1 +1 @@
|
|||||||
Subproject commit 0e89587db3ebee4d463f191bd296374c5fafc8ea
|
Subproject commit 009ecd192c1289c7529bff248a16cfe896254816
|
2
externals/vulkan-headers
vendored
2
externals/vulkan-headers
vendored
@ -1 +1 @@
|
|||||||
Subproject commit 5a5c9a643484d888873e32c5d7d484fae8e71d3d
|
Subproject commit 595c8d4794410a4e64b98dc58d27c0310d7ea2fd
|
@ -117,7 +117,7 @@ else()
|
|||||||
|
|
||||||
if (NOT CMAKE_BUILD_TYPE STREQUAL Debug)
|
if (NOT CMAKE_BUILD_TYPE STREQUAL Debug)
|
||||||
# _FORTIFY_SOURCE can't be used without optimizations.
|
# _FORTIFY_SOURCE can't be used without optimizations.
|
||||||
add_compile_options(-Wp,-D_FORTIFY_SOURCE=2)
|
add_compile_options(-U_FORTIFY_SOURCE -D_FORTIFY_SOURCE=2)
|
||||||
endif()
|
endif()
|
||||||
|
|
||||||
if (CITRA_WARNINGS_AS_ERRORS)
|
if (CITRA_WARNINGS_AS_ERRORS)
|
||||||
|
@ -29,7 +29,7 @@ android {
|
|||||||
namespace = "org.citra.citra_emu"
|
namespace = "org.citra.citra_emu"
|
||||||
|
|
||||||
compileSdkVersion = "android-34"
|
compileSdkVersion = "android-34"
|
||||||
ndkVersion = "26.1.10909125"
|
ndkVersion = "26.3.11579264"
|
||||||
|
|
||||||
compileOptions {
|
compileOptions {
|
||||||
sourceCompatibility = JavaVersion.VERSION_17
|
sourceCompatibility = JavaVersion.VERSION_17
|
||||||
|
@ -527,12 +527,28 @@ object NativeLibrary {
|
|||||||
|
|
||||||
external fun removeAmiibo()
|
external fun removeAmiibo()
|
||||||
|
|
||||||
const val SAVESTATE_SLOT_COUNT = 10
|
const val SAVESTATE_SLOT_COUNT = 11
|
||||||
|
const val QUICKSAVE_SLOT = 0
|
||||||
|
|
||||||
external fun getSavestateInfo(): Array<SaveStateInfo>?
|
external fun getSavestateInfo(): Array<SaveStateInfo>?
|
||||||
|
|
||||||
external fun saveState(slot: Int)
|
external fun saveState(slot: Int)
|
||||||
|
|
||||||
|
fun loadStateIfAvailable(slot: Int): Boolean {
|
||||||
|
var available = false
|
||||||
|
getSavestateInfo()?.forEach {
|
||||||
|
if (it.slot == slot){
|
||||||
|
available = true
|
||||||
|
return@forEach
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if (available) {
|
||||||
|
loadState(slot)
|
||||||
|
return true
|
||||||
|
}
|
||||||
|
return false
|
||||||
|
}
|
||||||
|
|
||||||
external fun loadState(slot: Int)
|
external fun loadState(slot: Int)
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
@ -38,7 +38,6 @@ import org.citra.citra_emu.features.settings.model.view.InputBindingSetting
|
|||||||
import org.citra.citra_emu.fragments.MessageDialogFragment
|
import org.citra.citra_emu.fragments.MessageDialogFragment
|
||||||
import org.citra.citra_emu.utils.ControllerMappingHelper
|
import org.citra.citra_emu.utils.ControllerMappingHelper
|
||||||
import org.citra.citra_emu.utils.FileBrowserHelper
|
import org.citra.citra_emu.utils.FileBrowserHelper
|
||||||
import org.citra.citra_emu.utils.ForegroundService
|
|
||||||
import org.citra.citra_emu.utils.EmulationLifecycleUtil
|
import org.citra.citra_emu.utils.EmulationLifecycleUtil
|
||||||
import org.citra.citra_emu.utils.EmulationMenuSettings
|
import org.citra.citra_emu.utils.EmulationMenuSettings
|
||||||
import org.citra.citra_emu.utils.ThemeUtil
|
import org.citra.citra_emu.utils.ThemeUtil
|
||||||
@ -47,7 +46,6 @@ import org.citra.citra_emu.viewmodel.EmulationViewModel
|
|||||||
class EmulationActivity : AppCompatActivity() {
|
class EmulationActivity : AppCompatActivity() {
|
||||||
private val preferences: SharedPreferences
|
private val preferences: SharedPreferences
|
||||||
get() = PreferenceManager.getDefaultSharedPreferences(CitraApplication.appContext)
|
get() = PreferenceManager.getDefaultSharedPreferences(CitraApplication.appContext)
|
||||||
private var foregroundService: Intent? = null
|
|
||||||
var isActivityRecreated = false
|
var isActivityRecreated = false
|
||||||
|
|
||||||
private val settingsViewModel: SettingsViewModel by viewModels()
|
private val settingsViewModel: SettingsViewModel by viewModels()
|
||||||
@ -66,7 +64,7 @@ class EmulationActivity : AppCompatActivity() {
|
|||||||
|
|
||||||
binding = ActivityEmulationBinding.inflate(layoutInflater)
|
binding = ActivityEmulationBinding.inflate(layoutInflater)
|
||||||
screenAdjustmentUtil = ScreenAdjustmentUtil(windowManager, settingsViewModel.settings)
|
screenAdjustmentUtil = ScreenAdjustmentUtil(windowManager, settingsViewModel.settings)
|
||||||
hotkeyUtility = HotkeyUtility(screenAdjustmentUtil)
|
hotkeyUtility = HotkeyUtility(screenAdjustmentUtil, this)
|
||||||
setContentView(binding.root)
|
setContentView(binding.root)
|
||||||
|
|
||||||
val navHostFragment =
|
val navHostFragment =
|
||||||
@ -85,10 +83,6 @@ class EmulationActivity : AppCompatActivity() {
|
|||||||
windowManager.defaultDisplay.rotation
|
windowManager.defaultDisplay.rotation
|
||||||
)
|
)
|
||||||
|
|
||||||
// Start a foreground service to prevent the app from getting killed in the background
|
|
||||||
foregroundService = Intent(this, ForegroundService::class.java)
|
|
||||||
startForegroundService(foregroundService)
|
|
||||||
|
|
||||||
EmulationLifecycleUtil.addShutdownHook(hook = { this.finish() })
|
EmulationLifecycleUtil.addShutdownHook(hook = { this.finish() })
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -112,7 +106,6 @@ class EmulationActivity : AppCompatActivity() {
|
|||||||
|
|
||||||
override fun onDestroy() {
|
override fun onDestroy() {
|
||||||
EmulationLifecycleUtil.clear()
|
EmulationLifecycleUtil.clear()
|
||||||
stopForegroundService(this)
|
|
||||||
super.onDestroy()
|
super.onDestroy()
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -186,8 +179,7 @@ class EmulationActivity : AppCompatActivity() {
|
|||||||
return false
|
return false
|
||||||
}
|
}
|
||||||
|
|
||||||
val button =
|
val button = preferences.getInt(InputBindingSetting.getInputButtonKey(event), event.scanCode)
|
||||||
preferences.getInt(InputBindingSetting.getInputButtonKey(event.keyCode), event.keyCode)
|
|
||||||
val action: Int = when (event.action) {
|
val action: Int = when (event.action) {
|
||||||
KeyEvent.ACTION_DOWN -> {
|
KeyEvent.ACTION_DOWN -> {
|
||||||
// On some devices, the back gesture / button press is not intercepted by androidx
|
// On some devices, the back gesture / button press is not intercepted by androidx
|
||||||
@ -453,12 +445,4 @@ class EmulationActivity : AppCompatActivity() {
|
|||||||
|
|
||||||
OnFilePickerResult(result.toString())
|
OnFilePickerResult(result.toString())
|
||||||
}
|
}
|
||||||
|
|
||||||
companion object {
|
|
||||||
fun stopForegroundService(activity: Activity) {
|
|
||||||
val startIntent = Intent(activity, ForegroundService::class.java)
|
|
||||||
startIntent.action = ForegroundService.ACTION_STOP
|
|
||||||
activity.startForegroundService(startIntent)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
@ -153,9 +153,15 @@ class GameAdapter(private val activity: AppCompatActivity) :
|
|||||||
} else {
|
} else {
|
||||||
View.VISIBLE
|
View.VISIBLE
|
||||||
}
|
}
|
||||||
|
binding.textGameId.visibility = if (game.titleId == 0L) {
|
||||||
|
View.GONE
|
||||||
|
} else {
|
||||||
|
View.VISIBLE
|
||||||
|
}
|
||||||
|
|
||||||
binding.textGameTitle.text = game.title
|
binding.textGameTitle.text = game.title
|
||||||
binding.textCompany.text = game.company
|
binding.textCompany.text = game.company
|
||||||
|
binding.textGameId.text = String.format("ID: %016X", game.titleId)
|
||||||
binding.textFilename.text = game.filename
|
binding.textFilename.text = game.filename
|
||||||
|
|
||||||
val backgroundColorId =
|
val backgroundColorId =
|
||||||
@ -181,6 +187,9 @@ class GameAdapter(private val activity: AppCompatActivity) :
|
|||||||
binding.textCompany.ellipsize = TextUtils.TruncateAt.MARQUEE
|
binding.textCompany.ellipsize = TextUtils.TruncateAt.MARQUEE
|
||||||
binding.textCompany.isSelected = true
|
binding.textCompany.isSelected = true
|
||||||
|
|
||||||
|
binding.textGameId.ellipsize = TextUtils.TruncateAt.MARQUEE
|
||||||
|
binding.textGameId.isSelected = true
|
||||||
|
|
||||||
binding.textFilename.ellipsize = TextUtils.TruncateAt.MARQUEE
|
binding.textFilename.ellipsize = TextUtils.TruncateAt.MARQUEE
|
||||||
binding.textFilename.isSelected = true
|
binding.textFilename.isSelected = true
|
||||||
},
|
},
|
||||||
|
@ -8,5 +8,7 @@ enum class Hotkey(val button: Int) {
|
|||||||
SWAP_SCREEN(10001),
|
SWAP_SCREEN(10001),
|
||||||
CYCLE_LAYOUT(10002),
|
CYCLE_LAYOUT(10002),
|
||||||
CLOSE_GAME(10003),
|
CLOSE_GAME(10003),
|
||||||
PAUSE_OR_RESUME(10004);
|
PAUSE_OR_RESUME(10004),
|
||||||
|
QUICKSAVE(10005),
|
||||||
|
QUICKLOAD(10006);
|
||||||
}
|
}
|
||||||
|
@ -4,10 +4,14 @@
|
|||||||
|
|
||||||
package org.citra.citra_emu.features.hotkeys
|
package org.citra.citra_emu.features.hotkeys
|
||||||
|
|
||||||
|
import android.content.Context
|
||||||
|
import android.widget.Toast
|
||||||
|
import org.citra.citra_emu.NativeLibrary
|
||||||
|
import org.citra.citra_emu.R
|
||||||
import org.citra.citra_emu.utils.EmulationLifecycleUtil
|
import org.citra.citra_emu.utils.EmulationLifecycleUtil
|
||||||
import org.citra.citra_emu.display.ScreenAdjustmentUtil
|
import org.citra.citra_emu.display.ScreenAdjustmentUtil
|
||||||
|
|
||||||
class HotkeyUtility(private val screenAdjustmentUtil: ScreenAdjustmentUtil) {
|
class HotkeyUtility(private val screenAdjustmentUtil: ScreenAdjustmentUtil, private val context: Context) {
|
||||||
|
|
||||||
val hotkeyButtons = Hotkey.entries.map { it.button }
|
val hotkeyButtons = Hotkey.entries.map { it.button }
|
||||||
|
|
||||||
@ -18,6 +22,23 @@ class HotkeyUtility(private val screenAdjustmentUtil: ScreenAdjustmentUtil) {
|
|||||||
Hotkey.CYCLE_LAYOUT.button -> screenAdjustmentUtil.cycleLayouts()
|
Hotkey.CYCLE_LAYOUT.button -> screenAdjustmentUtil.cycleLayouts()
|
||||||
Hotkey.CLOSE_GAME.button -> EmulationLifecycleUtil.closeGame()
|
Hotkey.CLOSE_GAME.button -> EmulationLifecycleUtil.closeGame()
|
||||||
Hotkey.PAUSE_OR_RESUME.button -> EmulationLifecycleUtil.pauseOrResume()
|
Hotkey.PAUSE_OR_RESUME.button -> EmulationLifecycleUtil.pauseOrResume()
|
||||||
|
Hotkey.QUICKSAVE.button -> {
|
||||||
|
NativeLibrary.saveState(NativeLibrary.QUICKSAVE_SLOT)
|
||||||
|
Toast.makeText(context,
|
||||||
|
context.getString(R.string.quicksave_saving),
|
||||||
|
Toast.LENGTH_SHORT).show()
|
||||||
|
}
|
||||||
|
Hotkey.QUICKLOAD.button -> {
|
||||||
|
val wasLoaded = NativeLibrary.loadStateIfAvailable(NativeLibrary.QUICKSAVE_SLOT)
|
||||||
|
val stringRes = if(wasLoaded) {
|
||||||
|
R.string.quickload_loading
|
||||||
|
} else {
|
||||||
|
R.string.quickload_not_found
|
||||||
|
}
|
||||||
|
Toast.makeText(context,
|
||||||
|
context.getString(stringRes),
|
||||||
|
Toast.LENGTH_SHORT).show()
|
||||||
|
}
|
||||||
else -> {}
|
else -> {}
|
||||||
}
|
}
|
||||||
return true
|
return true
|
||||||
|
@ -13,7 +13,8 @@ enum class BooleanSetting(
|
|||||||
ASYNC_SHADERS("async_shader_compilation", Settings.SECTION_RENDERER, false),
|
ASYNC_SHADERS("async_shader_compilation", Settings.SECTION_RENDERER, false),
|
||||||
PLUGIN_LOADER("plugin_loader", Settings.SECTION_SYSTEM, false),
|
PLUGIN_LOADER("plugin_loader", Settings.SECTION_SYSTEM, false),
|
||||||
ALLOW_PLUGIN_LOADER("allow_plugin_loader", Settings.SECTION_SYSTEM, true),
|
ALLOW_PLUGIN_LOADER("allow_plugin_loader", Settings.SECTION_SYSTEM, true),
|
||||||
SWAP_SCREEN("swap_screen", Settings.SECTION_LAYOUT, false);
|
SWAP_SCREEN("swap_screen", Settings.SECTION_LAYOUT, false),
|
||||||
|
INSTANT_DEBUG_LOG("instant_debug_log", Settings.SECTION_DEBUG, false);
|
||||||
|
|
||||||
override var boolean: Boolean = defaultValue
|
override var boolean: Boolean = defaultValue
|
||||||
|
|
||||||
@ -33,7 +34,8 @@ enum class BooleanSetting(
|
|||||||
companion object {
|
companion object {
|
||||||
private val NOT_RUNTIME_EDITABLE = listOf(
|
private val NOT_RUNTIME_EDITABLE = listOf(
|
||||||
PLUGIN_LOADER,
|
PLUGIN_LOADER,
|
||||||
ALLOW_PLUGIN_LOADER
|
ALLOW_PLUGIN_LOADER,
|
||||||
|
ASYNC_SHADERS
|
||||||
)
|
)
|
||||||
|
|
||||||
fun from(key: String): BooleanSetting? =
|
fun from(key: String): BooleanSetting? =
|
||||||
|
@ -19,6 +19,7 @@ enum class IntSetting(
|
|||||||
RESOLUTION_FACTOR("resolution_factor", Settings.SECTION_RENDERER, 1),
|
RESOLUTION_FACTOR("resolution_factor", Settings.SECTION_RENDERER, 1),
|
||||||
STEREOSCOPIC_3D_MODE("render_3d", Settings.SECTION_RENDERER, 0),
|
STEREOSCOPIC_3D_MODE("render_3d", Settings.SECTION_RENDERER, 0),
|
||||||
STEREOSCOPIC_3D_DEPTH("factor_3d", Settings.SECTION_RENDERER, 0),
|
STEREOSCOPIC_3D_DEPTH("factor_3d", Settings.SECTION_RENDERER, 0),
|
||||||
|
STEPS_PER_HOUR("steps_per_hour", Settings.SECTION_SYSTEM, 0),
|
||||||
CARDBOARD_SCREEN_SIZE("cardboard_screen_size", Settings.SECTION_LAYOUT, 85),
|
CARDBOARD_SCREEN_SIZE("cardboard_screen_size", Settings.SECTION_LAYOUT, 85),
|
||||||
CARDBOARD_X_SHIFT("cardboard_x_shift", Settings.SECTION_LAYOUT, 0),
|
CARDBOARD_X_SHIFT("cardboard_x_shift", Settings.SECTION_LAYOUT, 0),
|
||||||
CARDBOARD_Y_SHIFT("cardboard_y_shift", Settings.SECTION_LAYOUT, 0),
|
CARDBOARD_Y_SHIFT("cardboard_y_shift", Settings.SECTION_LAYOUT, 0),
|
||||||
@ -40,7 +41,9 @@ enum class IntSetting(
|
|||||||
VSYNC("use_vsync_new", Settings.SECTION_RENDERER, 1),
|
VSYNC("use_vsync_new", Settings.SECTION_RENDERER, 1),
|
||||||
DEBUG_RENDERER("renderer_debug", Settings.SECTION_DEBUG, 0),
|
DEBUG_RENDERER("renderer_debug", Settings.SECTION_DEBUG, 0),
|
||||||
TEXTURE_FILTER("texture_filter", Settings.SECTION_RENDERER, 0),
|
TEXTURE_FILTER("texture_filter", Settings.SECTION_RENDERER, 0),
|
||||||
USE_FRAME_LIMIT("use_frame_limit", Settings.SECTION_RENDERER, 1);
|
USE_FRAME_LIMIT("use_frame_limit", Settings.SECTION_RENDERER, 1),
|
||||||
|
DELAY_RENDER_THREAD_US("delay_game_render_thread_us", Settings.SECTION_RENDERER, 0),
|
||||||
|
USE_ARTIC_BASE_CONTROLLER("use_artic_base_controller", Settings.SECTION_CONTROLS, 0);
|
||||||
|
|
||||||
override var int: Int = defaultValue
|
override var int: Int = defaultValue
|
||||||
|
|
||||||
@ -68,7 +71,8 @@ enum class IntSetting(
|
|||||||
DEBUG_RENDERER,
|
DEBUG_RENDERER,
|
||||||
CPU_JIT,
|
CPU_JIT,
|
||||||
ASYNC_CUSTOM_LOADING,
|
ASYNC_CUSTOM_LOADING,
|
||||||
AUDIO_INPUT_TYPE
|
AUDIO_INPUT_TYPE,
|
||||||
|
USE_ARTIC_BASE_CONTROLLER
|
||||||
)
|
)
|
||||||
|
|
||||||
fun from(key: String): IntSetting? = IntSetting.values().firstOrNull { it.key == key }
|
fun from(key: String): IntSetting? = IntSetting.values().firstOrNull { it.key == key }
|
||||||
|
@ -136,6 +136,8 @@ class Settings {
|
|||||||
const val HOTKEY_CYCLE_LAYOUT = "hotkey_toggle_layout"
|
const val HOTKEY_CYCLE_LAYOUT = "hotkey_toggle_layout"
|
||||||
const val HOTKEY_CLOSE_GAME = "hotkey_close_game"
|
const val HOTKEY_CLOSE_GAME = "hotkey_close_game"
|
||||||
const val HOTKEY_PAUSE_OR_RESUME = "hotkey_pause_or_resume_game"
|
const val HOTKEY_PAUSE_OR_RESUME = "hotkey_pause_or_resume_game"
|
||||||
|
const val HOTKEY_QUICKSAVE = "hotkey_quickload"
|
||||||
|
const val HOTKEY_QUICKlOAD = "hotkey_quickpause"
|
||||||
|
|
||||||
val buttonKeys = listOf(
|
val buttonKeys = listOf(
|
||||||
KEY_BUTTON_A,
|
KEY_BUTTON_A,
|
||||||
@ -163,14 +165,28 @@ class Settings {
|
|||||||
KEY_CSTICK_AXIS_VERTICAL,
|
KEY_CSTICK_AXIS_VERTICAL,
|
||||||
KEY_CSTICK_AXIS_HORIZONTAL
|
KEY_CSTICK_AXIS_HORIZONTAL
|
||||||
)
|
)
|
||||||
val dPadKeys = listOf(
|
val dPadAxisKeys = listOf(
|
||||||
KEY_DPAD_AXIS_VERTICAL,
|
KEY_DPAD_AXIS_VERTICAL,
|
||||||
KEY_DPAD_AXIS_HORIZONTAL
|
KEY_DPAD_AXIS_HORIZONTAL
|
||||||
)
|
)
|
||||||
|
val dPadButtonKeys = listOf(
|
||||||
|
KEY_BUTTON_UP,
|
||||||
|
KEY_BUTTON_DOWN,
|
||||||
|
KEY_BUTTON_LEFT,
|
||||||
|
KEY_BUTTON_RIGHT
|
||||||
|
)
|
||||||
val axisTitles = listOf(
|
val axisTitles = listOf(
|
||||||
R.string.controller_axis_vertical,
|
R.string.controller_axis_vertical,
|
||||||
R.string.controller_axis_horizontal
|
R.string.controller_axis_horizontal
|
||||||
)
|
)
|
||||||
|
|
||||||
|
val dPadTitles = listOf(
|
||||||
|
R.string.direction_up,
|
||||||
|
R.string.direction_down,
|
||||||
|
R.string.direction_left,
|
||||||
|
R.string.direction_right,
|
||||||
|
)
|
||||||
|
|
||||||
val triggerKeys = listOf(
|
val triggerKeys = listOf(
|
||||||
KEY_BUTTON_L,
|
KEY_BUTTON_L,
|
||||||
KEY_BUTTON_R,
|
KEY_BUTTON_R,
|
||||||
@ -187,13 +203,17 @@ class Settings {
|
|||||||
HOTKEY_SCREEN_SWAP,
|
HOTKEY_SCREEN_SWAP,
|
||||||
HOTKEY_CYCLE_LAYOUT,
|
HOTKEY_CYCLE_LAYOUT,
|
||||||
HOTKEY_CLOSE_GAME,
|
HOTKEY_CLOSE_GAME,
|
||||||
HOTKEY_PAUSE_OR_RESUME
|
HOTKEY_PAUSE_OR_RESUME,
|
||||||
|
HOTKEY_QUICKSAVE,
|
||||||
|
HOTKEY_QUICKlOAD
|
||||||
)
|
)
|
||||||
val hotkeyTitles = listOf(
|
val hotkeyTitles = listOf(
|
||||||
R.string.emulation_swap_screens,
|
R.string.emulation_swap_screens,
|
||||||
R.string.emulation_cycle_landscape_layouts,
|
R.string.emulation_cycle_landscape_layouts,
|
||||||
R.string.emulation_close_game,
|
R.string.emulation_close_game,
|
||||||
R.string.emulation_toggle_pause
|
R.string.emulation_toggle_pause,
|
||||||
|
R.string.emulation_quicksave,
|
||||||
|
R.string.emulation_quickload,
|
||||||
)
|
)
|
||||||
|
|
||||||
const val PREF_FIRST_APP_LAUNCH = "FirstApplicationLaunch"
|
const val PREF_FIRST_APP_LAUNCH = "FirstApplicationLaunch"
|
||||||
|
@ -4,6 +4,6 @@
|
|||||||
|
|
||||||
package org.citra.citra_emu.features.settings.model.view
|
package org.citra.citra_emu.features.settings.model.view
|
||||||
|
|
||||||
class HeaderSetting(titleId: Int) : SettingsItem(null, titleId, 0) {
|
class HeaderSetting(titleId: Int,descId: Int = 0) : SettingsItem(null, titleId, descId) {
|
||||||
override val type = TYPE_HEADER
|
override val type = TYPE_HEADER
|
||||||
}
|
}
|
||||||
|
@ -78,7 +78,6 @@ class InputBindingSetting(
|
|||||||
|
|
||||||
else -> false
|
else -> false
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Returns true if this key is for the 3DS L/R or ZL/ZR buttons. Note, these are not real
|
* Returns true if this key is for the 3DS L/R or ZL/ZR buttons. Note, these are not real
|
||||||
* triggers on the 3DS, but we support them as such on a physical gamepad.
|
* triggers on the 3DS, but we support them as such on a physical gamepad.
|
||||||
@ -128,11 +127,12 @@ class InputBindingSetting(
|
|||||||
Settings.KEY_BUTTON_DOWN -> NativeLibrary.ButtonType.DPAD_DOWN
|
Settings.KEY_BUTTON_DOWN -> NativeLibrary.ButtonType.DPAD_DOWN
|
||||||
Settings.KEY_BUTTON_LEFT -> NativeLibrary.ButtonType.DPAD_LEFT
|
Settings.KEY_BUTTON_LEFT -> NativeLibrary.ButtonType.DPAD_LEFT
|
||||||
Settings.KEY_BUTTON_RIGHT -> NativeLibrary.ButtonType.DPAD_RIGHT
|
Settings.KEY_BUTTON_RIGHT -> NativeLibrary.ButtonType.DPAD_RIGHT
|
||||||
|
|
||||||
Settings.HOTKEY_SCREEN_SWAP -> Hotkey.SWAP_SCREEN.button
|
Settings.HOTKEY_SCREEN_SWAP -> Hotkey.SWAP_SCREEN.button
|
||||||
Settings.HOTKEY_CYCLE_LAYOUT -> Hotkey.CYCLE_LAYOUT.button
|
Settings.HOTKEY_CYCLE_LAYOUT -> Hotkey.CYCLE_LAYOUT.button
|
||||||
Settings.HOTKEY_CLOSE_GAME -> Hotkey.CLOSE_GAME.button
|
Settings.HOTKEY_CLOSE_GAME -> Hotkey.CLOSE_GAME.button
|
||||||
Settings.HOTKEY_PAUSE_OR_RESUME -> Hotkey.PAUSE_OR_RESUME.button
|
Settings.HOTKEY_PAUSE_OR_RESUME -> Hotkey.PAUSE_OR_RESUME.button
|
||||||
|
Settings.HOTKEY_QUICKSAVE -> Hotkey.QUICKSAVE.button
|
||||||
|
Settings.HOTKEY_QUICKlOAD -> Hotkey.QUICKLOAD.button
|
||||||
else -> -1
|
else -> -1
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -222,8 +222,10 @@ class InputBindingSetting(
|
|||||||
Toast.makeText(context, R.string.input_message_analog_only, Toast.LENGTH_LONG).show()
|
Toast.makeText(context, R.string.input_message_analog_only, Toast.LENGTH_LONG).show()
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
writeButtonMapping(getInputButtonKey(keyEvent.keyCode))
|
|
||||||
val uiString = "${keyEvent.device.name}: Button ${keyEvent.keyCode}"
|
val code = translateEventToKeyId(keyEvent)
|
||||||
|
writeButtonMapping(getInputButtonKey(code))
|
||||||
|
val uiString = "${keyEvent.device.name}: Button $code"
|
||||||
value = uiString
|
value = uiString
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -283,9 +285,17 @@ class InputBindingSetting(
|
|||||||
|
|
||||||
/**
|
/**
|
||||||
* Helper function to get the settings key for an gamepad button.
|
* Helper function to get the settings key for an gamepad button.
|
||||||
|
*
|
||||||
*/
|
*/
|
||||||
|
@Deprecated("Use the new getInputButtonKey(keyEvent) method to handle unknown keys")
|
||||||
fun getInputButtonKey(keyCode: Int): String = "${INPUT_MAPPING_PREFIX}_HostAxis_${keyCode}"
|
fun getInputButtonKey(keyCode: Int): String = "${INPUT_MAPPING_PREFIX}_HostAxis_${keyCode}"
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Helper function to get the settings key for an gamepad button.
|
||||||
|
*
|
||||||
|
*/
|
||||||
|
fun getInputButtonKey(event: KeyEvent): String = "${INPUT_MAPPING_PREFIX}_HostAxis_${translateEventToKeyId(event)}"
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Helper function to get the settings key for an gamepad axis.
|
* Helper function to get the settings key for an gamepad axis.
|
||||||
*/
|
*/
|
||||||
@ -301,5 +311,23 @@ class InputBindingSetting(
|
|||||||
*/
|
*/
|
||||||
fun getInputAxisOrientationKey(axis: Int): String =
|
fun getInputAxisOrientationKey(axis: Int): String =
|
||||||
"${getInputAxisKey(axis)}_GuestOrientation"
|
"${getInputAxisKey(axis)}_GuestOrientation"
|
||||||
|
|
||||||
|
|
||||||
|
/**
|
||||||
|
* This function translates a keyEvent into an "keyid"
|
||||||
|
* This key id is either the keyCode from the event, or
|
||||||
|
* the raw scanCode.
|
||||||
|
* Only when the keyCode itself is 0, (so it is an unknown key)
|
||||||
|
* we fall back to the raw scan code.
|
||||||
|
* This handles keys like the media-keys on google statia-controllers
|
||||||
|
* that don't have a conventional "mapping" and report as "unknown"
|
||||||
|
*/
|
||||||
|
fun translateEventToKeyId(event: KeyEvent): Int {
|
||||||
|
return if (event.keyCode == 0) {
|
||||||
|
event.scanCode
|
||||||
|
} else {
|
||||||
|
event.keyCode
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -191,7 +191,7 @@ class SettingsActivity : AppCompatActivity(), SettingsActivityView {
|
|||||||
presenter.onSettingsReset()
|
presenter.onSettingsReset()
|
||||||
|
|
||||||
val controllerKeys = Settings.buttonKeys + Settings.circlePadKeys + Settings.cStickKeys +
|
val controllerKeys = Settings.buttonKeys + Settings.circlePadKeys + Settings.cStickKeys +
|
||||||
Settings.dPadKeys + Settings.triggerKeys
|
Settings.dPadButtonKeys + Settings.dPadAxisKeys + Settings.triggerKeys
|
||||||
val editor =
|
val editor =
|
||||||
PreferenceManager.getDefaultSharedPreferences(CitraApplication.appContext).edit()
|
PreferenceManager.getDefaultSharedPreferences(CitraApplication.appContext).edit()
|
||||||
controllerKeys.forEach { editor.remove(it) }
|
controllerKeys.forEach { editor.remove(it) }
|
||||||
|
@ -298,6 +298,18 @@ class SettingsFragmentPresenter(private val fragmentView: SettingsFragmentView)
|
|||||||
""
|
""
|
||||||
)
|
)
|
||||||
)
|
)
|
||||||
|
add(
|
||||||
|
SliderSetting(
|
||||||
|
IntSetting.STEPS_PER_HOUR,
|
||||||
|
R.string.steps_per_hour,
|
||||||
|
R.string.steps_per_hour_description,
|
||||||
|
0,
|
||||||
|
65535,
|
||||||
|
" steps",
|
||||||
|
IntSetting.STEPS_PER_HOUR.key,
|
||||||
|
IntSetting.STEPS_PER_HOUR.defaultValue.toFloat()
|
||||||
|
)
|
||||||
|
)
|
||||||
add(
|
add(
|
||||||
RunnableSetting(
|
RunnableSetting(
|
||||||
R.string.console_id,
|
R.string.console_id,
|
||||||
@ -609,11 +621,16 @@ class SettingsFragmentPresenter(private val fragmentView: SettingsFragmentView)
|
|||||||
add(InputBindingSetting(button, Settings.axisTitles[i]))
|
add(InputBindingSetting(button, Settings.axisTitles[i]))
|
||||||
}
|
}
|
||||||
|
|
||||||
add(HeaderSetting(R.string.controller_dpad))
|
add(HeaderSetting(R.string.controller_dpad_axis,R.string.controller_dpad_axis_description))
|
||||||
Settings.dPadKeys.forEachIndexed { i: Int, key: String ->
|
Settings.dPadAxisKeys.forEachIndexed { i: Int, key: String ->
|
||||||
val button = getInputObject(key)
|
val button = getInputObject(key)
|
||||||
add(InputBindingSetting(button, Settings.axisTitles[i]))
|
add(InputBindingSetting(button, Settings.axisTitles[i]))
|
||||||
}
|
}
|
||||||
|
add(HeaderSetting(R.string.controller_dpad_button,R.string.controller_dpad_button_description))
|
||||||
|
Settings.dPadButtonKeys.forEachIndexed { i: Int, key: String ->
|
||||||
|
val button = getInputObject(key)
|
||||||
|
add(InputBindingSetting(button, Settings.dPadTitles[i]))
|
||||||
|
}
|
||||||
|
|
||||||
add(HeaderSetting(R.string.controller_triggers))
|
add(HeaderSetting(R.string.controller_triggers))
|
||||||
Settings.triggerKeys.forEachIndexed { i: Int, key: String ->
|
Settings.triggerKeys.forEachIndexed { i: Int, key: String ->
|
||||||
@ -626,6 +643,16 @@ class SettingsFragmentPresenter(private val fragmentView: SettingsFragmentView)
|
|||||||
val button = getInputObject(key)
|
val button = getInputObject(key)
|
||||||
add(InputBindingSetting(button, Settings.hotkeyTitles[i]))
|
add(InputBindingSetting(button, Settings.hotkeyTitles[i]))
|
||||||
}
|
}
|
||||||
|
add(HeaderSetting(R.string.miscellaneous))
|
||||||
|
add(
|
||||||
|
SwitchSetting(
|
||||||
|
IntSetting.USE_ARTIC_BASE_CONTROLLER,
|
||||||
|
R.string.use_artic_base_controller,
|
||||||
|
R.string.use_artic_base_controller_desc,
|
||||||
|
IntSetting.USE_ARTIC_BASE_CONTROLLER.key,
|
||||||
|
IntSetting.USE_ARTIC_BASE_CONTROLLER.defaultValue
|
||||||
|
)
|
||||||
|
)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -729,6 +756,18 @@ class SettingsFragmentPresenter(private val fragmentView: SettingsFragmentView)
|
|||||||
IntSetting.TEXTURE_FILTER.defaultValue
|
IntSetting.TEXTURE_FILTER.defaultValue
|
||||||
)
|
)
|
||||||
)
|
)
|
||||||
|
add(
|
||||||
|
SliderSetting(
|
||||||
|
IntSetting.DELAY_RENDER_THREAD_US,
|
||||||
|
R.string.delay_render_thread,
|
||||||
|
R.string.delay_render_thread_description,
|
||||||
|
0,
|
||||||
|
16000,
|
||||||
|
" μs",
|
||||||
|
IntSetting.DELAY_RENDER_THREAD_US.key,
|
||||||
|
IntSetting.DELAY_RENDER_THREAD_US.defaultValue.toFloat()
|
||||||
|
)
|
||||||
|
)
|
||||||
|
|
||||||
add(HeaderSetting(R.string.stereoscopy))
|
add(HeaderSetting(R.string.stereoscopy))
|
||||||
add(
|
add(
|
||||||
@ -964,6 +1003,15 @@ class SettingsFragmentPresenter(private val fragmentView: SettingsFragmentView)
|
|||||||
IntSetting.DEBUG_RENDERER.defaultValue
|
IntSetting.DEBUG_RENDERER.defaultValue
|
||||||
)
|
)
|
||||||
)
|
)
|
||||||
|
add(
|
||||||
|
SwitchSetting(
|
||||||
|
BooleanSetting.INSTANT_DEBUG_LOG,
|
||||||
|
R.string.instant_debug_log,
|
||||||
|
R.string.instant_debug_log_desc,
|
||||||
|
BooleanSetting.INSTANT_DEBUG_LOG.key,
|
||||||
|
BooleanSetting.INSTANT_DEBUG_LOG.defaultValue
|
||||||
|
)
|
||||||
|
)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -18,6 +18,12 @@ class HeaderViewHolder(val binding: ListItemSettingsHeaderBinding, adapter: Sett
|
|||||||
|
|
||||||
override fun bind(item: SettingsItem) {
|
override fun bind(item: SettingsItem) {
|
||||||
binding.textHeaderName.setText(item.nameId)
|
binding.textHeaderName.setText(item.nameId)
|
||||||
|
if (item.descriptionId != 0) {
|
||||||
|
binding.textHeaderDescription.visibility = View.VISIBLE
|
||||||
|
binding.textHeaderDescription.setText(item.descriptionId)
|
||||||
|
}else {
|
||||||
|
binding.textHeaderDescription.visibility = View.GONE
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
override fun onClick(clicked: View) {
|
override fun onClick(clicked: View) {
|
||||||
|
@ -481,12 +481,12 @@ class EmulationFragment : Fragment(), SurfaceHolder.Callback, Choreographer.Fram
|
|||||||
popupMenu.setOnMenuItemClickListener {
|
popupMenu.setOnMenuItemClickListener {
|
||||||
when (it.itemId) {
|
when (it.itemId) {
|
||||||
R.id.menu_emulation_save_state -> {
|
R.id.menu_emulation_save_state -> {
|
||||||
showSaveStateSubmenu()
|
showStateSubmenu(true)
|
||||||
true
|
true
|
||||||
}
|
}
|
||||||
|
|
||||||
R.id.menu_emulation_load_state -> {
|
R.id.menu_emulation_load_state -> {
|
||||||
showLoadStateSubmenu()
|
showStateSubmenu(false)
|
||||||
true
|
true
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -497,7 +497,8 @@ class EmulationFragment : Fragment(), SurfaceHolder.Callback, Choreographer.Fram
|
|||||||
popupMenu.show()
|
popupMenu.show()
|
||||||
}
|
}
|
||||||
|
|
||||||
private fun showSaveStateSubmenu() {
|
private fun showStateSubmenu(isSaving: Boolean) {
|
||||||
|
|
||||||
val savestates = NativeLibrary.getSavestateInfo()
|
val savestates = NativeLibrary.getSavestateInfo()
|
||||||
|
|
||||||
val popupMenu = PopupMenu(
|
val popupMenu = PopupMenu(
|
||||||
@ -507,19 +508,40 @@ class EmulationFragment : Fragment(), SurfaceHolder.Callback, Choreographer.Fram
|
|||||||
|
|
||||||
popupMenu.menu.apply {
|
popupMenu.menu.apply {
|
||||||
for (i in 0 until NativeLibrary.SAVESTATE_SLOT_COUNT) {
|
for (i in 0 until NativeLibrary.SAVESTATE_SLOT_COUNT) {
|
||||||
val slot = i + 1
|
val slot = i
|
||||||
val text = getString(R.string.emulation_empty_state_slot, slot)
|
var enableClick = isSaving
|
||||||
add(text).setEnabled(true).setOnMenuItemClickListener {
|
val text = if (slot == NativeLibrary.QUICKSAVE_SLOT) {
|
||||||
displaySavestateWarning()
|
enableClick = false
|
||||||
NativeLibrary.saveState(slot)
|
getString(R.string.emulation_quicksave_slot)
|
||||||
|
} else {
|
||||||
|
getString(R.string.emulation_empty_state_slot, slot)
|
||||||
|
}
|
||||||
|
|
||||||
|
add(text).setEnabled(enableClick).setOnMenuItemClickListener {
|
||||||
|
if(isSaving) {
|
||||||
|
NativeLibrary.saveState(slot)
|
||||||
|
} else {
|
||||||
|
NativeLibrary.loadState(slot)
|
||||||
|
binding.drawerLayout.close()
|
||||||
|
Toast.makeText(context,
|
||||||
|
getString(R.string.quickload_loading),
|
||||||
|
Toast.LENGTH_SHORT).show()
|
||||||
|
}
|
||||||
true
|
true
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
savestates?.forEach {
|
savestates?.forEach {
|
||||||
val text = getString(R.string.emulation_occupied_state_slot, it.slot, it.time)
|
var enableClick = true
|
||||||
popupMenu.menu.getItem(it.slot - 1).setTitle(text)
|
val text = if(it.slot == NativeLibrary.QUICKSAVE_SLOT) {
|
||||||
|
// do not allow saving in quicksave slot
|
||||||
|
enableClick = !isSaving
|
||||||
|
getString(R.string.emulation_occupied_quicksave_slot, it.time)
|
||||||
|
} else{
|
||||||
|
getString(R.string.emulation_occupied_state_slot, it.slot, it.time)
|
||||||
|
}
|
||||||
|
popupMenu.menu.getItem(it.slot).setTitle(text).setEnabled(enableClick)
|
||||||
}
|
}
|
||||||
|
|
||||||
popupMenu.show()
|
popupMenu.show()
|
||||||
|
@ -156,9 +156,6 @@ class MainActivity : AppCompatActivity(), ThemeProvider {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// Dismiss previous notifications (should not happen unless a crash occurred)
|
|
||||||
EmulationActivity.stopForegroundService(this)
|
|
||||||
|
|
||||||
setInsets()
|
setInsets()
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -170,7 +167,6 @@ class MainActivity : AppCompatActivity(), ThemeProvider {
|
|||||||
}
|
}
|
||||||
|
|
||||||
override fun onDestroy() {
|
override fun onDestroy() {
|
||||||
EmulationActivity.stopForegroundService(this)
|
|
||||||
super.onDestroy()
|
super.onDestroy()
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -128,6 +128,8 @@ void Config::ReadValues() {
|
|||||||
static_cast<u16>(sdl2_config->GetInteger("Controls", "udp_input_port",
|
static_cast<u16>(sdl2_config->GetInteger("Controls", "udp_input_port",
|
||||||
InputCommon::CemuhookUDP::DEFAULT_PORT));
|
InputCommon::CemuhookUDP::DEFAULT_PORT));
|
||||||
|
|
||||||
|
ReadSetting("Controls", Settings::values.use_artic_base_controller);
|
||||||
|
|
||||||
// Core
|
// Core
|
||||||
ReadSetting("Core", Settings::values.use_cpu_jit);
|
ReadSetting("Core", Settings::values.use_cpu_jit);
|
||||||
ReadSetting("Core", Settings::values.cpu_clock_percentage);
|
ReadSetting("Core", Settings::values.cpu_clock_percentage);
|
||||||
@ -169,6 +171,7 @@ void Config::ReadValues() {
|
|||||||
ReadSetting("Renderer", Settings::values.bg_red);
|
ReadSetting("Renderer", Settings::values.bg_red);
|
||||||
ReadSetting("Renderer", Settings::values.bg_green);
|
ReadSetting("Renderer", Settings::values.bg_green);
|
||||||
ReadSetting("Renderer", Settings::values.bg_blue);
|
ReadSetting("Renderer", Settings::values.bg_blue);
|
||||||
|
ReadSetting("Renderer", Settings::values.delay_game_render_thread_us);
|
||||||
|
|
||||||
// Layout
|
// Layout
|
||||||
Settings::values.layout_option = static_cast<Settings::LayoutOption>(sdl2_config->GetInteger(
|
Settings::values.layout_option = static_cast<Settings::LayoutOption>(sdl2_config->GetInteger(
|
||||||
@ -220,6 +223,7 @@ void Config::ReadValues() {
|
|||||||
ReadSetting("System", Settings::values.init_ticks_override);
|
ReadSetting("System", Settings::values.init_ticks_override);
|
||||||
ReadSetting("System", Settings::values.plugin_loader_enabled);
|
ReadSetting("System", Settings::values.plugin_loader_enabled);
|
||||||
ReadSetting("System", Settings::values.allow_plugin_loader);
|
ReadSetting("System", Settings::values.allow_plugin_loader);
|
||||||
|
ReadSetting("System", Settings::values.steps_per_hour);
|
||||||
|
|
||||||
// Camera
|
// Camera
|
||||||
using namespace Service::CAM;
|
using namespace Service::CAM;
|
||||||
@ -259,6 +263,7 @@ void Config::ReadValues() {
|
|||||||
ReadSetting("Debugging", Settings::values.renderer_debug);
|
ReadSetting("Debugging", Settings::values.renderer_debug);
|
||||||
ReadSetting("Debugging", Settings::values.use_gdbstub);
|
ReadSetting("Debugging", Settings::values.use_gdbstub);
|
||||||
ReadSetting("Debugging", Settings::values.gdbstub_port);
|
ReadSetting("Debugging", Settings::values.gdbstub_port);
|
||||||
|
ReadSetting("Debugging", Settings::values.instant_debug_log);
|
||||||
|
|
||||||
for (const auto& service_module : Service::service_module_map) {
|
for (const auto& service_module : Service::service_module_map) {
|
||||||
bool use_lle = sdl2_config->GetBoolean("Debugging", "LLE\\" + service_module.name, false);
|
bool use_lle = sdl2_config->GetBoolean("Debugging", "LLE\\" + service_module.name, false);
|
||||||
|
@ -86,6 +86,9 @@ udp_input_port=
|
|||||||
# The pad to request data on. Should be between 0 (Pad 1) and 3 (Pad 4). (Default 0)
|
# The pad to request data on. Should be between 0 (Pad 1) and 3 (Pad 4). (Default 0)
|
||||||
udp_pad_index=
|
udp_pad_index=
|
||||||
|
|
||||||
|
# Use Artic Controller when connected to Artic Base Server. (Default 0)
|
||||||
|
use_artic_base_controller=
|
||||||
|
|
||||||
[Core]
|
[Core]
|
||||||
# Whether to use the Just-In-Time (JIT) compiler for CPU emulation
|
# Whether to use the Just-In-Time (JIT) compiler for CPU emulation
|
||||||
# 0: Interpreter (slow), 1 (default): JIT (fast)
|
# 0: Interpreter (slow), 1 (default): JIT (fast)
|
||||||
@ -175,6 +178,10 @@ anaglyph_shader_name =
|
|||||||
# 0: Nearest, 1 (default): Linear
|
# 0: Nearest, 1 (default): Linear
|
||||||
filter_mode =
|
filter_mode =
|
||||||
|
|
||||||
|
# Delays the game render thread by the specified amount of microseconds
|
||||||
|
# Set to 0 for no delay, only useful in dynamic-fps games to simulate GPU delay.
|
||||||
|
delay_game_render_thread_us =
|
||||||
|
|
||||||
[Layout]
|
[Layout]
|
||||||
# Layout for the screen inside the render window.
|
# Layout for the screen inside the render window.
|
||||||
# 0 (default): Default Top Bottom Screen, 1: Single Screen Only, 2: Large Screen Small Screen, 3: Side by Side
|
# 0 (default): Default Top Bottom Screen, 1: Single Screen Only, 2: Large Screen Small Screen, 3: Side by Side
|
||||||
@ -300,6 +307,10 @@ init_ticks_type =
|
|||||||
# Defaults to 0.
|
# Defaults to 0.
|
||||||
init_ticks_override =
|
init_ticks_override =
|
||||||
|
|
||||||
|
# Number of steps per hour reported by the pedometer. Range from 0 to 65,535.
|
||||||
|
# Defaults to 0.
|
||||||
|
steps_per_hour =
|
||||||
|
|
||||||
# Plugin loader state, if enabled plugins will be loaded from the SD card.
|
# Plugin loader state, if enabled plugins will be loaded from the SD card.
|
||||||
# You can also set if homebrew apps are allowed to enable the plugin loader
|
# You can also set if homebrew apps are allowed to enable the plugin loader
|
||||||
plugin_loader =
|
plugin_loader =
|
||||||
@ -350,6 +361,10 @@ renderer_debug =
|
|||||||
use_gdbstub=false
|
use_gdbstub=false
|
||||||
gdbstub_port=24689
|
gdbstub_port=24689
|
||||||
|
|
||||||
|
# Flush log output on every message
|
||||||
|
# Immediately commits the debug log to file. Use this if citra crashes and the log output is being cut.
|
||||||
|
instant_debug_log =
|
||||||
|
|
||||||
# To LLE a service module add "LLE\<module name>=true"
|
# To LLE a service module add "LLE\<module name>=true"
|
||||||
|
|
||||||
[WebService]
|
[WebService]
|
||||||
|
@ -27,14 +27,18 @@ static void UpdateLandscapeScreenLayout() {
|
|||||||
IDCache::GetNativeLibraryClass(), IDCache::GetLandscapeScreenLayout()));
|
IDCache::GetNativeLibraryClass(), IDCache::GetLandscapeScreenLayout()));
|
||||||
}
|
}
|
||||||
|
|
||||||
void EmuWindow_Android::OnSurfaceChanged(ANativeWindow* surface) {
|
bool EmuWindow_Android::OnSurfaceChanged(ANativeWindow* surface) {
|
||||||
render_window = surface;
|
if (render_window == surface) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
render_window = surface;
|
||||||
window_info.type = Frontend::WindowSystemType::Android;
|
window_info.type = Frontend::WindowSystemType::Android;
|
||||||
window_info.render_surface = surface;
|
window_info.render_surface = surface;
|
||||||
|
|
||||||
StopPresenting();
|
StopPresenting();
|
||||||
OnFramebufferSizeChanged();
|
OnFramebufferSizeChanged();
|
||||||
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
bool EmuWindow_Android::OnTouchEvent(int x, int y, bool pressed) {
|
bool EmuWindow_Android::OnTouchEvent(int x, int y, bool pressed) {
|
||||||
|
@ -17,7 +17,7 @@ public:
|
|||||||
~EmuWindow_Android();
|
~EmuWindow_Android();
|
||||||
|
|
||||||
/// Called by the onSurfaceChanges() method to change the surface
|
/// Called by the onSurfaceChanges() method to change the surface
|
||||||
void OnSurfaceChanged(ANativeWindow* surface);
|
bool OnSurfaceChanged(ANativeWindow* surface);
|
||||||
|
|
||||||
/// Handles touch event that occur.(Touched or released)
|
/// Handles touch event that occur.(Touched or released)
|
||||||
bool OnTouchEvent(int x, int y, bool pressed);
|
bool OnTouchEvent(int x, int y, bool pressed);
|
||||||
|
@ -294,12 +294,13 @@ void Java_org_citra_citra_1emu_NativeLibrary_surfaceChanged(JNIEnv* env,
|
|||||||
jobject surf) {
|
jobject surf) {
|
||||||
s_surf = ANativeWindow_fromSurface(env, surf);
|
s_surf = ANativeWindow_fromSurface(env, surf);
|
||||||
|
|
||||||
|
bool notify = false;
|
||||||
if (window) {
|
if (window) {
|
||||||
window->OnSurfaceChanged(s_surf);
|
notify = window->OnSurfaceChanged(s_surf);
|
||||||
}
|
}
|
||||||
|
|
||||||
auto& system = Core::System::GetInstance();
|
auto& system = Core::System::GetInstance();
|
||||||
if (system.IsPoweredOn()) {
|
if (notify && system.IsPoweredOn()) {
|
||||||
system.GPU().Renderer().NotifySurfaceChanged();
|
system.GPU().Renderer().NotifySurfaceChanged();
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -308,10 +309,12 @@ void Java_org_citra_citra_1emu_NativeLibrary_surfaceChanged(JNIEnv* env,
|
|||||||
|
|
||||||
void Java_org_citra_citra_1emu_NativeLibrary_surfaceDestroyed([[maybe_unused]] JNIEnv* env,
|
void Java_org_citra_citra_1emu_NativeLibrary_surfaceDestroyed([[maybe_unused]] JNIEnv* env,
|
||||||
[[maybe_unused]] jobject obj) {
|
[[maybe_unused]] jobject obj) {
|
||||||
ANativeWindow_release(s_surf);
|
if (s_surf != nullptr) {
|
||||||
s_surf = nullptr;
|
ANativeWindow_release(s_surf);
|
||||||
if (window) {
|
s_surf = nullptr;
|
||||||
window->OnSurfaceChanged(s_surf);
|
if (window) {
|
||||||
|
window->OnSurfaceChanged(s_surf);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -22,8 +22,8 @@
|
|||||||
|
|
||||||
<ImageView
|
<ImageView
|
||||||
android:id="@+id/image_game_screen"
|
android:id="@+id/image_game_screen"
|
||||||
android:layout_width="56dp"
|
android:layout_width="75dp"
|
||||||
android:layout_height="56dp"
|
android:layout_height="75dp"
|
||||||
app:layout_constraintBottom_toBottomOf="parent"
|
app:layout_constraintBottom_toBottomOf="parent"
|
||||||
app:layout_constraintStart_toStartOf="parent"
|
app:layout_constraintStart_toStartOf="parent"
|
||||||
app:layout_constraintTop_toTopOf="parent" />
|
app:layout_constraintTop_toTopOf="parent" />
|
||||||
@ -63,6 +63,18 @@
|
|||||||
android:requiresFadingEdge="horizontal"
|
android:requiresFadingEdge="horizontal"
|
||||||
tools:text="Nintendo" />
|
tools:text="Nintendo" />
|
||||||
|
|
||||||
|
<TextView
|
||||||
|
android:id="@+id/text_game_id"
|
||||||
|
style="@style/TextAppearance.Material3.BodySmall"
|
||||||
|
android:layout_width="match_parent"
|
||||||
|
android:layout_height="wrap_content"
|
||||||
|
android:textAlignment="viewStart"
|
||||||
|
android:singleLine="true"
|
||||||
|
android:marqueeRepeatLimit="marquee_forever"
|
||||||
|
android:ellipsize="none"
|
||||||
|
android:requiresFadingEdge="horizontal"
|
||||||
|
tools:text="0004000000033400" />
|
||||||
|
|
||||||
<TextView
|
<TextView
|
||||||
android:id="@+id/text_filename"
|
android:id="@+id/text_filename"
|
||||||
style="@style/TextAppearance.Material3.BodySmall"
|
style="@style/TextAppearance.Material3.BodySmall"
|
||||||
|
@ -1,16 +1,33 @@
|
|||||||
<?xml version="1.0" encoding="utf-8"?>
|
<?xml version="1.0" encoding="utf-8"?>
|
||||||
<com.google.android.material.textview.MaterialTextView xmlns:android="http://schemas.android.com/apk/res/android"
|
<LinearLayout
|
||||||
|
xmlns:android="http://schemas.android.com/apk/res/android"
|
||||||
|
xmlns:app="http://schemas.android.com/apk/res-auto"
|
||||||
xmlns:tools="http://schemas.android.com/tools"
|
xmlns:tools="http://schemas.android.com/tools"
|
||||||
|
android:layout_width="match_parent"
|
||||||
|
android:layout_height="wrap_content"
|
||||||
|
android:orientation="vertical"
|
||||||
|
android:focusable="false"
|
||||||
|
android:clickable="false"
|
||||||
|
android:paddingVertical="16dp"
|
||||||
|
>
|
||||||
|
|
||||||
|
<com.google.android.material.textview.MaterialTextView
|
||||||
|
|
||||||
android:id="@+id/text_header_name"
|
android:id="@+id/text_header_name"
|
||||||
style="@style/TextAppearance.Material3.TitleSmall"
|
style="@style/TextAppearance.Material3.TitleSmall"
|
||||||
android:layout_width="match_parent"
|
android:layout_width="match_parent"
|
||||||
android:layout_height="wrap_content"
|
android:layout_height="wrap_content"
|
||||||
android:layout_gravity="start|center_vertical"
|
android:layout_gravity="start|center_vertical"
|
||||||
android:paddingHorizontal="@dimen/spacing_large"
|
|
||||||
android:paddingVertical="16dp"
|
|
||||||
android:focusable="false"
|
|
||||||
android:clickable="false"
|
|
||||||
android:textAlignment="viewStart"
|
android:textAlignment="viewStart"
|
||||||
android:textColor="?attr/colorPrimary"
|
android:textColor="?attr/colorPrimary"
|
||||||
android:textStyle="bold"
|
android:textStyle="bold"
|
||||||
tools:text="CPU Settings" />
|
tools:text="CPU Settings" />
|
||||||
|
<com.google.android.material.textview.MaterialTextView
|
||||||
|
android:id="@+id/text_header_description"
|
||||||
|
style="@style/TextAppearance.Material3.BodySmall"
|
||||||
|
android:layout_width="match_parent"
|
||||||
|
android:layout_height="wrap_content"
|
||||||
|
android:layout_marginTop="@dimen/spacing_small"
|
||||||
|
android:textAlignment="viewStart"
|
||||||
|
tools:text="@string/app_disclaimer" />
|
||||||
|
</LinearLayout>
|
@ -663,5 +663,10 @@ Se esperan fallos gráficos temporales cuando ésta esté activado.</string>
|
|||||||
<string name="artic_base_connect">Conectar con Artic Base</string>
|
<string name="artic_base_connect">Conectar con Artic Base</string>
|
||||||
<string name="artic_base_connect_description">Conectar con una consola real que esté ejecutando un servidor Artic Base</string>
|
<string name="artic_base_connect_description">Conectar con una consola real que esté ejecutando un servidor Artic Base</string>
|
||||||
<string name="artic_base_enter_address">Introduce la dirección del servidor Artic Base</string>
|
<string name="artic_base_enter_address">Introduce la dirección del servidor Artic Base</string>
|
||||||
|
<string name="delay_render_thread">Retrasa el hilo de dibujado del juego</string>
|
||||||
|
<string name="delay_render_thread_description">Retrasa el hilo de dibujado del juego cuando envía datos a la GPU. Ayuda con problemas de rendimiento en los (muy pocos) juegos de fps dinámicos.</string>
|
||||||
|
<string name="miscellaneous">Misceláneo</string>
|
||||||
|
<string name="use_artic_base_controller">Usar Artic Controller cuando se está conectado a Artic Base Server</string>
|
||||||
|
<string name="use_artic_base_controller_desc">Usa los controles proporcionados por Artic Base Server cuando esté conectado a él en lugar del dispositivo de entrada configurado.</string>
|
||||||
|
|
||||||
</resources>
|
</resources>
|
||||||
|
@ -108,8 +108,16 @@
|
|||||||
<string name="controller_triggers">Triggers</string>
|
<string name="controller_triggers">Triggers</string>
|
||||||
<string name="controller_trigger">Trigger</string>
|
<string name="controller_trigger">Trigger</string>
|
||||||
<string name="controller_dpad">D-Pad</string>
|
<string name="controller_dpad">D-Pad</string>
|
||||||
|
<string name="controller_dpad_axis">D-Pad (Axis)</string>
|
||||||
|
<string name="controller_dpad_axis_description">Some controllers will not be able to map their dpad as an axis. In that case, use the D-Pad (buttons) section below instead.</string>
|
||||||
|
<string name="controller_dpad_button">D-Pad (Buttons)</string>
|
||||||
|
<string name="controller_dpad_button_description">Only map these buttons if the D-Pad (Axis) settings above do not work with your controller.</string>
|
||||||
<string name="controller_axis_vertical">Up/Down Axis</string>
|
<string name="controller_axis_vertical">Up/Down Axis</string>
|
||||||
<string name="controller_axis_horizontal">Left/Right Axis</string>
|
<string name="controller_axis_horizontal">Left/Right Axis</string>
|
||||||
|
<string name="direction_up">Up</string>
|
||||||
|
<string name="direction_down">Down</string>
|
||||||
|
<string name="direction_left">Left</string>
|
||||||
|
<string name="direction_right">Right</string>
|
||||||
<string name="input_dialog_title">Bind %1$s %2$s</string>
|
<string name="input_dialog_title">Bind %1$s %2$s</string>
|
||||||
<string name="input_dialog_description">Press or move an input.</string>
|
<string name="input_dialog_description">Press or move an input.</string>
|
||||||
<string name="input_binding">Input Binding</string>
|
<string name="input_binding">Input Binding</string>
|
||||||
@ -182,6 +190,8 @@
|
|||||||
<string name="birthday_day">Day</string>
|
<string name="birthday_day">Day</string>
|
||||||
<string name="country">Country</string>
|
<string name="country">Country</string>
|
||||||
<string name="play_coins">Play Coins</string>
|
<string name="play_coins">Play Coins</string>
|
||||||
|
<string name="steps_per_hour">Pedometer Steps per Hour</string>
|
||||||
|
<string name="steps_per_hour_description">Number of steps per hour reported by the pedometer. Range from 0 to 65,535.</string>
|
||||||
<string name="console_id">Console ID</string>
|
<string name="console_id">Console ID</string>
|
||||||
<string name="regenerate_console_id">Regenerate Console ID</string>
|
<string name="regenerate_console_id">Regenerate Console ID</string>
|
||||||
<string name="regenerate_console_id_description">This will replace your current virtual 3DS with a new one. Your current virtual 3DS will not be recoverable. This might have unexpected effects in games. This might fail if you use an outdated config savegame. Continue?</string>
|
<string name="regenerate_console_id_description">This will replace your current virtual 3DS with a new one. Your current virtual 3DS will not be recoverable. This might have unexpected effects in games. This might fail if you use an outdated config savegame. Continue?</string>
|
||||||
@ -689,5 +699,21 @@
|
|||||||
<string name="artic_base_connect_description">Connect to a real console that is running an Artic Base server</string>
|
<string name="artic_base_connect_description">Connect to a real console that is running an Artic Base server</string>
|
||||||
<string name="artic_base_connect">Connect to Artic Base</string>
|
<string name="artic_base_connect">Connect to Artic Base</string>
|
||||||
<string name="artic_base_enter_address">Enter Artic Base server address</string>
|
<string name="artic_base_enter_address">Enter Artic Base server address</string>
|
||||||
|
<string name="delay_render_thread">Delay game render thread</string>
|
||||||
|
<string name="delay_render_thread_description">Delay the game render thread when it submits data to the GPU. Helps with performance issues in the (very few) dynamic-fps games.</string>
|
||||||
|
|
||||||
|
<!-- Quickload&Save-->
|
||||||
|
<string name="emulation_quicksave_slot">Quicksave</string>
|
||||||
|
<string name="emulation_quicksave">Quicksave</string>
|
||||||
|
<string name="emulation_quickload">Quickload</string>
|
||||||
|
<string name="emulation_occupied_quicksave_slot">Quicksave - %1$tF %1$tR</string>
|
||||||
|
<string name="quicksave_saving">Saving…</string>
|
||||||
|
<string name="quickload_loading">Loading…</string>
|
||||||
|
<string name="quickload_not_found">No Quicksave available.</string>
|
||||||
|
<string name="miscellaneous">Miscellaneous</string>
|
||||||
|
<string name="use_artic_base_controller">Use Artic Controller when connected to Artic Base Server</string>
|
||||||
|
<string name="use_artic_base_controller_desc">Use the controls provided by Artic Base Server when connected to it instead of the configured input device.</string>
|
||||||
|
<string name="instant_debug_log">Flush log output on every message</string>
|
||||||
|
<string name="instant_debug_log_desc">Immediately commits the debug log to file. Use this if citra crashes and the log output is being cut.</string>
|
||||||
|
|
||||||
</resources>
|
</resources>
|
||||||
|
@ -3,4 +3,4 @@ distributionBase=GRADLE_USER_HOME
|
|||||||
distributionPath=wrapper/dists
|
distributionPath=wrapper/dists
|
||||||
zipStoreBase=GRADLE_USER_HOME
|
zipStoreBase=GRADLE_USER_HOME
|
||||||
zipStorePath=wrapper/dists
|
zipStorePath=wrapper/dists
|
||||||
distributionUrl=https\://services.gradle.org/distributions/gradle-8.2-bin.zip
|
distributionUrl=https\://services.gradle.org/distributions/gradle-8.7-bin.zip
|
||||||
|
@ -126,6 +126,7 @@ void Config::ReadValues() {
|
|||||||
Settings::values.current_input_profile.udp_input_port =
|
Settings::values.current_input_profile.udp_input_port =
|
||||||
static_cast<u16>(sdl2_config->GetInteger("Controls", "udp_input_port",
|
static_cast<u16>(sdl2_config->GetInteger("Controls", "udp_input_port",
|
||||||
InputCommon::CemuhookUDP::DEFAULT_PORT));
|
InputCommon::CemuhookUDP::DEFAULT_PORT));
|
||||||
|
ReadSetting("Controls", Settings::values.use_artic_base_controller);
|
||||||
|
|
||||||
// Core
|
// Core
|
||||||
ReadSetting("Core", Settings::values.use_cpu_jit);
|
ReadSetting("Core", Settings::values.use_cpu_jit);
|
||||||
@ -147,6 +148,7 @@ void Config::ReadValues() {
|
|||||||
ReadSetting("Renderer", Settings::values.use_vsync_new);
|
ReadSetting("Renderer", Settings::values.use_vsync_new);
|
||||||
ReadSetting("Renderer", Settings::values.texture_filter);
|
ReadSetting("Renderer", Settings::values.texture_filter);
|
||||||
ReadSetting("Renderer", Settings::values.texture_sampling);
|
ReadSetting("Renderer", Settings::values.texture_sampling);
|
||||||
|
ReadSetting("Renderer", Settings::values.delay_game_render_thread_us);
|
||||||
|
|
||||||
ReadSetting("Renderer", Settings::values.mono_render_option);
|
ReadSetting("Renderer", Settings::values.mono_render_option);
|
||||||
ReadSetting("Renderer", Settings::values.render_3d);
|
ReadSetting("Renderer", Settings::values.render_3d);
|
||||||
@ -230,6 +232,7 @@ void Config::ReadValues() {
|
|||||||
ReadSetting("System", Settings::values.init_ticks_override);
|
ReadSetting("System", Settings::values.init_ticks_override);
|
||||||
ReadSetting("System", Settings::values.plugin_loader_enabled);
|
ReadSetting("System", Settings::values.plugin_loader_enabled);
|
||||||
ReadSetting("System", Settings::values.allow_plugin_loader);
|
ReadSetting("System", Settings::values.allow_plugin_loader);
|
||||||
|
ReadSetting("System", Settings::values.steps_per_hour);
|
||||||
|
|
||||||
{
|
{
|
||||||
constexpr const char* default_init_time_offset = "0 00:00:00";
|
constexpr const char* default_init_time_offset = "0 00:00:00";
|
||||||
@ -321,6 +324,7 @@ void Config::ReadValues() {
|
|||||||
ReadSetting("Debugging", Settings::values.renderer_debug);
|
ReadSetting("Debugging", Settings::values.renderer_debug);
|
||||||
ReadSetting("Debugging", Settings::values.use_gdbstub);
|
ReadSetting("Debugging", Settings::values.use_gdbstub);
|
||||||
ReadSetting("Debugging", Settings::values.gdbstub_port);
|
ReadSetting("Debugging", Settings::values.gdbstub_port);
|
||||||
|
ReadSetting("Debugging", Settings::values.instant_debug_log);
|
||||||
|
|
||||||
for (const auto& service_module : Service::service_module_map) {
|
for (const auto& service_module : Service::service_module_map) {
|
||||||
bool use_lle = sdl2_config->GetBoolean("Debugging", "LLE\\" + service_module.name, false);
|
bool use_lle = sdl2_config->GetBoolean("Debugging", "LLE\\" + service_module.name, false);
|
||||||
|
@ -319,6 +319,10 @@ init_ticks_type =
|
|||||||
# Defaults to 0.
|
# Defaults to 0.
|
||||||
init_ticks_override =
|
init_ticks_override =
|
||||||
|
|
||||||
|
# Number of steps per hour reported by the pedometer. Range from 0 to 65,535.
|
||||||
|
# Defaults to 0.
|
||||||
|
steps_per_hour =
|
||||||
|
|
||||||
[Camera]
|
[Camera]
|
||||||
# Which camera engine to use for the right outer camera
|
# Which camera engine to use for the right outer camera
|
||||||
# blank (default): a dummy camera that always returns black image
|
# blank (default): a dummy camera that always returns black image
|
||||||
|
@ -327,6 +327,8 @@ void Config::ReadCameraValues() {
|
|||||||
void Config::ReadControlValues() {
|
void Config::ReadControlValues() {
|
||||||
qt_config->beginGroup(QStringLiteral("Controls"));
|
qt_config->beginGroup(QStringLiteral("Controls"));
|
||||||
|
|
||||||
|
ReadBasicSetting(Settings::values.use_artic_base_controller);
|
||||||
|
|
||||||
int num_touch_from_button_maps =
|
int num_touch_from_button_maps =
|
||||||
qt_config->beginReadArray(QStringLiteral("touch_from_button_maps"));
|
qt_config->beginReadArray(QStringLiteral("touch_from_button_maps"));
|
||||||
|
|
||||||
@ -492,6 +494,7 @@ void Config::ReadDebuggingValues() {
|
|||||||
ReadBasicSetting(Settings::values.gdbstub_port);
|
ReadBasicSetting(Settings::values.gdbstub_port);
|
||||||
ReadBasicSetting(Settings::values.renderer_debug);
|
ReadBasicSetting(Settings::values.renderer_debug);
|
||||||
ReadBasicSetting(Settings::values.dump_command_buffers);
|
ReadBasicSetting(Settings::values.dump_command_buffers);
|
||||||
|
ReadBasicSetting(Settings::values.instant_debug_log);
|
||||||
|
|
||||||
qt_config->beginGroup(QStringLiteral("LLE"));
|
qt_config->beginGroup(QStringLiteral("LLE"));
|
||||||
for (const auto& service_module : Service::service_module_map) {
|
for (const auto& service_module : Service::service_module_map) {
|
||||||
@ -667,6 +670,8 @@ void Config::ReadRendererValues() {
|
|||||||
ReadGlobalSetting(Settings::values.texture_filter);
|
ReadGlobalSetting(Settings::values.texture_filter);
|
||||||
ReadGlobalSetting(Settings::values.texture_sampling);
|
ReadGlobalSetting(Settings::values.texture_sampling);
|
||||||
|
|
||||||
|
ReadGlobalSetting(Settings::values.delay_game_render_thread_us);
|
||||||
|
|
||||||
if (global) {
|
if (global) {
|
||||||
ReadBasicSetting(Settings::values.use_shader_jit);
|
ReadBasicSetting(Settings::values.use_shader_jit);
|
||||||
}
|
}
|
||||||
@ -708,6 +713,7 @@ void Config::ReadSystemValues() {
|
|||||||
ReadBasicSetting(Settings::values.init_time_offset);
|
ReadBasicSetting(Settings::values.init_time_offset);
|
||||||
ReadBasicSetting(Settings::values.init_ticks_type);
|
ReadBasicSetting(Settings::values.init_ticks_type);
|
||||||
ReadBasicSetting(Settings::values.init_ticks_override);
|
ReadBasicSetting(Settings::values.init_ticks_override);
|
||||||
|
ReadBasicSetting(Settings::values.steps_per_hour);
|
||||||
ReadBasicSetting(Settings::values.plugin_loader_enabled);
|
ReadBasicSetting(Settings::values.plugin_loader_enabled);
|
||||||
ReadBasicSetting(Settings::values.allow_plugin_loader);
|
ReadBasicSetting(Settings::values.allow_plugin_loader);
|
||||||
}
|
}
|
||||||
@ -922,6 +928,8 @@ void Config::SaveCameraValues() {
|
|||||||
void Config::SaveControlValues() {
|
void Config::SaveControlValues() {
|
||||||
qt_config->beginGroup(QStringLiteral("Controls"));
|
qt_config->beginGroup(QStringLiteral("Controls"));
|
||||||
|
|
||||||
|
WriteBasicSetting(Settings::values.use_artic_base_controller);
|
||||||
|
|
||||||
WriteSetting(QStringLiteral("profile"), Settings::values.current_input_profile_index, 0);
|
WriteSetting(QStringLiteral("profile"), Settings::values.current_input_profile_index, 0);
|
||||||
qt_config->beginWriteArray(QStringLiteral("profiles"));
|
qt_config->beginWriteArray(QStringLiteral("profiles"));
|
||||||
for (std::size_t p = 0; p < Settings::values.input_profiles.size(); ++p) {
|
for (std::size_t p = 0; p < Settings::values.input_profiles.size(); ++p) {
|
||||||
@ -1025,6 +1033,7 @@ void Config::SaveDebuggingValues() {
|
|||||||
WriteBasicSetting(Settings::values.use_gdbstub);
|
WriteBasicSetting(Settings::values.use_gdbstub);
|
||||||
WriteBasicSetting(Settings::values.gdbstub_port);
|
WriteBasicSetting(Settings::values.gdbstub_port);
|
||||||
WriteBasicSetting(Settings::values.renderer_debug);
|
WriteBasicSetting(Settings::values.renderer_debug);
|
||||||
|
WriteBasicSetting(Settings::values.instant_debug_log);
|
||||||
|
|
||||||
qt_config->beginGroup(QStringLiteral("LLE"));
|
qt_config->beginGroup(QStringLiteral("LLE"));
|
||||||
for (const auto& service_module : Settings::values.lle_modules) {
|
for (const auto& service_module : Settings::values.lle_modules) {
|
||||||
@ -1168,6 +1177,8 @@ void Config::SaveRendererValues() {
|
|||||||
WriteGlobalSetting(Settings::values.texture_filter);
|
WriteGlobalSetting(Settings::values.texture_filter);
|
||||||
WriteGlobalSetting(Settings::values.texture_sampling);
|
WriteGlobalSetting(Settings::values.texture_sampling);
|
||||||
|
|
||||||
|
WriteGlobalSetting(Settings::values.delay_game_render_thread_us);
|
||||||
|
|
||||||
if (global) {
|
if (global) {
|
||||||
WriteSetting(QStringLiteral("use_shader_jit"), Settings::values.use_shader_jit.GetValue(),
|
WriteSetting(QStringLiteral("use_shader_jit"), Settings::values.use_shader_jit.GetValue(),
|
||||||
true);
|
true);
|
||||||
@ -1209,6 +1220,7 @@ void Config::SaveSystemValues() {
|
|||||||
WriteBasicSetting(Settings::values.init_time_offset);
|
WriteBasicSetting(Settings::values.init_time_offset);
|
||||||
WriteBasicSetting(Settings::values.init_ticks_type);
|
WriteBasicSetting(Settings::values.init_ticks_type);
|
||||||
WriteBasicSetting(Settings::values.init_ticks_override);
|
WriteBasicSetting(Settings::values.init_ticks_override);
|
||||||
|
WriteBasicSetting(Settings::values.steps_per_hour);
|
||||||
WriteBasicSetting(Settings::values.plugin_loader_enabled);
|
WriteBasicSetting(Settings::values.plugin_loader_enabled);
|
||||||
WriteBasicSetting(Settings::values.allow_plugin_loader);
|
WriteBasicSetting(Settings::values.allow_plugin_loader);
|
||||||
}
|
}
|
||||||
|
@ -9,6 +9,7 @@
|
|||||||
#include <QMediaDevices>
|
#include <QMediaDevices>
|
||||||
#include <QMessageBox>
|
#include <QMessageBox>
|
||||||
#include <QWidget>
|
#include <QWidget>
|
||||||
|
#include <QtGlobal>
|
||||||
#include "citra_qt/configuration/configure_camera.h"
|
#include "citra_qt/configuration/configure_camera.h"
|
||||||
#include "common/settings.h"
|
#include "common/settings.h"
|
||||||
#include "core/frontend/camera/factory.h"
|
#include "core/frontend/camera/factory.h"
|
||||||
@ -86,7 +87,11 @@ void ConfigureCamera::ConnectEvents() {
|
|||||||
});
|
});
|
||||||
connect(ui->toolButton, &QToolButton::clicked, this, &ConfigureCamera::OnToolButtonClicked);
|
connect(ui->toolButton, &QToolButton::clicked, this, &ConfigureCamera::OnToolButtonClicked);
|
||||||
connect(ui->preview_button, &QPushButton::clicked, this, [this] { StartPreviewing(); });
|
connect(ui->preview_button, &QPushButton::clicked, this, [this] { StartPreviewing(); });
|
||||||
|
#if QT_VERSION < QT_VERSION_CHECK(6, 7, 0)
|
||||||
connect(ui->prompt_before_load, &QCheckBox::stateChanged, this, [this](int state) {
|
connect(ui->prompt_before_load, &QCheckBox::stateChanged, this, [this](int state) {
|
||||||
|
#else
|
||||||
|
connect(ui->prompt_before_load, &QCheckBox::checkStateChanged, this, [this](int state) {
|
||||||
|
#endif
|
||||||
ui->camera_file->setDisabled(state == Qt::Checked);
|
ui->camera_file->setDisabled(state == Qt::Checked);
|
||||||
ui->toolButton->setDisabled(state == Qt::Checked);
|
ui->toolButton->setDisabled(state == Qt::Checked);
|
||||||
if (state == Qt::Checked) {
|
if (state == Qt::Checked) {
|
||||||
|
@ -5,6 +5,7 @@
|
|||||||
#include <QCheckBox>
|
#include <QCheckBox>
|
||||||
#include <QMessageBox>
|
#include <QMessageBox>
|
||||||
#include <QTableWidgetItem>
|
#include <QTableWidgetItem>
|
||||||
|
#include <QtGlobal>
|
||||||
#include "configure_cheats.h"
|
#include "configure_cheats.h"
|
||||||
#include "core/cheats/cheat_base.h"
|
#include "core/cheats/cheat_base.h"
|
||||||
#include "core/cheats/cheats.h"
|
#include "core/cheats/cheats.h"
|
||||||
@ -60,7 +61,11 @@ void ConfigureCheats::LoadCheats() {
|
|||||||
i, 2, new QTableWidgetItem(QString::fromStdString(cheats[i]->GetType())));
|
i, 2, new QTableWidgetItem(QString::fromStdString(cheats[i]->GetType())));
|
||||||
enabled->setProperty("row", static_cast<int>(i));
|
enabled->setProperty("row", static_cast<int>(i));
|
||||||
|
|
||||||
|
#if QT_VERSION < QT_VERSION_CHECK(6, 7, 0)
|
||||||
connect(enabled, &QCheckBox::stateChanged, this, &ConfigureCheats::OnCheckChanged);
|
connect(enabled, &QCheckBox::stateChanged, this, &ConfigureCheats::OnCheckChanged);
|
||||||
|
#else
|
||||||
|
connect(enabled, &QCheckBox::checkStateChanged, this, &ConfigureCheats::OnCheckChanged);
|
||||||
|
#endif
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -121,6 +121,7 @@ void ConfigureDebug::SetConfiguration() {
|
|||||||
SettingsToSlider(Settings::values.cpu_clock_percentage.GetValue()));
|
SettingsToSlider(Settings::values.cpu_clock_percentage.GetValue()));
|
||||||
ui->clock_display_label->setText(
|
ui->clock_display_label->setText(
|
||||||
QStringLiteral("%1%").arg(Settings::values.cpu_clock_percentage.GetValue()));
|
QStringLiteral("%1%").arg(Settings::values.cpu_clock_percentage.GetValue()));
|
||||||
|
ui->instant_debug_log->setChecked(Settings::values.instant_debug_log.GetValue());
|
||||||
}
|
}
|
||||||
|
|
||||||
void ConfigureDebug::ApplyConfiguration() {
|
void ConfigureDebug::ApplyConfiguration() {
|
||||||
@ -138,6 +139,7 @@ void ConfigureDebug::ApplyConfiguration() {
|
|||||||
Settings::values.delay_start_for_lle_modules = ui->delay_start_for_lle_modules->isChecked();
|
Settings::values.delay_start_for_lle_modules = ui->delay_start_for_lle_modules->isChecked();
|
||||||
Settings::values.renderer_debug = ui->toggle_renderer_debug->isChecked();
|
Settings::values.renderer_debug = ui->toggle_renderer_debug->isChecked();
|
||||||
Settings::values.dump_command_buffers = ui->toggle_dump_command_buffers->isChecked();
|
Settings::values.dump_command_buffers = ui->toggle_dump_command_buffers->isChecked();
|
||||||
|
Settings::values.instant_debug_log = ui->instant_debug_log->isChecked();
|
||||||
|
|
||||||
ConfigurationShared::ApplyPerGameSetting(
|
ConfigurationShared::ApplyPerGameSetting(
|
||||||
&Settings::values.cpu_clock_percentage, ui->clock_speed_combo,
|
&Settings::values.cpu_clock_percentage, ui->clock_speed_combo,
|
||||||
|
@ -86,7 +86,7 @@
|
|||||||
</layout>
|
</layout>
|
||||||
</item>
|
</item>
|
||||||
<item>
|
<item>
|
||||||
<layout class="QHBoxLayout" name="horizontalLayout">
|
<layout class="QHBoxLayout" name="horizontalLayout1">
|
||||||
<item>
|
<item>
|
||||||
<widget class="QLabel" name="label_3">
|
<widget class="QLabel" name="label_3">
|
||||||
<property name="text">
|
<property name="text">
|
||||||
@ -100,7 +100,7 @@
|
|||||||
</layout>
|
</layout>
|
||||||
</item>
|
</item>
|
||||||
<item>
|
<item>
|
||||||
<layout class="QHBoxLayout" name="horizontalLayout_2">
|
<layout class="QHBoxLayout" name="horizontalLayout2">
|
||||||
<item>
|
<item>
|
||||||
<widget class="QCheckBox" name="toggle_console">
|
<widget class="QCheckBox" name="toggle_console">
|
||||||
<property name="text">
|
<property name="text">
|
||||||
@ -117,6 +117,16 @@
|
|||||||
</item>
|
</item>
|
||||||
</layout>
|
</layout>
|
||||||
</item>
|
</item>
|
||||||
|
<item>
|
||||||
|
<widget class="QCheckBox" name="instant_debug_log">
|
||||||
|
<property name="text">
|
||||||
|
<string>Flush log output on every message</string>
|
||||||
|
</property>
|
||||||
|
<property name="toolTip">
|
||||||
|
<string><html><body>Immediately commits the debug log to file. Use this if citra crashes and the log output is being cut.<br>Enabling this feature will decrease performance, only use it for debugging purposes.</body></html></string>
|
||||||
|
</property>
|
||||||
|
</widget>
|
||||||
|
</item>
|
||||||
</layout>
|
</layout>
|
||||||
</widget>
|
</widget>
|
||||||
</item>
|
</item>
|
||||||
@ -125,7 +135,7 @@
|
|||||||
<property name="title">
|
<property name="title">
|
||||||
<string>CPU</string>
|
<string>CPU</string>
|
||||||
</property>
|
</property>
|
||||||
<layout class="QGridLayout" name="gridLayout_2">
|
<layout class="QGridLayout" name="clock_speed_GLayout">
|
||||||
<item row="1" column="0">
|
<item row="1" column="0">
|
||||||
<widget class="QWidget" name="clock_speed_widget" native="true">
|
<widget class="QWidget" name="clock_speed_widget" native="true">
|
||||||
<layout class="QHBoxLayout" name="clock_speed_layout">
|
<layout class="QHBoxLayout" name="clock_speed_layout">
|
||||||
|
@ -29,7 +29,7 @@ ConfigureDialog::ConfigureDialog(QWidget* parent, HotkeyRegistry& registry_, Cor
|
|||||||
system{system_}, is_powered_on{system.IsPoweredOn()},
|
system{system_}, is_powered_on{system.IsPoweredOn()},
|
||||||
general_tab{std::make_unique<ConfigureGeneral>(this)},
|
general_tab{std::make_unique<ConfigureGeneral>(this)},
|
||||||
system_tab{std::make_unique<ConfigureSystem>(system, this)},
|
system_tab{std::make_unique<ConfigureSystem>(system, this)},
|
||||||
input_tab{std::make_unique<ConfigureInput>(this)},
|
input_tab{std::make_unique<ConfigureInput>(system, this)},
|
||||||
hotkeys_tab{std::make_unique<ConfigureHotkeys>(this)},
|
hotkeys_tab{std::make_unique<ConfigureHotkeys>(this)},
|
||||||
graphics_tab{
|
graphics_tab{
|
||||||
std::make_unique<ConfigureGraphics>(gl_renderer, physical_devices, is_powered_on, this)},
|
std::make_unique<ConfigureGraphics>(gl_renderer, physical_devices, is_powered_on, this)},
|
||||||
|
@ -26,6 +26,10 @@ ConfigureGraphics::ConfigureGraphics(QString gl_renderer, std::span<const QStrin
|
|||||||
// Set the index to -1 to ensure the below lambda is called with setCurrentIndex
|
// Set the index to -1 to ensure the below lambda is called with setCurrentIndex
|
||||||
ui->graphics_api_combo->setCurrentIndex(-1);
|
ui->graphics_api_combo->setCurrentIndex(-1);
|
||||||
|
|
||||||
|
const auto width = static_cast<int>(QString::fromStdString("000000000").size() * 6);
|
||||||
|
ui->delay_render_display_label->setMinimumWidth(width);
|
||||||
|
ui->delay_render_combo->setVisible(!Settings::IsConfiguringGlobal());
|
||||||
|
|
||||||
auto graphics_api_combo_model =
|
auto graphics_api_combo_model =
|
||||||
qobject_cast<QStandardItemModel*>(ui->graphics_api_combo->model());
|
qobject_cast<QStandardItemModel*>(ui->graphics_api_combo->model());
|
||||||
#ifndef ENABLE_SOFTWARE_RENDERER
|
#ifndef ENABLE_SOFTWARE_RENDERER
|
||||||
@ -82,12 +86,25 @@ ConfigureGraphics::ConfigureGraphics(QString gl_renderer, std::span<const QStrin
|
|||||||
connect(ui->graphics_api_combo, qOverload<int>(&QComboBox::currentIndexChanged), this,
|
connect(ui->graphics_api_combo, qOverload<int>(&QComboBox::currentIndexChanged), this,
|
||||||
&ConfigureGraphics::SetPhysicalDeviceComboVisibility);
|
&ConfigureGraphics::SetPhysicalDeviceComboVisibility);
|
||||||
|
|
||||||
|
connect(ui->delay_render_slider, &QSlider::valueChanged, this, [&](int value) {
|
||||||
|
ui->delay_render_display_label->setText(
|
||||||
|
QStringLiteral("%1 ms")
|
||||||
|
.arg(((double)value) / 1000.f, 0, 'f', 3)
|
||||||
|
.rightJustified(QString::fromStdString("000000000").size()));
|
||||||
|
});
|
||||||
|
|
||||||
SetConfiguration();
|
SetConfiguration();
|
||||||
}
|
}
|
||||||
|
|
||||||
ConfigureGraphics::~ConfigureGraphics() = default;
|
ConfigureGraphics::~ConfigureGraphics() = default;
|
||||||
|
|
||||||
void ConfigureGraphics::SetConfiguration() {
|
void ConfigureGraphics::SetConfiguration() {
|
||||||
|
ui->delay_render_slider->setValue(Settings::values.delay_game_render_thread_us.GetValue());
|
||||||
|
ui->delay_render_display_label->setText(
|
||||||
|
QStringLiteral("%1 ms")
|
||||||
|
.arg(((double)ui->delay_render_slider->value()) / 1000, 0, 'f', 3)
|
||||||
|
.rightJustified(QString::fromStdString("000000000").size()));
|
||||||
|
|
||||||
if (!Settings::IsConfiguringGlobal()) {
|
if (!Settings::IsConfiguringGlobal()) {
|
||||||
ConfigurationShared::SetHighlight(ui->graphics_api_group,
|
ConfigurationShared::SetHighlight(ui->graphics_api_group,
|
||||||
!Settings::values.graphics_api.UsingGlobal());
|
!Settings::values.graphics_api.UsingGlobal());
|
||||||
@ -101,6 +118,16 @@ void ConfigureGraphics::SetConfiguration() {
|
|||||||
&Settings::values.texture_sampling);
|
&Settings::values.texture_sampling);
|
||||||
ConfigurationShared::SetHighlight(ui->widget_texture_sampling,
|
ConfigurationShared::SetHighlight(ui->widget_texture_sampling,
|
||||||
!Settings::values.texture_sampling.UsingGlobal());
|
!Settings::values.texture_sampling.UsingGlobal());
|
||||||
|
ConfigurationShared::SetHighlight(
|
||||||
|
ui->delay_render_layout, !Settings::values.delay_game_render_thread_us.UsingGlobal());
|
||||||
|
|
||||||
|
if (Settings::values.delay_game_render_thread_us.UsingGlobal()) {
|
||||||
|
ui->delay_render_combo->setCurrentIndex(0);
|
||||||
|
ui->delay_render_slider->setEnabled(false);
|
||||||
|
} else {
|
||||||
|
ui->delay_render_combo->setCurrentIndex(1);
|
||||||
|
ui->delay_render_slider->setEnabled(true);
|
||||||
|
}
|
||||||
} else {
|
} else {
|
||||||
ui->graphics_api_combo->setCurrentIndex(
|
ui->graphics_api_combo->setCurrentIndex(
|
||||||
static_cast<int>(Settings::values.graphics_api.GetValue()));
|
static_cast<int>(Settings::values.graphics_api.GetValue()));
|
||||||
@ -144,6 +171,9 @@ void ConfigureGraphics::ApplyConfiguration() {
|
|||||||
ui->toggle_disk_shader_cache, use_disk_shader_cache);
|
ui->toggle_disk_shader_cache, use_disk_shader_cache);
|
||||||
ConfigurationShared::ApplyPerGameSetting(&Settings::values.use_vsync_new, ui->toggle_vsync_new,
|
ConfigurationShared::ApplyPerGameSetting(&Settings::values.use_vsync_new, ui->toggle_vsync_new,
|
||||||
use_vsync_new);
|
use_vsync_new);
|
||||||
|
ConfigurationShared::ApplyPerGameSetting(
|
||||||
|
&Settings::values.delay_game_render_thread_us, ui->delay_render_combo,
|
||||||
|
[this](s32) { return ui->delay_render_slider->value(); });
|
||||||
|
|
||||||
if (Settings::IsConfiguringGlobal()) {
|
if (Settings::IsConfiguringGlobal()) {
|
||||||
Settings::values.use_shader_jit = ui->toggle_shader_jit->isChecked();
|
Settings::values.use_shader_jit = ui->toggle_shader_jit->isChecked();
|
||||||
@ -170,9 +200,16 @@ void ConfigureGraphics::SetupPerGameUI() {
|
|||||||
ui->toggle_async_present->setEnabled(Settings::values.async_presentation.UsingGlobal());
|
ui->toggle_async_present->setEnabled(Settings::values.async_presentation.UsingGlobal());
|
||||||
ui->graphics_api_combo->setEnabled(Settings::values.graphics_api.UsingGlobal());
|
ui->graphics_api_combo->setEnabled(Settings::values.graphics_api.UsingGlobal());
|
||||||
ui->physical_device_combo->setEnabled(Settings::values.physical_device.UsingGlobal());
|
ui->physical_device_combo->setEnabled(Settings::values.physical_device.UsingGlobal());
|
||||||
|
ui->delay_render_combo->setEnabled(
|
||||||
|
Settings::values.delay_game_render_thread_us.UsingGlobal());
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
connect(ui->delay_render_combo, qOverload<int>(&QComboBox::activated), this, [this](int index) {
|
||||||
|
ui->delay_render_slider->setEnabled(index == 1);
|
||||||
|
ConfigurationShared::SetHighlight(ui->delay_render_layout, index == 1);
|
||||||
|
});
|
||||||
|
|
||||||
ui->toggle_shader_jit->setVisible(false);
|
ui->toggle_shader_jit->setVisible(false);
|
||||||
|
|
||||||
ConfigurationShared::SetColoredComboBox(
|
ConfigurationShared::SetColoredComboBox(
|
||||||
|
@ -307,6 +307,83 @@
|
|||||||
</property>
|
</property>
|
||||||
</widget>
|
</widget>
|
||||||
</item>
|
</item>
|
||||||
|
<item>
|
||||||
|
<widget class="QWidget" name="delay_render_layout" native="true">
|
||||||
|
<layout class="QHBoxLayout" name="delay_render_layout_inner">
|
||||||
|
<property name="leftMargin">
|
||||||
|
<number>0</number>
|
||||||
|
</property>
|
||||||
|
<property name="topMargin">
|
||||||
|
<number>0</number>
|
||||||
|
</property>
|
||||||
|
<property name="rightMargin">
|
||||||
|
<number>0</number>
|
||||||
|
</property>
|
||||||
|
<property name="bottomMargin">
|
||||||
|
<number>0</number>
|
||||||
|
</property>
|
||||||
|
<item>
|
||||||
|
<widget class="QComboBox" name="delay_render_combo">
|
||||||
|
<item>
|
||||||
|
<property name="text">
|
||||||
|
<string>Use global</string>
|
||||||
|
</property>
|
||||||
|
</item>
|
||||||
|
<item>
|
||||||
|
<property name="text">
|
||||||
|
<string>Use per-game</string>
|
||||||
|
</property>
|
||||||
|
</item>
|
||||||
|
</widget>
|
||||||
|
</item>
|
||||||
|
<item>
|
||||||
|
<widget class="QLabel" name="label_delay_render">
|
||||||
|
<property name="text">
|
||||||
|
<string>Delay game render thread:</string>
|
||||||
|
</property>
|
||||||
|
<property name="toolTip">
|
||||||
|
<string><html><head/><body><p>Delays the emulated game render thread the specified amount of milliseconds every time it submits render commands to the GPU.</p><p>Adjust this feature in the (very few) dynamic-fps games to fix performance issues.</p></body></html></string>
|
||||||
|
</property>
|
||||||
|
</widget>
|
||||||
|
</item>
|
||||||
|
<item>
|
||||||
|
<widget class="QSlider" name="delay_render_slider">
|
||||||
|
<property name="minimum">
|
||||||
|
<number>0</number>
|
||||||
|
</property>
|
||||||
|
<property name="maximum">
|
||||||
|
<number>16000</number>
|
||||||
|
</property>
|
||||||
|
<property name="singleStep">
|
||||||
|
<number>100</number>
|
||||||
|
</property>
|
||||||
|
<property name="pageStep">
|
||||||
|
<number>250</number>
|
||||||
|
</property>
|
||||||
|
<property name="value">
|
||||||
|
<number>0</number>
|
||||||
|
</property>
|
||||||
|
<property name="orientation">
|
||||||
|
<enum>Qt::Horizontal</enum>
|
||||||
|
</property>
|
||||||
|
<property name="tickPosition">
|
||||||
|
<enum>QSlider::TicksBelow</enum>
|
||||||
|
</property>
|
||||||
|
</widget>
|
||||||
|
</item>
|
||||||
|
<item>
|
||||||
|
<widget class="QLabel" name="delay_render_display_label">
|
||||||
|
<property name="text">
|
||||||
|
<string/>
|
||||||
|
</property>
|
||||||
|
<property name="alignment">
|
||||||
|
<set>Qt::AlignRight|Qt::AlignTrailing|Qt::AlignVCenter</set>
|
||||||
|
</property>
|
||||||
|
</widget>
|
||||||
|
</item>
|
||||||
|
</layout>
|
||||||
|
</widget>
|
||||||
|
</item>
|
||||||
</layout>
|
</layout>
|
||||||
</widget>
|
</widget>
|
||||||
</item>
|
</item>
|
||||||
|
@ -16,6 +16,7 @@
|
|||||||
#include "citra_qt/configuration/configure_input.h"
|
#include "citra_qt/configuration/configure_input.h"
|
||||||
#include "citra_qt/configuration/configure_motion_touch.h"
|
#include "citra_qt/configuration/configure_motion_touch.h"
|
||||||
#include "common/param_package.h"
|
#include "common/param_package.h"
|
||||||
|
#include "core/core.h"
|
||||||
#include "ui_configure_input.h"
|
#include "ui_configure_input.h"
|
||||||
|
|
||||||
const std::array<std::string, ConfigureInput::ANALOG_SUB_BUTTONS_NUM>
|
const std::array<std::string, ConfigureInput::ANALOG_SUB_BUTTONS_NUM>
|
||||||
@ -145,8 +146,8 @@ static QString AnalogToText(const Common::ParamPackage& param, const std::string
|
|||||||
return QObject::tr("[unknown]");
|
return QObject::tr("[unknown]");
|
||||||
}
|
}
|
||||||
|
|
||||||
ConfigureInput::ConfigureInput(QWidget* parent)
|
ConfigureInput::ConfigureInput(Core::System& _system, QWidget* parent)
|
||||||
: QWidget(parent), ui(std::make_unique<Ui::ConfigureInput>()),
|
: QWidget(parent), system(_system), ui(std::make_unique<Ui::ConfigureInput>()),
|
||||||
timeout_timer(std::make_unique<QTimer>()), poll_timer(std::make_unique<QTimer>()) {
|
timeout_timer(std::make_unique<QTimer>()), poll_timer(std::make_unique<QTimer>()) {
|
||||||
ui->setupUi(this);
|
ui->setupUi(this);
|
||||||
setFocusPolicy(Qt::ClickFocus);
|
setFocusPolicy(Qt::ClickFocus);
|
||||||
@ -400,6 +401,9 @@ ConfigureInput::ConfigureInput(QWidget* parent)
|
|||||||
ConfigureInput::~ConfigureInput() = default;
|
ConfigureInput::~ConfigureInput() = default;
|
||||||
|
|
||||||
void ConfigureInput::ApplyConfiguration() {
|
void ConfigureInput::ApplyConfiguration() {
|
||||||
|
|
||||||
|
Settings::values.use_artic_base_controller = ui->use_artic_controller->isChecked();
|
||||||
|
|
||||||
std::transform(buttons_param.begin(), buttons_param.end(),
|
std::transform(buttons_param.begin(), buttons_param.end(),
|
||||||
Settings::values.current_input_profile.buttons.begin(),
|
Settings::values.current_input_profile.buttons.begin(),
|
||||||
[](const Common::ParamPackage& param) { return param.Serialize(); });
|
[](const Common::ParamPackage& param) { return param.Serialize(); });
|
||||||
@ -444,6 +448,10 @@ QList<QKeySequence> ConfigureInput::GetUsedKeyboardKeys() {
|
|||||||
}
|
}
|
||||||
|
|
||||||
void ConfigureInput::LoadConfiguration() {
|
void ConfigureInput::LoadConfiguration() {
|
||||||
|
|
||||||
|
ui->use_artic_controller->setChecked(Settings::values.use_artic_base_controller.GetValue());
|
||||||
|
ui->use_artic_controller->setEnabled(!system.IsPoweredOn());
|
||||||
|
|
||||||
std::transform(Settings::values.current_input_profile.buttons.begin(),
|
std::transform(Settings::values.current_input_profile.buttons.begin(),
|
||||||
Settings::values.current_input_profile.buttons.end(), buttons_param.begin(),
|
Settings::values.current_input_profile.buttons.end(), buttons_param.begin(),
|
||||||
[](const std::string& str) { return Common::ParamPackage(str); });
|
[](const std::string& str) { return Common::ParamPackage(str); });
|
||||||
|
@ -30,7 +30,7 @@ class ConfigureInput : public QWidget {
|
|||||||
Q_OBJECT
|
Q_OBJECT
|
||||||
|
|
||||||
public:
|
public:
|
||||||
explicit ConfigureInput(QWidget* parent = nullptr);
|
explicit ConfigureInput(Core::System& system, QWidget* parent = nullptr);
|
||||||
~ConfigureInput() override;
|
~ConfigureInput() override;
|
||||||
|
|
||||||
/// Save all button configurations to settings file
|
/// Save all button configurations to settings file
|
||||||
@ -50,6 +50,7 @@ signals:
|
|||||||
void InputKeysChanged(QList<QKeySequence> new_key_list);
|
void InputKeysChanged(QList<QKeySequence> new_key_list);
|
||||||
|
|
||||||
private:
|
private:
|
||||||
|
Core::System& system;
|
||||||
std::unique_ptr<Ui::ConfigureInput> ui;
|
std::unique_ptr<Ui::ConfigureInput> ui;
|
||||||
|
|
||||||
std::unique_ptr<QTimer> timeout_timer;
|
std::unique_ptr<QTimer> timeout_timer;
|
||||||
|
@ -841,6 +841,13 @@
|
|||||||
</item>
|
</item>
|
||||||
</layout>
|
</layout>
|
||||||
</item>
|
</item>
|
||||||
|
<item>
|
||||||
|
<widget class="QCheckBox" name="use_artic_controller">
|
||||||
|
<property name="text">
|
||||||
|
<string>Use Artic Controller when connected to Artic Base Server</string>
|
||||||
|
</property>
|
||||||
|
</widget>
|
||||||
|
</item>
|
||||||
</layout>
|
</layout>
|
||||||
</item>
|
</item>
|
||||||
</layout>
|
</layout>
|
||||||
|
@ -151,7 +151,14 @@ void ConfigurePerGame::LoadConfiguration() {
|
|||||||
ui->display_title_id->setText(
|
ui->display_title_id->setText(
|
||||||
QStringLiteral("%1").arg(title_id, 16, 16, QLatin1Char{'0'}).toUpper());
|
QStringLiteral("%1").arg(title_id, 16, 16, QLatin1Char{'0'}).toUpper());
|
||||||
|
|
||||||
const auto loader = Loader::GetLoader(filename);
|
std::unique_ptr<Loader::AppLoader> loader_ptr;
|
||||||
|
Loader::AppLoader* loader;
|
||||||
|
if (system.IsPoweredOn()) {
|
||||||
|
loader = &system.GetAppLoader();
|
||||||
|
} else {
|
||||||
|
loader_ptr = Loader::GetLoader(filename);
|
||||||
|
loader = loader_ptr.get();
|
||||||
|
}
|
||||||
|
|
||||||
std::string title;
|
std::string title;
|
||||||
if (loader->ReadTitle(title) == Loader::ResultStatus::Success)
|
if (loader->ReadTitle(title) == Loader::ResultStatus::Success)
|
||||||
|
@ -328,6 +328,8 @@ void ConfigureSystem::SetConfiguration() {
|
|||||||
ui->edit_init_ticks_value->setText(
|
ui->edit_init_ticks_value->setText(
|
||||||
QString::number(Settings::values.init_ticks_override.GetValue()));
|
QString::number(Settings::values.init_ticks_override.GetValue()));
|
||||||
|
|
||||||
|
ui->spinBox_steps_per_hour->setValue(Settings::values.steps_per_hour.GetValue());
|
||||||
|
|
||||||
cfg = Service::CFG::GetModule(system);
|
cfg = Service::CFG::GetModule(system);
|
||||||
ReadSystemSettings();
|
ReadSystemSettings();
|
||||||
|
|
||||||
@ -460,6 +462,8 @@ void ConfigureSystem::ApplyConfiguration() {
|
|||||||
Settings::values.init_ticks_override =
|
Settings::values.init_ticks_override =
|
||||||
static_cast<s64>(ui->edit_init_ticks_value->text().toLongLong());
|
static_cast<s64>(ui->edit_init_ticks_value->text().toLongLong());
|
||||||
|
|
||||||
|
Settings::values.steps_per_hour = static_cast<u16>(ui->spinBox_steps_per_hour->value());
|
||||||
|
|
||||||
s64 time_offset_time = ui->edit_init_time_offset_time->time().msecsSinceStartOfDay() / 1000;
|
s64 time_offset_time = ui->edit_init_time_offset_time->time().msecsSinceStartOfDay() / 1000;
|
||||||
s64 time_offset_days = ui->edit_init_time_offset_days->value() * 86400;
|
s64 time_offset_days = ui->edit_init_time_offset_days->value() * 86400;
|
||||||
|
|
||||||
@ -631,8 +635,10 @@ void ConfigureSystem::SetupPerGameUI() {
|
|||||||
ui->label_language->setVisible(false);
|
ui->label_language->setVisible(false);
|
||||||
ui->label_country->setVisible(false);
|
ui->label_country->setVisible(false);
|
||||||
ui->label_play_coins->setVisible(false);
|
ui->label_play_coins->setVisible(false);
|
||||||
|
ui->label_steps_per_hour->setVisible(false);
|
||||||
ui->edit_username->setVisible(false);
|
ui->edit_username->setVisible(false);
|
||||||
ui->spinBox_play_coins->setVisible(false);
|
ui->spinBox_play_coins->setVisible(false);
|
||||||
|
ui->spinBox_steps_per_hour->setVisible(false);
|
||||||
ui->combo_birthday->setVisible(false);
|
ui->combo_birthday->setVisible(false);
|
||||||
ui->combo_birthmonth->setVisible(false);
|
ui->combo_birthmonth->setVisible(false);
|
||||||
ui->combo_init_clock->setVisible(false);
|
ui->combo_init_clock->setVisible(false);
|
||||||
|
File diff suppressed because it is too large
Load Diff
@ -5,6 +5,7 @@
|
|||||||
#include <QBrush>
|
#include <QBrush>
|
||||||
#include <QString>
|
#include <QString>
|
||||||
#include <QTreeWidgetItem>
|
#include <QTreeWidgetItem>
|
||||||
|
#include <QtGlobal>
|
||||||
#include <fmt/format.h>
|
#include <fmt/format.h>
|
||||||
#include "citra_qt/debugger/ipc/record_dialog.h"
|
#include "citra_qt/debugger/ipc/record_dialog.h"
|
||||||
#include "citra_qt/debugger/ipc/recorder.h"
|
#include "citra_qt/debugger/ipc/recorder.h"
|
||||||
@ -22,8 +23,13 @@ IPCRecorderWidget::IPCRecorderWidget(Core::System& system_, QWidget* parent)
|
|||||||
ui->setupUi(this);
|
ui->setupUi(this);
|
||||||
qRegisterMetaType<IPCDebugger::RequestRecord>();
|
qRegisterMetaType<IPCDebugger::RequestRecord>();
|
||||||
|
|
||||||
|
#if QT_VERSION < QT_VERSION_CHECK(6, 7, 0)
|
||||||
connect(ui->enabled, &QCheckBox::stateChanged, this,
|
connect(ui->enabled, &QCheckBox::stateChanged, this,
|
||||||
[this](int new_state) { SetEnabled(new_state == Qt::Checked); });
|
[this](int new_state) { SetEnabled(new_state == Qt::Checked); });
|
||||||
|
#else
|
||||||
|
connect(ui->enabled, &QCheckBox::checkStateChanged, this,
|
||||||
|
[this](int new_state) { SetEnabled(new_state == Qt::Checked); });
|
||||||
|
#endif
|
||||||
connect(ui->clearButton, &QPushButton::clicked, this, &IPCRecorderWidget::Clear);
|
connect(ui->clearButton, &QPushButton::clicked, this, &IPCRecorderWidget::Clear);
|
||||||
connect(ui->filter, &QLineEdit::textChanged, this, &IPCRecorderWidget::ApplyFilterToAll);
|
connect(ui->filter, &QLineEdit::textChanged, this, &IPCRecorderWidget::ApplyFilterToAll);
|
||||||
connect(ui->main, &QTreeWidget::itemDoubleClicked, this, &IPCRecorderWidget::OpenRecordDialog);
|
connect(ui->main, &QTreeWidget::itemDoubleClicked, this, &IPCRecorderWidget::OpenRecordDialog);
|
||||||
|
@ -27,7 +27,7 @@ static const std::unordered_map<AVOptionType, const char*> TypeNameMap{{
|
|||||||
{AV_OPT_TYPE_STRING, QT_TR_NOOP("string")},
|
{AV_OPT_TYPE_STRING, QT_TR_NOOP("string")},
|
||||||
{AV_OPT_TYPE_DICT, QT_TR_NOOP("dictionary")},
|
{AV_OPT_TYPE_DICT, QT_TR_NOOP("dictionary")},
|
||||||
{AV_OPT_TYPE_VIDEO_RATE, QT_TR_NOOP("video rate")},
|
{AV_OPT_TYPE_VIDEO_RATE, QT_TR_NOOP("video rate")},
|
||||||
{AV_OPT_TYPE_CHANNEL_LAYOUT, QT_TR_NOOP("channel layout")},
|
{AV_OPT_TYPE_CHLAYOUT, QT_TR_NOOP("channel layout")},
|
||||||
}};
|
}};
|
||||||
|
|
||||||
static const std::unordered_map<AVOptionType, const char*> TypeDescriptionMap{{
|
static const std::unordered_map<AVOptionType, const char*> TypeDescriptionMap{{
|
||||||
@ -39,7 +39,7 @@ static const std::unordered_map<AVOptionType, const char*> TypeDescriptionMap{{
|
|||||||
{AV_OPT_TYPE_DICT,
|
{AV_OPT_TYPE_DICT,
|
||||||
QT_TR_NOOP("Comma-splitted list of <key>=<value>. Do not put spaces.")},
|
QT_TR_NOOP("Comma-splitted list of <key>=<value>. Do not put spaces.")},
|
||||||
{AV_OPT_TYPE_VIDEO_RATE, QT_TR_NOOP("<num>/<den>, or preset values like 'pal'.")},
|
{AV_OPT_TYPE_VIDEO_RATE, QT_TR_NOOP("<num>/<den>, or preset values like 'pal'.")},
|
||||||
{AV_OPT_TYPE_CHANNEL_LAYOUT, QT_TR_NOOP("Hexadecimal channel layout mask starting with '0x'.")},
|
{AV_OPT_TYPE_CHLAYOUT, QT_TR_NOOP("Hexadecimal channel layout mask starting with '0x'.")},
|
||||||
}};
|
}};
|
||||||
|
|
||||||
/// Get the preset values of an option. returns {display value, real value}
|
/// Get the preset values of an option. returns {display value, real value}
|
||||||
|
@ -974,7 +974,7 @@ void GMainWindow::UpdateMenuState() {
|
|||||||
action->setEnabled(emulation_running);
|
action->setEnabled(emulation_running);
|
||||||
}
|
}
|
||||||
|
|
||||||
ui->action_Capture_Screenshot->setEnabled(emulation_running && !is_paused);
|
ui->action_Capture_Screenshot->setEnabled(emulation_running);
|
||||||
|
|
||||||
if (emulation_running && is_paused) {
|
if (emulation_running && is_paused) {
|
||||||
ui->action_Pause->setText(tr("&Continue"));
|
ui->action_Pause->setText(tr("&Continue"));
|
||||||
@ -1216,7 +1216,10 @@ bool GMainWindow::LoadROM(const QString& filename) {
|
|||||||
case Core::System::ResultStatus::ErrorArticDisconnected:
|
case Core::System::ResultStatus::ErrorArticDisconnected:
|
||||||
QMessageBox::critical(
|
QMessageBox::critical(
|
||||||
this, tr("Artic Base Server"),
|
this, tr("Artic Base Server"),
|
||||||
tr("An error has occurred whilst communicating with the Artic Base Server."));
|
tr(fmt::format(
|
||||||
|
"An error has occurred whilst communicating with the Artic Base Server.\n{}",
|
||||||
|
system.GetStatusDetails())
|
||||||
|
.c_str()));
|
||||||
break;
|
break;
|
||||||
default:
|
default:
|
||||||
QMessageBox::critical(
|
QMessageBox::critical(
|
||||||
@ -1238,6 +1241,10 @@ bool GMainWindow::LoadROM(const QString& filename) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
void GMainWindow::BootGame(const QString& filename) {
|
void GMainWindow::BootGame(const QString& filename) {
|
||||||
|
if (emu_thread) {
|
||||||
|
ShutdownGame();
|
||||||
|
}
|
||||||
|
|
||||||
const bool is_artic = filename.startsWith(QString::fromStdString("articbase://"));
|
const bool is_artic = filename.startsWith(QString::fromStdString("articbase://"));
|
||||||
|
|
||||||
if (!is_artic && filename.endsWith(QStringLiteral(".cia"))) {
|
if (!is_artic && filename.endsWith(QStringLiteral(".cia"))) {
|
||||||
@ -2412,33 +2419,47 @@ void GMainWindow::OnSaveMovie() {
|
|||||||
}
|
}
|
||||||
|
|
||||||
void GMainWindow::OnCaptureScreenshot() {
|
void GMainWindow::OnCaptureScreenshot() {
|
||||||
if (!emu_thread || !emu_thread->IsRunning()) [[unlikely]] {
|
if (!emu_thread) [[unlikely]] {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
OnPauseGame();
|
const bool was_running = emu_thread->IsRunning();
|
||||||
std::string path = UISettings::values.screenshot_path.GetValue();
|
|
||||||
if (!FileUtil::IsDirectory(path)) {
|
if (was_running ||
|
||||||
if (!FileUtil::CreateFullPath(path)) {
|
(QMessageBox::question(
|
||||||
QMessageBox::information(this, tr("Invalid Screenshot Directory"),
|
this, tr("Game will unpause"),
|
||||||
tr("Cannot create specified screenshot directory. Screenshot "
|
tr("The game will be unpaused, and the next frame will be captured. Is this okay?"),
|
||||||
"path is set back to its default value."));
|
QMessageBox::Yes | QMessageBox::No, QMessageBox::No) == QMessageBox::Yes)) {
|
||||||
path = FileUtil::GetUserPath(FileUtil::UserPath::UserDir);
|
if (was_running) {
|
||||||
path.append("screenshots/");
|
OnPauseGame();
|
||||||
UISettings::values.screenshot_path = path;
|
}
|
||||||
};
|
std::string path = UISettings::values.screenshot_path.GetValue();
|
||||||
|
if (!FileUtil::IsDirectory(path)) {
|
||||||
|
if (!FileUtil::CreateFullPath(path)) {
|
||||||
|
QMessageBox::information(
|
||||||
|
this, tr("Invalid Screenshot Directory"),
|
||||||
|
tr("Cannot create specified screenshot directory. Screenshot "
|
||||||
|
"path is set back to its default value."));
|
||||||
|
path = FileUtil::GetUserPath(FileUtil::UserPath::UserDir);
|
||||||
|
path.append("screenshots/");
|
||||||
|
UISettings::values.screenshot_path = path;
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
|
static QRegularExpression expr(QStringLiteral("[\\/:?\"<>|]"));
|
||||||
|
const std::string filename = game_title.remove(expr).toStdString();
|
||||||
|
const std::string timestamp = QDateTime::currentDateTime()
|
||||||
|
.toString(QStringLiteral("dd.MM.yy_hh.mm.ss.z"))
|
||||||
|
.toStdString();
|
||||||
|
path.append(fmt::format("/{}_{}.png", filename, timestamp));
|
||||||
|
|
||||||
|
auto* const screenshot_window =
|
||||||
|
secondary_window->HasFocus() ? secondary_window : render_window;
|
||||||
|
screenshot_window->CaptureScreenshot(
|
||||||
|
UISettings::values.screenshot_resolution_factor.GetValue(),
|
||||||
|
QString::fromStdString(path));
|
||||||
|
OnStartGame();
|
||||||
}
|
}
|
||||||
|
|
||||||
static QRegularExpression expr(QStringLiteral("[\\/:?\"<>|]"));
|
|
||||||
const std::string filename = game_title.remove(expr).toStdString();
|
|
||||||
const std::string timestamp =
|
|
||||||
QDateTime::currentDateTime().toString(QStringLiteral("dd.MM.yy_hh.mm.ss.z")).toStdString();
|
|
||||||
path.append(fmt::format("/{}_{}.png", filename, timestamp));
|
|
||||||
|
|
||||||
auto* const screenshot_window = secondary_window->HasFocus() ? secondary_window : render_window;
|
|
||||||
screenshot_window->CaptureScreenshot(UISettings::values.screenshot_resolution_factor.GetValue(),
|
|
||||||
QString::fromStdString(path));
|
|
||||||
OnStartGame();
|
|
||||||
}
|
}
|
||||||
|
|
||||||
void GMainWindow::OnDumpVideo() {
|
void GMainWindow::OnDumpVideo() {
|
||||||
@ -2626,10 +2647,12 @@ void GMainWindow::UpdateStatusBar() {
|
|||||||
const bool do_mb = results.artic_transmitted >= (1000.0 * 1000.0);
|
const bool do_mb = results.artic_transmitted >= (1000.0 * 1000.0);
|
||||||
const double value = do_mb ? (results.artic_transmitted / (1000.0 * 1000.0))
|
const double value = do_mb ? (results.artic_transmitted / (1000.0 * 1000.0))
|
||||||
: (results.artic_transmitted / 1000.0);
|
: (results.artic_transmitted / 1000.0);
|
||||||
static const std::array<std::pair<Core::PerfStats::PerfArticEventBits, QString>, 4>
|
static const std::array<std::pair<Core::PerfStats::PerfArticEventBits, QString>, 5>
|
||||||
perf_events = {
|
perf_events = {
|
||||||
std::make_pair(Core::PerfStats::PerfArticEventBits::ARTIC_SHARED_EXT_DATA,
|
std::make_pair(Core::PerfStats::PerfArticEventBits::ARTIC_SHARED_EXT_DATA,
|
||||||
tr("(Accessing SharedExtData)")),
|
tr("(Accessing SharedExtData)")),
|
||||||
|
std::make_pair(Core::PerfStats::PerfArticEventBits::ARTIC_SYSTEM_SAVE_DATA,
|
||||||
|
tr("(Accessing SystemSaveData)")),
|
||||||
std::make_pair(Core::PerfStats::PerfArticEventBits::ARTIC_BOSS_EXT_DATA,
|
std::make_pair(Core::PerfStats::PerfArticEventBits::ARTIC_BOSS_EXT_DATA,
|
||||||
tr("(Accessing BossExtData)")),
|
tr("(Accessing BossExtData)")),
|
||||||
std::make_pair(Core::PerfStats::PerfArticEventBits::ARTIC_EXT_DATA,
|
std::make_pair(Core::PerfStats::PerfArticEventBits::ARTIC_EXT_DATA,
|
||||||
@ -2854,7 +2877,9 @@ void GMainWindow::OnCoreError(Core::System::ResultStatus result, std::string det
|
|||||||
error_severity_icon = QMessageBox::Icon::Warning;
|
error_severity_icon = QMessageBox::Icon::Warning;
|
||||||
} else if (result == Core::System::ResultStatus::ErrorArticDisconnected) {
|
} else if (result == Core::System::ResultStatus::ErrorArticDisconnected) {
|
||||||
title = tr("Artic Base Server");
|
title = tr("Artic Base Server");
|
||||||
message = tr("A communication error has occurred. The game will quit.");
|
message =
|
||||||
|
tr(fmt::format("A communication error has occurred. The game will quit.\n{}", details)
|
||||||
|
.c_str());
|
||||||
error_severity_icon = QMessageBox::Icon::Critical;
|
error_severity_icon = QMessageBox::Icon::Critical;
|
||||||
can_continue = false;
|
can_continue = false;
|
||||||
} else {
|
} else {
|
||||||
@ -3068,8 +3093,8 @@ void GMainWindow::LoadTranslation() {
|
|||||||
bool loaded;
|
bool loaded;
|
||||||
|
|
||||||
if (UISettings::values.language.isEmpty()) {
|
if (UISettings::values.language.isEmpty()) {
|
||||||
// If the selected language is empty, use system locale
|
// Use the system's default locale
|
||||||
loaded = translator.load(QLocale(), {}, {}, QStringLiteral(":/languages/"));
|
loaded = translator.load(QLocale::system(), {}, {}, QStringLiteral(":/languages/"));
|
||||||
} else {
|
} else {
|
||||||
// Otherwise load from the specified file
|
// Otherwise load from the specified file
|
||||||
loaded = translator.load(UISettings::values.language, QStringLiteral(":/languages/"));
|
loaded = translator.load(UISettings::values.language, QStringLiteral(":/languages/"));
|
||||||
|
@ -78,7 +78,8 @@ inline ABIFrameInfo ABI_CalculateFrameSize(std::bitset<64> regs, std::size_t fra
|
|||||||
return ABIFrameInfo{static_cast<u32>(total_size), static_cast<u32>(fprs_base_subtraction)};
|
return ABIFrameInfo{static_cast<u32>(total_size), static_cast<u32>(fprs_base_subtraction)};
|
||||||
}
|
}
|
||||||
|
|
||||||
inline void ABI_PushRegisters(oaknut::CodeGenerator& code, std::bitset<64> regs,
|
template <typename Policy>
|
||||||
|
inline void ABI_PushRegisters(oaknut::BasicCodeGenerator<Policy>& code, std::bitset<64> regs,
|
||||||
std::size_t frame_size = 0) {
|
std::size_t frame_size = 0) {
|
||||||
using namespace oaknut;
|
using namespace oaknut;
|
||||||
using namespace oaknut::util;
|
using namespace oaknut::util;
|
||||||
@ -137,7 +138,8 @@ inline void ABI_PushRegisters(oaknut::CodeGenerator& code, std::bitset<64> regs,
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
inline void ABI_PopRegisters(oaknut::CodeGenerator& code, std::bitset<64> regs,
|
template <typename Policy>
|
||||||
|
inline void ABI_PopRegisters(oaknut::BasicCodeGenerator<Policy>& code, std::bitset<64> regs,
|
||||||
std::size_t frame_size = 0) {
|
std::size_t frame_size = 0) {
|
||||||
using namespace oaknut;
|
using namespace oaknut;
|
||||||
using namespace oaknut::util;
|
using namespace oaknut::util;
|
||||||
|
@ -38,6 +38,16 @@ inline void CallFarFunction(oaknut::CodeGenerator& code, const T f) {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
template <typename T>
|
||||||
|
inline void CallFarFunction(oaknut::VectorCodeGenerator& code, const T f) {
|
||||||
|
static_assert(std::is_pointer_v<T>, "Argument must be a (function) pointer.");
|
||||||
|
// X16(IP0) and X17(IP1) is the standard veneer register
|
||||||
|
// LR is also available as an intermediate register
|
||||||
|
// https://developer.arm.com/documentation/102374/0101/Procedure-Call-Standard
|
||||||
|
code.MOVP2R(oaknut::util::X16, reinterpret_cast<const void*>(f));
|
||||||
|
code.BLR(oaknut::util::X16);
|
||||||
|
}
|
||||||
|
|
||||||
} // namespace Common::A64
|
} // namespace Common::A64
|
||||||
|
|
||||||
#endif // CITRA_ARCH(arm64)
|
#endif // CITRA_ARCH(arm64)
|
||||||
|
@ -65,6 +65,9 @@ avcodec_find_encoder_by_name_func avcodec_find_encoder_by_name;
|
|||||||
avcodec_free_context_func avcodec_free_context;
|
avcodec_free_context_func avcodec_free_context;
|
||||||
avcodec_get_class_func avcodec_get_class;
|
avcodec_get_class_func avcodec_get_class;
|
||||||
avcodec_get_hw_config_func avcodec_get_hw_config;
|
avcodec_get_hw_config_func avcodec_get_hw_config;
|
||||||
|
#if LIBAVCODEC_VERSION_INT >= AV_VERSION_INT(61, 13, 100) // lavc 61.13.100
|
||||||
|
avcodec_get_supported_config_func avcodec_get_supported_config;
|
||||||
|
#endif
|
||||||
avcodec_open2_func avcodec_open2;
|
avcodec_open2_func avcodec_open2;
|
||||||
avcodec_parameters_from_context_func avcodec_parameters_from_context;
|
avcodec_parameters_from_context_func avcodec_parameters_from_context;
|
||||||
avcodec_receive_frame_func avcodec_receive_frame;
|
avcodec_receive_frame_func avcodec_receive_frame;
|
||||||
@ -232,6 +235,9 @@ static bool LoadAVCodec() {
|
|||||||
LOAD_SYMBOL(avcodec, avcodec_free_context);
|
LOAD_SYMBOL(avcodec, avcodec_free_context);
|
||||||
LOAD_SYMBOL(avcodec, avcodec_get_class);
|
LOAD_SYMBOL(avcodec, avcodec_get_class);
|
||||||
LOAD_SYMBOL(avcodec, avcodec_get_hw_config);
|
LOAD_SYMBOL(avcodec, avcodec_get_hw_config);
|
||||||
|
#if LIBAVCODEC_VERSION_INT >= AV_VERSION_INT(61, 13, 100) // lavc 61.13.100
|
||||||
|
LOAD_SYMBOL(avcodec, avcodec_get_supported_config);
|
||||||
|
#endif
|
||||||
LOAD_SYMBOL(avcodec, avcodec_open2);
|
LOAD_SYMBOL(avcodec, avcodec_open2);
|
||||||
LOAD_SYMBOL(avcodec, avcodec_parameters_from_context);
|
LOAD_SYMBOL(avcodec, avcodec_parameters_from_context);
|
||||||
LOAD_SYMBOL(avcodec, avcodec_receive_frame);
|
LOAD_SYMBOL(avcodec, avcodec_receive_frame);
|
||||||
|
@ -114,6 +114,10 @@ typedef const AVCodec* (*avcodec_find_encoder_by_name_func)(const char*);
|
|||||||
typedef void (*avcodec_free_context_func)(AVCodecContext**);
|
typedef void (*avcodec_free_context_func)(AVCodecContext**);
|
||||||
typedef const AVClass* (*avcodec_get_class_func)();
|
typedef const AVClass* (*avcodec_get_class_func)();
|
||||||
typedef const AVCodecHWConfig* (*avcodec_get_hw_config_func)(const AVCodec*, int);
|
typedef const AVCodecHWConfig* (*avcodec_get_hw_config_func)(const AVCodec*, int);
|
||||||
|
#if LIBAVCODEC_VERSION_INT >= AV_VERSION_INT(61, 13, 100) // lavc 61.13.100
|
||||||
|
typedef int (*avcodec_get_supported_config_func)(const AVCodecContext*, const AVCodec*,
|
||||||
|
enum AVCodecConfig, unsigned, const void**, int*);
|
||||||
|
#endif
|
||||||
typedef int (*avcodec_open2_func)(AVCodecContext*, const AVCodec*, AVDictionary**);
|
typedef int (*avcodec_open2_func)(AVCodecContext*, const AVCodec*, AVDictionary**);
|
||||||
typedef int (*avcodec_parameters_from_context_func)(AVCodecParameters* par, const AVCodecContext*);
|
typedef int (*avcodec_parameters_from_context_func)(AVCodecParameters* par, const AVCodecContext*);
|
||||||
typedef int (*avcodec_receive_frame_func)(AVCodecContext*, AVFrame*);
|
typedef int (*avcodec_receive_frame_func)(AVCodecContext*, AVFrame*);
|
||||||
@ -138,6 +142,9 @@ extern avcodec_find_encoder_by_name_func avcodec_find_encoder_by_name;
|
|||||||
extern avcodec_free_context_func avcodec_free_context;
|
extern avcodec_free_context_func avcodec_free_context;
|
||||||
extern avcodec_get_class_func avcodec_get_class;
|
extern avcodec_get_class_func avcodec_get_class;
|
||||||
extern avcodec_get_hw_config_func avcodec_get_hw_config;
|
extern avcodec_get_hw_config_func avcodec_get_hw_config;
|
||||||
|
#if LIBAVCODEC_VERSION_INT >= AV_VERSION_INT(61, 13, 100) // lavc 61.13.100
|
||||||
|
extern avcodec_get_supported_config_func avcodec_get_supported_config;
|
||||||
|
#endif
|
||||||
extern avcodec_open2_func avcodec_open2;
|
extern avcodec_open2_func avcodec_open2;
|
||||||
extern avcodec_parameters_from_context_func avcodec_parameters_from_context;
|
extern avcodec_parameters_from_context_func avcodec_parameters_from_context;
|
||||||
extern avcodec_receive_frame_func avcodec_receive_frame;
|
extern avcodec_receive_frame_func avcodec_receive_frame;
|
||||||
|
@ -68,7 +68,7 @@ public:
|
|||||||
}
|
}
|
||||||
|
|
||||||
void Flush() override {
|
void Flush() override {
|
||||||
// stderr shouldn't be buffered
|
std::fflush(stderr);
|
||||||
}
|
}
|
||||||
|
|
||||||
void EnableForStacktrace() override {
|
void EnableForStacktrace() override {
|
||||||
@ -263,7 +263,14 @@ public:
|
|||||||
!boost::regex_search(FormatLogMessage(new_entry), regex_filter)) {
|
!boost::regex_search(FormatLogMessage(new_entry), regex_filter)) {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
message_queue.EmplaceWait(new_entry);
|
if (Settings::values.instant_debug_log.GetValue()) {
|
||||||
|
ForEachBackend([&new_entry](Backend& backend) {
|
||||||
|
backend.Write(new_entry);
|
||||||
|
backend.Flush();
|
||||||
|
});
|
||||||
|
} else {
|
||||||
|
message_queue.EmplaceWait(new_entry);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
private:
|
private:
|
||||||
|
@ -12,9 +12,9 @@
|
|||||||
#if FMT_VERSION >= 80100
|
#if FMT_VERSION >= 80100
|
||||||
template <typename T>
|
template <typename T>
|
||||||
struct fmt::formatter<T, std::enable_if_t<std::is_enum_v<T>, char>>
|
struct fmt::formatter<T, std::enable_if_t<std::is_enum_v<T>, char>>
|
||||||
: formatter<std::underlying_type_t<T>> {
|
: fmt::formatter<std::underlying_type_t<T>> {
|
||||||
template <typename FormatContext>
|
template <typename FormatContext>
|
||||||
auto format(const T& value, FormatContext& ctx) -> decltype(ctx.out()) {
|
auto format(const T& value, FormatContext& ctx) const -> decltype(ctx.out()) {
|
||||||
return fmt::formatter<std::underlying_type_t<T>>::format(
|
return fmt::formatter<std::underlying_type_t<T>>::format(
|
||||||
static_cast<std::underlying_type_t<T>>(value), ctx);
|
static_cast<std::underlying_type_t<T>>(value), ctx);
|
||||||
}
|
}
|
||||||
|
@ -83,6 +83,7 @@ void LogSettings() {
|
|||||||
LOG_INFO(Config, "Citra Configuration:");
|
LOG_INFO(Config, "Citra Configuration:");
|
||||||
log_setting("Core_UseCpuJit", values.use_cpu_jit.GetValue());
|
log_setting("Core_UseCpuJit", values.use_cpu_jit.GetValue());
|
||||||
log_setting("Core_CPUClockPercentage", values.cpu_clock_percentage.GetValue());
|
log_setting("Core_CPUClockPercentage", values.cpu_clock_percentage.GetValue());
|
||||||
|
log_setting("Controller_UseArticController", values.use_artic_base_controller.GetValue());
|
||||||
log_setting("Renderer_UseGLES", values.use_gles.GetValue());
|
log_setting("Renderer_UseGLES", values.use_gles.GetValue());
|
||||||
log_setting("Renderer_GraphicsAPI", GetGraphicsAPIName(values.graphics_api.GetValue()));
|
log_setting("Renderer_GraphicsAPI", GetGraphicsAPIName(values.graphics_api.GetValue()));
|
||||||
log_setting("Renderer_AsyncShaders", values.async_shader_compilation.GetValue());
|
log_setting("Renderer_AsyncShaders", values.async_shader_compilation.GetValue());
|
||||||
@ -100,6 +101,7 @@ void LogSettings() {
|
|||||||
log_setting("Renderer_TextureFilter", GetTextureFilterName(values.texture_filter.GetValue()));
|
log_setting("Renderer_TextureFilter", GetTextureFilterName(values.texture_filter.GetValue()));
|
||||||
log_setting("Renderer_TextureSampling",
|
log_setting("Renderer_TextureSampling",
|
||||||
GetTextureSamplingName(values.texture_sampling.GetValue()));
|
GetTextureSamplingName(values.texture_sampling.GetValue()));
|
||||||
|
log_setting("Renderer_DelayGameRenderThreasUs", values.delay_game_render_thread_us.GetValue());
|
||||||
log_setting("Stereoscopy_Render3d", values.render_3d.GetValue());
|
log_setting("Stereoscopy_Render3d", values.render_3d.GetValue());
|
||||||
log_setting("Stereoscopy_Factor3d", values.factor_3d.GetValue());
|
log_setting("Stereoscopy_Factor3d", values.factor_3d.GetValue());
|
||||||
log_setting("Stereoscopy_MonoRenderOption", values.mono_render_option.GetValue());
|
log_setting("Stereoscopy_MonoRenderOption", values.mono_render_option.GetValue());
|
||||||
@ -145,6 +147,7 @@ void LogSettings() {
|
|||||||
log_setting("Debugging_DelayStartForLLEModules", values.delay_start_for_lle_modules.GetValue());
|
log_setting("Debugging_DelayStartForLLEModules", values.delay_start_for_lle_modules.GetValue());
|
||||||
log_setting("Debugging_UseGdbstub", values.use_gdbstub.GetValue());
|
log_setting("Debugging_UseGdbstub", values.use_gdbstub.GetValue());
|
||||||
log_setting("Debugging_GdbstubPort", values.gdbstub_port.GetValue());
|
log_setting("Debugging_GdbstubPort", values.gdbstub_port.GetValue());
|
||||||
|
log_setting("Debugging_InstantDebugLog", values.instant_debug_log.GetValue());
|
||||||
}
|
}
|
||||||
|
|
||||||
bool IsConfiguringGlobal() {
|
bool IsConfiguringGlobal() {
|
||||||
@ -192,6 +195,7 @@ void RestoreGlobalState(bool is_powered_on) {
|
|||||||
values.frame_limit.SetGlobal(true);
|
values.frame_limit.SetGlobal(true);
|
||||||
values.texture_filter.SetGlobal(true);
|
values.texture_filter.SetGlobal(true);
|
||||||
values.texture_sampling.SetGlobal(true);
|
values.texture_sampling.SetGlobal(true);
|
||||||
|
values.delay_game_render_thread_us.SetGlobal(true);
|
||||||
values.layout_option.SetGlobal(true);
|
values.layout_option.SetGlobal(true);
|
||||||
values.swap_screen.SetGlobal(true);
|
values.swap_screen.SetGlobal(true);
|
||||||
values.upright_screen.SetGlobal(true);
|
values.upright_screen.SetGlobal(true);
|
||||||
|
@ -425,6 +425,7 @@ struct Values {
|
|||||||
int current_input_profile_index; ///< The current input profile index
|
int current_input_profile_index; ///< The current input profile index
|
||||||
std::vector<InputProfile> input_profiles; ///< The list of input profiles
|
std::vector<InputProfile> input_profiles; ///< The list of input profiles
|
||||||
std::vector<TouchFromButtonMap> touch_from_button_maps;
|
std::vector<TouchFromButtonMap> touch_from_button_maps;
|
||||||
|
Setting<bool> use_artic_base_controller{false, "use_artic_base_controller"};
|
||||||
|
|
||||||
SwitchableSetting<bool> enable_gamemode{true, "enable_gamemode"};
|
SwitchableSetting<bool> enable_gamemode{true, "enable_gamemode"};
|
||||||
|
|
||||||
@ -447,6 +448,7 @@ struct Values {
|
|||||||
Setting<s64> init_ticks_override{0, "init_ticks_override"};
|
Setting<s64> init_ticks_override{0, "init_ticks_override"};
|
||||||
Setting<bool> plugin_loader_enabled{false, "plugin_loader"};
|
Setting<bool> plugin_loader_enabled{false, "plugin_loader"};
|
||||||
Setting<bool> allow_plugin_loader{true, "allow_plugin_loader"};
|
Setting<bool> allow_plugin_loader{true, "allow_plugin_loader"};
|
||||||
|
Setting<u16> steps_per_hour{0, "steps_per_hour"};
|
||||||
|
|
||||||
// Renderer
|
// Renderer
|
||||||
SwitchableSetting<GraphicsAPI, true> graphics_api {
|
SwitchableSetting<GraphicsAPI, true> graphics_api {
|
||||||
@ -479,6 +481,8 @@ struct Values {
|
|||||||
SwitchableSetting<TextureFilter> texture_filter{TextureFilter::None, "texture_filter"};
|
SwitchableSetting<TextureFilter> texture_filter{TextureFilter::None, "texture_filter"};
|
||||||
SwitchableSetting<TextureSampling> texture_sampling{TextureSampling::GameControlled,
|
SwitchableSetting<TextureSampling> texture_sampling{TextureSampling::GameControlled,
|
||||||
"texture_sampling"};
|
"texture_sampling"};
|
||||||
|
SwitchableSetting<u16, true> delay_game_render_thread_us{0, 0, 16000,
|
||||||
|
"delay_game_render_thread_us"};
|
||||||
|
|
||||||
SwitchableSetting<LayoutOption> layout_option{LayoutOption::Default, "layout_option"};
|
SwitchableSetting<LayoutOption> layout_option{LayoutOption::Default, "layout_option"};
|
||||||
SwitchableSetting<bool> swap_screen{false, "swap_screen"};
|
SwitchableSetting<bool> swap_screen{false, "swap_screen"};
|
||||||
@ -539,6 +543,7 @@ struct Values {
|
|||||||
Setting<bool> delay_start_for_lle_modules{true, "delay_start_for_lle_modules"};
|
Setting<bool> delay_start_for_lle_modules{true, "delay_start_for_lle_modules"};
|
||||||
Setting<bool> use_gdbstub{false, "use_gdbstub"};
|
Setting<bool> use_gdbstub{false, "use_gdbstub"};
|
||||||
Setting<u16> gdbstub_port{24689, "gdbstub_port"};
|
Setting<u16> gdbstub_port{24689, "gdbstub_port"};
|
||||||
|
Setting<bool> instant_debug_log{false, "instant_debug_log"};
|
||||||
|
|
||||||
// Miscellaneous
|
// Miscellaneous
|
||||||
Setting<std::string> log_filter{"*:Info", "log_filter"};
|
Setting<std::string> log_filter{"*:Info", "log_filter"};
|
||||||
|
@ -203,6 +203,8 @@ add_library(citra_core STATIC
|
|||||||
hle/service/ac/ac_u.h
|
hle/service/ac/ac_u.h
|
||||||
hle/service/act/act.cpp
|
hle/service/act/act.cpp
|
||||||
hle/service/act/act.h
|
hle/service/act/act.h
|
||||||
|
hle/service/act/act_errors.cpp
|
||||||
|
hle/service/act/act_errors.h
|
||||||
hle/service/act/act_a.cpp
|
hle/service/act/act_a.cpp
|
||||||
hle/service/act/act_a.h
|
hle/service/act/act_a.h
|
||||||
hle/service/act/act_u.cpp
|
hle/service/act/act_u.cpp
|
||||||
|
@ -171,12 +171,21 @@ bool FFmpegVideoStream::Init(FFmpegMuxer& muxer, const Layout::FramebufferLayout
|
|||||||
codec_context->gop_size = 12;
|
codec_context->gop_size = 12;
|
||||||
|
|
||||||
// Get pixel format for codec
|
// Get pixel format for codec
|
||||||
|
#if LIBAVCODEC_VERSION_INT >= AV_VERSION_INT(61, 13, 100) // lavc 61.13.100
|
||||||
|
const enum AVPixelFormat* pix_fmts = NULL;
|
||||||
|
int ret = FFmpeg::avcodec_get_supported_config(NULL, codec, AV_CODEC_CONFIG_PIX_FORMAT, 0,
|
||||||
|
(const void**)&pix_fmts, NULL);
|
||||||
|
#else
|
||||||
|
const enum AVPixelFormat* pix_fmts = codec->pix_fmts;
|
||||||
|
int ret = 0;
|
||||||
|
#endif
|
||||||
|
|
||||||
auto options = ToAVDictionary(Settings::values.video_encoder_options);
|
auto options = ToAVDictionary(Settings::values.video_encoder_options);
|
||||||
auto pixel_format_opt = FFmpeg::av_dict_get(options, "pixel_format", nullptr, 0);
|
auto pixel_format_opt = FFmpeg::av_dict_get(options, "pixel_format", nullptr, 0);
|
||||||
if (pixel_format_opt) {
|
if (pixel_format_opt) {
|
||||||
sw_pixel_format = FFmpeg::av_get_pix_fmt(pixel_format_opt->value);
|
sw_pixel_format = FFmpeg::av_get_pix_fmt(pixel_format_opt->value);
|
||||||
} else if (codec->pix_fmts) {
|
} else if (ret >= 0 && pix_fmts) {
|
||||||
sw_pixel_format = GetPixelFormat(codec_context.get(), codec->pix_fmts);
|
sw_pixel_format = GetPixelFormat(codec_context.get(), pix_fmts);
|
||||||
} else {
|
} else {
|
||||||
sw_pixel_format = AV_PIX_FMT_YUV420P;
|
sw_pixel_format = AV_PIX_FMT_YUV420P;
|
||||||
}
|
}
|
||||||
@ -285,11 +294,20 @@ void FFmpegVideoStream::ProcessFrame(VideoFrame& frame) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
bool FFmpegVideoStream::InitHWContext(const AVCodec* codec) {
|
bool FFmpegVideoStream::InitHWContext(const AVCodec* codec) {
|
||||||
for (std::size_t i = 0; codec->pix_fmts[i] != AV_PIX_FMT_NONE; ++i) {
|
#if LIBAVCODEC_VERSION_INT >= AV_VERSION_INT(61, 13, 100) // lavc 61.13.100
|
||||||
|
const enum AVPixelFormat* pix_fmts = NULL;
|
||||||
|
int ret = FFmpeg::avcodec_get_supported_config(NULL, codec, AV_CODEC_CONFIG_PIX_FORMAT, 0,
|
||||||
|
(const void**)&pix_fmts, NULL);
|
||||||
|
#else
|
||||||
|
const enum AVPixelFormat* pix_fmts = codec->pix_fmts;
|
||||||
|
int ret = 0;
|
||||||
|
#endif
|
||||||
|
|
||||||
|
for (std::size_t i = 0; (ret >= 0 && pix_fmts) && (pix_fmts[i] != AV_PIX_FMT_NONE); ++i) {
|
||||||
const AVCodecHWConfig* config;
|
const AVCodecHWConfig* config;
|
||||||
for (int j = 0;; ++j) {
|
for (int j = 0;; ++j) {
|
||||||
config = FFmpeg::avcodec_get_hw_config(codec, j);
|
config = FFmpeg::avcodec_get_hw_config(codec, j);
|
||||||
if (!config || config->pix_fmt == codec->pix_fmts[i]) {
|
if (!config || config->pix_fmt == pix_fmts[i]) {
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -303,7 +321,7 @@ bool FFmpegVideoStream::InitHWContext(const AVCodec* codec) {
|
|||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
|
|
||||||
codec_context->pix_fmt = codec->pix_fmts[i];
|
codec_context->pix_fmt = pix_fmts[i];
|
||||||
|
|
||||||
// Create HW device context
|
// Create HW device context
|
||||||
AVBufferRef* hw_device_context;
|
AVBufferRef* hw_device_context;
|
||||||
@ -351,7 +369,7 @@ bool FFmpegVideoStream::InitHWContext(const AVCodec* codec) {
|
|||||||
|
|
||||||
AVHWFramesContext* hw_frames_context =
|
AVHWFramesContext* hw_frames_context =
|
||||||
reinterpret_cast<AVHWFramesContext*>(hw_frames_context_ref->data);
|
reinterpret_cast<AVHWFramesContext*>(hw_frames_context_ref->data);
|
||||||
hw_frames_context->format = codec->pix_fmts[i];
|
hw_frames_context->format = pix_fmts[i];
|
||||||
hw_frames_context->sw_format = sw_pixel_format;
|
hw_frames_context->sw_format = sw_pixel_format;
|
||||||
hw_frames_context->width = codec_context->width;
|
hw_frames_context->width = codec_context->width;
|
||||||
hw_frames_context->height = codec_context->height;
|
hw_frames_context->height = codec_context->height;
|
||||||
@ -455,6 +473,7 @@ bool FFmpegAudioStream::Init(FFmpegMuxer& muxer) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
frame_count = 0;
|
frame_count = 0;
|
||||||
|
int ret;
|
||||||
|
|
||||||
// Initialize audio codec
|
// Initialize audio codec
|
||||||
const AVCodec* codec =
|
const AVCodec* codec =
|
||||||
@ -468,16 +487,33 @@ bool FFmpegAudioStream::Init(FFmpegMuxer& muxer) {
|
|||||||
// Configure audio codec context
|
// Configure audio codec context
|
||||||
codec_context->codec_type = AVMEDIA_TYPE_AUDIO;
|
codec_context->codec_type = AVMEDIA_TYPE_AUDIO;
|
||||||
codec_context->bit_rate = Settings::values.audio_bitrate;
|
codec_context->bit_rate = Settings::values.audio_bitrate;
|
||||||
if (codec->sample_fmts) {
|
|
||||||
codec_context->sample_fmt = codec->sample_fmts[0];
|
#if LIBAVCODEC_VERSION_INT >= AV_VERSION_INT(61, 13, 100) // lavc 61.13.100
|
||||||
|
const enum AVSampleFormat* sample_fmts = NULL;
|
||||||
|
ret = FFmpeg::avcodec_get_supported_config(NULL, codec, AV_CODEC_CONFIG_SAMPLE_FORMAT, 0,
|
||||||
|
(const void**)&sample_fmts, NULL);
|
||||||
|
#else
|
||||||
|
const enum AVSampleFormat* sample_fmts = codec->sample_fmts;
|
||||||
|
ret = 0;
|
||||||
|
#endif
|
||||||
|
if (ret >= 0 && sample_fmts) {
|
||||||
|
codec_context->sample_fmt = sample_fmts[0];
|
||||||
} else {
|
} else {
|
||||||
codec_context->sample_fmt = AV_SAMPLE_FMT_S16P;
|
codec_context->sample_fmt = AV_SAMPLE_FMT_S16P;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (codec->supported_samplerates) {
|
#if LIBAVCODEC_VERSION_INT >= AV_VERSION_INT(61, 13, 100) // lavc 61.13.100
|
||||||
codec_context->sample_rate = codec->supported_samplerates[0];
|
const int* supported_samplerates = NULL;
|
||||||
|
ret = FFmpeg::avcodec_get_supported_config(NULL, codec, AV_CODEC_CONFIG_SAMPLE_RATE, 0,
|
||||||
|
(const void**)&supported_samplerates, NULL);
|
||||||
|
#else
|
||||||
|
const int* supported_samplerates = codec->supported_samplerates;
|
||||||
|
ret = 0;
|
||||||
|
#endif
|
||||||
|
if (ret >= 0 && supported_samplerates) {
|
||||||
|
codec_context->sample_rate = supported_samplerates[0];
|
||||||
// Prefer native sample rate if supported
|
// Prefer native sample rate if supported
|
||||||
const int* ptr = codec->supported_samplerates;
|
const int* ptr = supported_samplerates;
|
||||||
while ((*ptr)) {
|
while ((*ptr)) {
|
||||||
if ((*ptr) == AudioCore::native_sample_rate) {
|
if ((*ptr) == AudioCore::native_sample_rate) {
|
||||||
codec_context->sample_rate = AudioCore::native_sample_rate;
|
codec_context->sample_rate = AudioCore::native_sample_rate;
|
||||||
@ -956,7 +992,7 @@ std::string FormatDefaultValue(const AVOption* option,
|
|||||||
case AV_OPT_TYPE_VIDEO_RATE: {
|
case AV_OPT_TYPE_VIDEO_RATE: {
|
||||||
return ToStdString(option->default_val.str);
|
return ToStdString(option->default_val.str);
|
||||||
}
|
}
|
||||||
case AV_OPT_TYPE_CHANNEL_LAYOUT: {
|
case AV_OPT_TYPE_CHLAYOUT: {
|
||||||
return fmt::format("{:#x}", option->default_val.i64);
|
return fmt::format("{:#x}", option->default_val.i64);
|
||||||
}
|
}
|
||||||
default:
|
default:
|
||||||
|
@ -387,24 +387,35 @@ ResultVal<std::size_t> ArticFileBackend::Read(u64 offset, std::size_t length, u8
|
|||||||
return cache->Read(file_handle, offset, length, buffer);
|
return cache->Read(file_handle, offset, length, buffer);
|
||||||
}
|
}
|
||||||
|
|
||||||
auto req = client->NewRequest("FSFILE_Read");
|
size_t read_amount = 0;
|
||||||
|
while (read_amount != length) {
|
||||||
|
size_t to_read =
|
||||||
|
std::min<size_t>(client->GetServerRequestMaxSize() - 0x100, length - read_amount);
|
||||||
|
|
||||||
req.AddParameterS32(file_handle);
|
auto req = client->NewRequest("FSFILE_Read");
|
||||||
req.AddParameterU64(offset);
|
req.AddParameterS32(file_handle);
|
||||||
req.AddParameterU32(static_cast<u32>(length));
|
req.AddParameterS64(static_cast<s64>(offset + read_amount));
|
||||||
|
req.AddParameterS32(static_cast<s32>(to_read));
|
||||||
|
auto resp = client->Send(req);
|
||||||
|
if (!resp.has_value() || !resp->Succeeded())
|
||||||
|
return Result(-1);
|
||||||
|
|
||||||
auto resp = client->Send(req);
|
auto res = Result(static_cast<u32>(resp->GetMethodResult()));
|
||||||
auto res = ArticArchive::RespResult(resp);
|
if (res.IsError())
|
||||||
if (res.IsError())
|
return res;
|
||||||
return res;
|
|
||||||
|
|
||||||
auto read_buf = resp->GetResponseBuffer(0);
|
auto read_buff = resp->GetResponseBuffer(0);
|
||||||
if (!read_buf || read_buf->second > length) {
|
size_t actually_read = 0;
|
||||||
return std::size_t(0);
|
if (read_buff.has_value()) {
|
||||||
|
actually_read = read_buff->second;
|
||||||
|
memcpy(buffer + read_amount, read_buff->first, actually_read);
|
||||||
|
}
|
||||||
|
|
||||||
|
read_amount += actually_read;
|
||||||
|
if (actually_read != to_read)
|
||||||
|
break;
|
||||||
}
|
}
|
||||||
|
return read_amount;
|
||||||
memcpy(buffer, read_buf->first, read_buf->second);
|
|
||||||
return read_buf->second;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
ResultVal<std::size_t> ArticFileBackend::Write(u64 offset, std::size_t length, bool flush,
|
ResultVal<std::size_t> ArticFileBackend::Write(u64 offset, std::size_t length, bool flush,
|
||||||
@ -415,25 +426,36 @@ ResultVal<std::size_t> ArticFileBackend::Write(u64 offset, std::size_t length, b
|
|||||||
if (cache != nullptr) {
|
if (cache != nullptr) {
|
||||||
return cache->Write(file_handle, offset, length, buffer, flags);
|
return cache->Write(file_handle, offset, length, buffer, flags);
|
||||||
} else {
|
} else {
|
||||||
auto req = client->NewRequest("FSFILE_Write");
|
size_t written_amount = 0;
|
||||||
|
while (written_amount != length) {
|
||||||
|
size_t to_write = std::min<size_t>(client->GetServerRequestMaxSize() - 0x100,
|
||||||
|
length - written_amount);
|
||||||
|
|
||||||
req.AddParameterS32(file_handle);
|
auto req = client->NewRequest("FSFILE_Write");
|
||||||
req.AddParameterU64(offset);
|
req.AddParameterS32(file_handle);
|
||||||
req.AddParameterU32(static_cast<u32>(length));
|
req.AddParameterS64(static_cast<s64>(offset + written_amount));
|
||||||
req.AddParameterU32(flags);
|
req.AddParameterS32(static_cast<s32>(to_write));
|
||||||
req.AddParameterBuffer(buffer, length);
|
req.AddParameterS32(static_cast<s32>(flags));
|
||||||
|
req.AddParameterBuffer(buffer + written_amount, to_write);
|
||||||
|
auto resp = client->Send(req);
|
||||||
|
if (!resp.has_value() || !resp->Succeeded())
|
||||||
|
return Result(-1);
|
||||||
|
|
||||||
auto resp = client->Send(req);
|
auto res = Result(static_cast<u32>(resp->GetMethodResult()));
|
||||||
auto res = ArticArchive::RespResult(resp);
|
if (res.IsError())
|
||||||
if (res.IsError())
|
return res;
|
||||||
return res;
|
|
||||||
|
|
||||||
auto writen_buf = resp->GetResponseS32(0);
|
auto actually_written_opt = resp->GetResponseS32(0);
|
||||||
if (!writen_buf) {
|
if (!actually_written_opt.has_value())
|
||||||
return std::size_t(0);
|
return Result(-1);
|
||||||
|
|
||||||
|
size_t actually_written = static_cast<size_t>(actually_written_opt.value());
|
||||||
|
|
||||||
|
written_amount += actually_written;
|
||||||
|
if (actually_written != to_write)
|
||||||
|
break;
|
||||||
}
|
}
|
||||||
|
return written_amount;
|
||||||
return std::size_t(*writen_buf);
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -10,6 +10,7 @@
|
|||||||
#include "common/archives.h"
|
#include "common/archives.h"
|
||||||
#include "common/common_types.h"
|
#include "common/common_types.h"
|
||||||
#include "common/file_util.h"
|
#include "common/file_util.h"
|
||||||
|
#include "core/file_sys/archive_artic.h"
|
||||||
#include "core/file_sys/archive_systemsavedata.h"
|
#include "core/file_sys/archive_systemsavedata.h"
|
||||||
#include "core/file_sys/errors.h"
|
#include "core/file_sys/errors.h"
|
||||||
#include "core/file_sys/savedata_archive.h"
|
#include "core/file_sys/savedata_archive.h"
|
||||||
@ -52,24 +53,45 @@ Path ConstructSystemSaveDataBinaryPath(u32 high, u32 low) {
|
|||||||
ArchiveFactory_SystemSaveData::ArchiveFactory_SystemSaveData(const std::string& nand_path)
|
ArchiveFactory_SystemSaveData::ArchiveFactory_SystemSaveData(const std::string& nand_path)
|
||||||
: base_path(GetSystemSaveDataContainerPath(nand_path)) {}
|
: base_path(GetSystemSaveDataContainerPath(nand_path)) {}
|
||||||
|
|
||||||
|
static bool AllowArticSystemSaveData(const Path& path) {
|
||||||
|
constexpr u32 APP_SYSTEM_SAVE_DATA_MASK = 0x00020000;
|
||||||
|
if (path.GetType() == FileSys::LowPathType::Binary) {
|
||||||
|
std::vector<u8> path_data = path.AsBinary();
|
||||||
|
return path_data.size() == 8 &&
|
||||||
|
(*reinterpret_cast<u32*>(path_data.data() + 4) & APP_SYSTEM_SAVE_DATA_MASK) != 0;
|
||||||
|
}
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
ResultVal<std::unique_ptr<ArchiveBackend>> ArchiveFactory_SystemSaveData::Open(const Path& path,
|
ResultVal<std::unique_ptr<ArchiveBackend>> ArchiveFactory_SystemSaveData::Open(const Path& path,
|
||||||
u64 program_id) {
|
u64 program_id) {
|
||||||
std::string fullpath = GetSystemSaveDataPath(base_path, path);
|
if (IsUsingArtic() && AllowArticSystemSaveData(path)) {
|
||||||
if (!FileUtil::Exists(fullpath)) {
|
EnsureCacheCreated();
|
||||||
// TODO(Subv): Check error code, this one is probably wrong
|
return ArticArchive::Open(artic_client, Service::FS::ArchiveIdCode::SystemSaveData, path,
|
||||||
return ResultNotFound;
|
Core::PerfStats::PerfArticEventBits::ARTIC_SYSTEM_SAVE_DATA,
|
||||||
|
*this, false);
|
||||||
|
} else {
|
||||||
|
std::string fullpath = GetSystemSaveDataPath(base_path, path);
|
||||||
|
if (!FileUtil::Exists(fullpath)) {
|
||||||
|
// TODO(Subv): Check error code, this one is probably wrong
|
||||||
|
return ResultNotFound;
|
||||||
|
}
|
||||||
|
return std::make_unique<SaveDataArchive>(fullpath);
|
||||||
}
|
}
|
||||||
return std::make_unique<SaveDataArchive>(fullpath);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
Result ArchiveFactory_SystemSaveData::Format(const Path& path,
|
Result ArchiveFactory_SystemSaveData::Format(const Path& path,
|
||||||
const FileSys::ArchiveFormatInfo& format_info,
|
const FileSys::ArchiveFormatInfo& format_info,
|
||||||
u64 program_id, u32 directory_buckets,
|
u64 program_id, u32 directory_buckets,
|
||||||
u32 file_buckets) {
|
u32 file_buckets) {
|
||||||
std::string fullpath = GetSystemSaveDataPath(base_path, path);
|
const std::vector<u8> vec_data = path.AsBinary();
|
||||||
FileUtil::DeleteDirRecursively(fullpath);
|
u32 save_low;
|
||||||
FileUtil::CreateFullPath(fullpath);
|
u32 save_high;
|
||||||
return ResultSuccess;
|
std::memcpy(&save_low, &vec_data[4], sizeof(u32));
|
||||||
|
std::memcpy(&save_high, &vec_data[0], sizeof(u32));
|
||||||
|
return FormatAsSysData(save_high, save_low, format_info.total_size, 0x1000,
|
||||||
|
format_info.number_directories, format_info.number_files,
|
||||||
|
directory_buckets, file_buckets, format_info.duplicate_data);
|
||||||
}
|
}
|
||||||
|
|
||||||
ResultVal<ArchiveFormatInfo> ArchiveFactory_SystemSaveData::GetFormatInfo(const Path& path,
|
ResultVal<ArchiveFormatInfo> ArchiveFactory_SystemSaveData::GetFormatInfo(const Path& path,
|
||||||
@ -79,4 +101,45 @@ ResultVal<ArchiveFormatInfo> ArchiveFactory_SystemSaveData::GetFormatInfo(const
|
|||||||
return ResultUnknown;
|
return ResultUnknown;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
Result ArchiveFactory_SystemSaveData::FormatAsSysData(u32 high, u32 low, u32 total_size,
|
||||||
|
u32 block_size, u32 number_directories,
|
||||||
|
u32 number_files,
|
||||||
|
u32 number_directory_buckets,
|
||||||
|
u32 number_file_buckets, u8 duplicate_data) {
|
||||||
|
if (IsUsingArtic() &&
|
||||||
|
AllowArticSystemSaveData(FileSys::ConstructSystemSaveDataBinaryPath(high, low))) {
|
||||||
|
auto req = artic_client->NewRequest("FSUSER_CreateSysSaveData");
|
||||||
|
|
||||||
|
req.AddParameterU32(high);
|
||||||
|
req.AddParameterU32(low);
|
||||||
|
req.AddParameterU32(total_size);
|
||||||
|
req.AddParameterU32(block_size);
|
||||||
|
req.AddParameterU32(number_directories);
|
||||||
|
req.AddParameterU32(number_files);
|
||||||
|
req.AddParameterU32(number_directory_buckets);
|
||||||
|
req.AddParameterU32(number_file_buckets);
|
||||||
|
req.AddParameterU8(duplicate_data);
|
||||||
|
|
||||||
|
auto resp = artic_client->Send(req);
|
||||||
|
if (!resp.has_value() || !resp->Succeeded()) {
|
||||||
|
return ResultUnknown;
|
||||||
|
}
|
||||||
|
|
||||||
|
Result res(static_cast<u32>(resp->GetMethodResult()));
|
||||||
|
return res;
|
||||||
|
|
||||||
|
} else {
|
||||||
|
// Construct the binary path to the archive first
|
||||||
|
const FileSys::Path path = FileSys::ConstructSystemSaveDataBinaryPath(high, low);
|
||||||
|
|
||||||
|
const std::string& nand_directory = FileUtil::GetUserPath(FileUtil::UserPath::NANDDir);
|
||||||
|
const std::string base_path = FileSys::GetSystemSaveDataContainerPath(nand_directory);
|
||||||
|
const std::string systemsavedata_path = FileSys::GetSystemSaveDataPath(base_path, path);
|
||||||
|
if (!FileUtil::CreateFullPath(systemsavedata_path)) {
|
||||||
|
return ResultUnknown; // TODO(Subv): Find the right error code
|
||||||
|
}
|
||||||
|
return ResultSuccess;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
} // namespace FileSys
|
} // namespace FileSys
|
||||||
|
@ -10,12 +10,15 @@
|
|||||||
#include <boost/serialization/string.hpp>
|
#include <boost/serialization/string.hpp>
|
||||||
#include "common/common_types.h"
|
#include "common/common_types.h"
|
||||||
#include "core/file_sys/archive_backend.h"
|
#include "core/file_sys/archive_backend.h"
|
||||||
|
#include "core/file_sys/artic_cache.h"
|
||||||
#include "core/hle/result.h"
|
#include "core/hle/result.h"
|
||||||
|
#include "core/hle/service/fs/archive.h"
|
||||||
|
#include "network/artic_base/artic_base_client.h"
|
||||||
|
|
||||||
namespace FileSys {
|
namespace FileSys {
|
||||||
|
|
||||||
/// File system interface to the SystemSaveData archive
|
/// File system interface to the SystemSaveData archive
|
||||||
class ArchiveFactory_SystemSaveData final : public ArchiveFactory {
|
class ArchiveFactory_SystemSaveData final : public ArchiveFactory, public ArticCacheProvider {
|
||||||
public:
|
public:
|
||||||
explicit ArchiveFactory_SystemSaveData(const std::string& mount_point);
|
explicit ArchiveFactory_SystemSaveData(const std::string& mount_point);
|
||||||
|
|
||||||
@ -24,13 +27,31 @@ public:
|
|||||||
u32 directory_buckets, u32 file_buckets) override;
|
u32 directory_buckets, u32 file_buckets) override;
|
||||||
ResultVal<ArchiveFormatInfo> GetFormatInfo(const Path& path, u64 program_id) const override;
|
ResultVal<ArchiveFormatInfo> GetFormatInfo(const Path& path, u64 program_id) const override;
|
||||||
|
|
||||||
|
Result FormatAsSysData(u32 high, u32 low, u32 total_size, u32 block_size,
|
||||||
|
u32 number_directories, u32 number_files, u32 number_directory_buckets,
|
||||||
|
u32 number_file_buckets, u8 duplicate_data);
|
||||||
|
|
||||||
std::string GetName() const override {
|
std::string GetName() const override {
|
||||||
return "SystemSaveData";
|
return "SystemSaveData";
|
||||||
}
|
}
|
||||||
|
|
||||||
|
bool IsSlow() override {
|
||||||
|
return IsUsingArtic();
|
||||||
|
}
|
||||||
|
|
||||||
|
void RegisterArtic(std::shared_ptr<Network::ArticBase::Client>& client) {
|
||||||
|
artic_client = client;
|
||||||
|
}
|
||||||
|
|
||||||
|
bool IsUsingArtic() const {
|
||||||
|
return artic_client.get() != nullptr;
|
||||||
|
}
|
||||||
|
|
||||||
private:
|
private:
|
||||||
std::string base_path;
|
std::string base_path;
|
||||||
|
|
||||||
|
std::shared_ptr<Network::ArticBase::Client> artic_client = nullptr;
|
||||||
|
|
||||||
ArchiveFactory_SystemSaveData() = default;
|
ArchiveFactory_SystemSaveData() = default;
|
||||||
template <class Archive>
|
template <class Archive>
|
||||||
void serialize(Archive& ar, const unsigned int) {
|
void serialize(Archive& ar, const unsigned int) {
|
||||||
|
@ -200,11 +200,12 @@ ResultVal<size_t> ArticCache::ReadFromArtic(s32 file_handle, u8* buffer, size_t
|
|||||||
return res;
|
return res;
|
||||||
|
|
||||||
auto read_buff = resp->GetResponseBuffer(0);
|
auto read_buff = resp->GetResponseBuffer(0);
|
||||||
if (!read_buff.has_value())
|
size_t actually_read = 0;
|
||||||
return Result(-1);
|
if (read_buff.has_value()) {
|
||||||
size_t actually_read = read_buff->second;
|
actually_read = read_buff->second;
|
||||||
|
memcpy(buffer + read_amount, read_buff->first, actually_read);
|
||||||
|
}
|
||||||
|
|
||||||
memcpy(buffer + read_amount, read_buff->first, actually_read);
|
|
||||||
read_amount += actually_read;
|
read_amount += actually_read;
|
||||||
if (actually_read != to_read)
|
if (actually_read != to_read)
|
||||||
break;
|
break;
|
||||||
|
@ -179,6 +179,8 @@ Loader::ResultStatus FileSys::Plugin3GXLoader::Map(
|
|||||||
4 * 1024 * 1024 // 4 MiB
|
4 * 1024 * 1024 // 4 MiB
|
||||||
};
|
};
|
||||||
|
|
||||||
|
const bool is_mem_private = header.infos.flags.use_private_memory != 0;
|
||||||
|
|
||||||
// Map memory block. This behaviour mimics how plugins are loaded on 3DS as much as possible.
|
// Map memory block. This behaviour mimics how plugins are loaded on 3DS as much as possible.
|
||||||
// Calculate the sizes of the different memory regions
|
// Calculate the sizes of the different memory regions
|
||||||
const u32 block_size = mem_region_sizes[header.infos.flags.memory_region_size.Value()];
|
const u32 block_size = mem_region_sizes[header.infos.flags.memory_region_size.Value()];
|
||||||
@ -199,7 +201,8 @@ Loader::ResultStatus FileSys::Plugin3GXLoader::Map(
|
|||||||
std::fill(backing_memory_fb.GetPtr(), backing_memory_fb.GetPtr() + _3GX_fb_size, 0);
|
std::fill(backing_memory_fb.GetPtr(), backing_memory_fb.GetPtr() + _3GX_fb_size, 0);
|
||||||
|
|
||||||
auto vma_heap_fb = process.vm_manager.MapBackingMemory(
|
auto vma_heap_fb = process.vm_manager.MapBackingMemory(
|
||||||
_3GX_heap_load_addr, backing_memory_fb, _3GX_fb_size, Kernel::MemoryState::Continuous);
|
_3GX_heap_load_addr, backing_memory_fb, _3GX_fb_size,
|
||||||
|
is_mem_private ? Kernel::MemoryState::Private : Kernel::MemoryState::Shared);
|
||||||
ASSERT(vma_heap_fb.Succeeded());
|
ASSERT(vma_heap_fb.Succeeded());
|
||||||
process.vm_manager.Reprotect(vma_heap_fb.Unwrap(), Kernel::VMAPermission::ReadWrite);
|
process.vm_manager.Reprotect(vma_heap_fb.Unwrap(), Kernel::VMAPermission::ReadWrite);
|
||||||
|
|
||||||
@ -217,7 +220,8 @@ Loader::ResultStatus FileSys::Plugin3GXLoader::Map(
|
|||||||
|
|
||||||
// Then we map part of the memory, which contains the executable
|
// Then we map part of the memory, which contains the executable
|
||||||
auto vma = process.vm_manager.MapBackingMemory(_3GX_exe_load_addr, backing_memory, exe_size,
|
auto vma = process.vm_manager.MapBackingMemory(_3GX_exe_load_addr, backing_memory, exe_size,
|
||||||
Kernel::MemoryState::Continuous);
|
is_mem_private ? Kernel::MemoryState::Private
|
||||||
|
: Kernel::MemoryState::Shared);
|
||||||
ASSERT(vma.Succeeded());
|
ASSERT(vma.Succeeded());
|
||||||
process.vm_manager.Reprotect(vma.Unwrap(), Kernel::VMAPermission::ReadWriteExecute);
|
process.vm_manager.Reprotect(vma.Unwrap(), Kernel::VMAPermission::ReadWriteExecute);
|
||||||
|
|
||||||
@ -256,7 +260,8 @@ Loader::ResultStatus FileSys::Plugin3GXLoader::Map(
|
|||||||
// Map the rest of the memory at the heap location
|
// Map the rest of the memory at the heap location
|
||||||
auto vma_heap = process.vm_manager.MapBackingMemory(
|
auto vma_heap = process.vm_manager.MapBackingMemory(
|
||||||
_3GX_heap_load_addr + _3GX_fb_size, backing_memory_heap,
|
_3GX_heap_load_addr + _3GX_fb_size, backing_memory_heap,
|
||||||
block_size - exe_size - _3GX_fb_size, Kernel::MemoryState::Continuous);
|
block_size - exe_size - _3GX_fb_size,
|
||||||
|
is_mem_private ? Kernel::MemoryState::Private : Kernel::MemoryState::Shared);
|
||||||
ASSERT(vma_heap.Succeeded());
|
ASSERT(vma_heap.Succeeded());
|
||||||
process.vm_manager.Reprotect(vma_heap.Unwrap(), Kernel::VMAPermission::ReadWriteExecute);
|
process.vm_manager.Reprotect(vma_heap.Unwrap(), Kernel::VMAPermission::ReadWriteExecute);
|
||||||
|
|
||||||
|
@ -94,6 +94,9 @@ private:
|
|||||||
BitField<1, 1, u32_le> embedded_swap_func;
|
BitField<1, 1, u32_le> embedded_swap_func;
|
||||||
BitField<2, 2, u32_le> memory_region_size;
|
BitField<2, 2, u32_le> memory_region_size;
|
||||||
BitField<4, 2, u32_le> compatibility;
|
BitField<4, 2, u32_le> compatibility;
|
||||||
|
BitField<6, 1, u32_le> events_self_managed;
|
||||||
|
BitField<7, 1, u32_le> swap_not_needed;
|
||||||
|
BitField<8, 1, u32_le> use_private_memory;
|
||||||
} flags;
|
} flags;
|
||||||
u32_le exe_load_checksum;
|
u32_le exe_load_checksum;
|
||||||
u32_le builtin_load_exe_args[4];
|
u32_le builtin_load_exe_args[4];
|
||||||
|
@ -369,6 +369,16 @@ enum class ControlProcessOP {
|
|||||||
PROCESSOP_DISABLE_CREATE_THREAD_RESTRICTIONS,
|
PROCESSOP_DISABLE_CREATE_THREAD_RESTRICTIONS,
|
||||||
};
|
};
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Accepted by the custom svcMapProcessMemoryEx.
|
||||||
|
*/
|
||||||
|
enum class MapMemoryExFlag {
|
||||||
|
/**
|
||||||
|
* Maps the memory region as PRIVATE instead of SHARED
|
||||||
|
*/
|
||||||
|
MAPEXFLAGS_PRIVATE = (1 << 0),
|
||||||
|
};
|
||||||
|
|
||||||
class SVC : public SVCWrapper<SVC> {
|
class SVC : public SVCWrapper<SVC> {
|
||||||
public:
|
public:
|
||||||
SVC(Core::System& system);
|
SVC(Core::System& system);
|
||||||
@ -460,7 +470,8 @@ private:
|
|||||||
Result InvalidateEntireInstructionCache();
|
Result InvalidateEntireInstructionCache();
|
||||||
u32 ConvertVaToPa(u32 addr);
|
u32 ConvertVaToPa(u32 addr);
|
||||||
Result MapProcessMemoryEx(Handle dst_process_handle, u32 dst_address, Handle src_process_handle,
|
Result MapProcessMemoryEx(Handle dst_process_handle, u32 dst_address, Handle src_process_handle,
|
||||||
u32 src_address, u32 size);
|
u32 src_address, u32 size, MapMemoryExFlag flags,
|
||||||
|
Handle dst_process_handle_backup);
|
||||||
Result UnmapProcessMemoryEx(Handle process, u32 dst_address, u32 size);
|
Result UnmapProcessMemoryEx(Handle process, u32 dst_address, u32 size);
|
||||||
Result ControlProcess(Handle process_handle, u32 process_OP, u32 varg2, u32 varg3);
|
Result ControlProcess(Handle process_handle, u32 process_OP, u32 varg2, u32 varg3);
|
||||||
|
|
||||||
@ -2012,7 +2023,22 @@ u32 SVC::ConvertVaToPa(u32 addr) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
Result SVC::MapProcessMemoryEx(Handle dst_process_handle, u32 dst_address,
|
Result SVC::MapProcessMemoryEx(Handle dst_process_handle, u32 dst_address,
|
||||||
Handle src_process_handle, u32 src_address, u32 size) {
|
Handle src_process_handle, u32 src_address, u32 size,
|
||||||
|
MapMemoryExFlag flags, Handle dst_process_handle_backup) {
|
||||||
|
|
||||||
|
// Determine if this is the second version of the svc by checking the value at R0.
|
||||||
|
constexpr u32 SVC_VERSION2_MAGIC = 0xFFFFFFF2;
|
||||||
|
if (static_cast<u32>(dst_process_handle) == SVC_VERSION2_MAGIC) {
|
||||||
|
// Version 2, actual handle is provided in 6th argument
|
||||||
|
dst_process_handle = dst_process_handle_backup;
|
||||||
|
} else {
|
||||||
|
// Version 1, the flags argument is not used
|
||||||
|
flags = static_cast<MapMemoryExFlag>(0);
|
||||||
|
}
|
||||||
|
|
||||||
|
const bool map_as_private =
|
||||||
|
(static_cast<u32>(flags) & static_cast<u32>(MapMemoryExFlag::MAPEXFLAGS_PRIVATE)) != 0;
|
||||||
|
|
||||||
std::shared_ptr<Process> dst_process =
|
std::shared_ptr<Process> dst_process =
|
||||||
kernel.GetCurrentProcess()->handle_table.Get<Process>(dst_process_handle);
|
kernel.GetCurrentProcess()->handle_table.Get<Process>(dst_process_handle);
|
||||||
std::shared_ptr<Process> src_process =
|
std::shared_ptr<Process> src_process =
|
||||||
@ -2024,11 +2050,12 @@ Result SVC::MapProcessMemoryEx(Handle dst_process_handle, u32 dst_address,
|
|||||||
size = (size & ~0xFFF) + Memory::CITRA_PAGE_SIZE;
|
size = (size & ~0xFFF) + Memory::CITRA_PAGE_SIZE;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// TODO(PabloMK7) Fix-up this svc.
|
||||||
|
|
||||||
// Only linear memory supported
|
// Only linear memory supported
|
||||||
auto vma = src_process->vm_manager.FindVMA(src_address);
|
auto vma = src_process->vm_manager.FindVMA(src_address);
|
||||||
R_UNLESS(vma != src_process->vm_manager.vma_map.end() &&
|
R_UNLESS(vma != src_process->vm_manager.vma_map.end() &&
|
||||||
vma->second.type == VMAType::BackingMemory &&
|
vma->second.type == VMAType::BackingMemory,
|
||||||
vma->second.meminfo_state == MemoryState::Continuous,
|
|
||||||
ResultInvalidAddress);
|
ResultInvalidAddress);
|
||||||
|
|
||||||
const u32 offset = src_address - vma->second.base;
|
const u32 offset = src_address - vma->second.base;
|
||||||
@ -2038,7 +2065,7 @@ Result SVC::MapProcessMemoryEx(Handle dst_process_handle, u32 dst_address,
|
|||||||
dst_address,
|
dst_address,
|
||||||
memory.GetFCRAMRef(vma->second.backing_memory.GetPtr() + offset -
|
memory.GetFCRAMRef(vma->second.backing_memory.GetPtr() + offset -
|
||||||
kernel.memory.GetFCRAMPointer(0)),
|
kernel.memory.GetFCRAMPointer(0)),
|
||||||
size, Kernel::MemoryState::Continuous);
|
size, map_as_private ? MemoryState::Private : MemoryState::Shared);
|
||||||
|
|
||||||
if (!vma_res.Succeeded()) {
|
if (!vma_res.Succeeded()) {
|
||||||
return ResultInvalidAddressState;
|
return ResultInvalidAddressState;
|
||||||
@ -2060,8 +2087,7 @@ Result SVC::UnmapProcessMemoryEx(Handle process, u32 dst_address, u32 size) {
|
|||||||
// Only linear memory supported
|
// Only linear memory supported
|
||||||
auto vma = dst_process->vm_manager.FindVMA(dst_address);
|
auto vma = dst_process->vm_manager.FindVMA(dst_address);
|
||||||
R_UNLESS(vma != dst_process->vm_manager.vma_map.end() &&
|
R_UNLESS(vma != dst_process->vm_manager.vma_map.end() &&
|
||||||
vma->second.type == VMAType::BackingMemory &&
|
vma->second.type == VMAType::BackingMemory,
|
||||||
vma->second.meminfo_state == MemoryState::Continuous,
|
|
||||||
ResultInvalidAddress);
|
ResultInvalidAddress);
|
||||||
|
|
||||||
dst_process->vm_manager.UnmapRange(dst_address, size);
|
dst_process->vm_manager.UnmapRange(dst_address, size);
|
||||||
|
@ -7,6 +7,7 @@
|
|||||||
#include "core/hle/kernel/shared_memory.h"
|
#include "core/hle/kernel/shared_memory.h"
|
||||||
#include "core/hle/service/act/act.h"
|
#include "core/hle/service/act/act.h"
|
||||||
#include "core/hle/service/act/act_a.h"
|
#include "core/hle/service/act/act_a.h"
|
||||||
|
#include "core/hle/service/act/act_errors.h"
|
||||||
#include "core/hle/service/act/act_u.h"
|
#include "core/hle/service/act/act_u.h"
|
||||||
|
|
||||||
namespace Service::ACT {
|
namespace Service::ACT {
|
||||||
@ -31,15 +32,28 @@ void Module::Interface::Initialize(Kernel::HLERequestContext& ctx) {
|
|||||||
rb.Push(ResultSuccess);
|
rb.Push(ResultSuccess);
|
||||||
}
|
}
|
||||||
|
|
||||||
void Module::Interface::GetAccountDataBlock(Kernel::HLERequestContext& ctx) {
|
void Module::Interface::GetErrorCode(Kernel::HLERequestContext& ctx) {
|
||||||
IPC::RequestParser rp(ctx);
|
IPC::RequestParser rp(ctx);
|
||||||
const auto unknown = rp.Pop<u8>();
|
const auto result = rp.Pop<Result>();
|
||||||
|
|
||||||
|
LOG_DEBUG(Service_ACT, "called result={:08X}", result.raw);
|
||||||
|
|
||||||
|
const u32 error_code = GetACTErrorCode(result);
|
||||||
|
|
||||||
|
IPC::RequestBuilder rb = rp.MakeBuilder(2, 0);
|
||||||
|
rb.Push(ResultSuccess);
|
||||||
|
rb.Push(error_code);
|
||||||
|
}
|
||||||
|
|
||||||
|
void Module::Interface::GetAccountInfo(Kernel::HLERequestContext& ctx) {
|
||||||
|
IPC::RequestParser rp(ctx);
|
||||||
|
const auto account_slot = rp.Pop<u8>();
|
||||||
const auto size = rp.Pop<u32>();
|
const auto size = rp.Pop<u32>();
|
||||||
const auto block_id = rp.Pop<u32>();
|
const auto block_id = rp.Pop<u32>();
|
||||||
[[maybe_unused]] auto output_buffer = rp.PopMappedBuffer();
|
[[maybe_unused]] auto output_buffer = rp.PopMappedBuffer();
|
||||||
|
|
||||||
LOG_DEBUG(Service_ACT, "(STUBBED) called unknown={:02X}, size={:08X}, block_id={:08X}", unknown,
|
LOG_DEBUG(Service_ACT, "(STUBBED) called account_slot={:02X}, size={:08X}, block_id={:08X}",
|
||||||
size, block_id);
|
account_slot, size, block_id);
|
||||||
|
|
||||||
IPC::RequestBuilder rb = rp.MakeBuilder(1, 0);
|
IPC::RequestBuilder rb = rp.MakeBuilder(1, 0);
|
||||||
rb.Push(ResultSuccess);
|
rb.Push(ResultSuccess);
|
||||||
|
@ -38,9 +38,19 @@ public:
|
|||||||
void Initialize(Kernel::HLERequestContext& ctx);
|
void Initialize(Kernel::HLERequestContext& ctx);
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* ACT::GetAccountDataBlock service function.
|
* ACT::GetErrorCode service function.
|
||||||
* Inputs:
|
* Inputs:
|
||||||
* 1 : u8 Unknown
|
* 1 : Result code
|
||||||
|
* Outputs:
|
||||||
|
* 1 : Result of function, 0 on success, otherwise error code
|
||||||
|
* 2 : Error code
|
||||||
|
*/
|
||||||
|
void GetErrorCode(Kernel::HLERequestContext& ctx);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* ACT::GetAccountInfo service function.
|
||||||
|
* Inputs:
|
||||||
|
* 1 : Account slot
|
||||||
* 2 : Size
|
* 2 : Size
|
||||||
* 3 : Block ID
|
* 3 : Block ID
|
||||||
* 4 : Output Buffer Mapping Translation Header ((Size << 4) | 0xC)
|
* 4 : Output Buffer Mapping Translation Header ((Size << 4) | 0xC)
|
||||||
@ -48,7 +58,7 @@ public:
|
|||||||
* Outputs:
|
* Outputs:
|
||||||
* 1 : Result of function, 0 on success, otherwise error code
|
* 1 : Result of function, 0 on success, otherwise error code
|
||||||
*/
|
*/
|
||||||
void GetAccountDataBlock(Kernel::HLERequestContext& ctx);
|
void GetAccountInfo(Kernel::HLERequestContext& ctx);
|
||||||
};
|
};
|
||||||
|
|
||||||
private:
|
private:
|
||||||
|
@ -12,15 +12,61 @@ ACT_A::ACT_A(std::shared_ptr<Module> act) : Module::Interface(std::move(act), "a
|
|||||||
// act:u shared commands
|
// act:u shared commands
|
||||||
// clang-format off
|
// clang-format off
|
||||||
{0x0001, &ACT_A::Initialize, "Initialize"},
|
{0x0001, &ACT_A::Initialize, "Initialize"},
|
||||||
{0x0002, nullptr, "GetErrorCode"},
|
{0x0002, &ACT_A::GetErrorCode, "GetErrorCode"},
|
||||||
{0x0006, &ACT_A::GetAccountDataBlock, "GetAccountDataBlock"},
|
{0x0003, nullptr, "GetLastResponseCode"},
|
||||||
|
{0x0005, nullptr, "GetCommonInfo"},
|
||||||
|
{0x0006, &ACT_A::GetAccountInfo, "GetAccountInfo"},
|
||||||
|
{0x0007, nullptr, "GetResultAsync"},
|
||||||
|
{0x0008, nullptr, "GetMiiImageData"},
|
||||||
|
{0x0009, nullptr, "SetNfsPassword"},
|
||||||
{0x000B, nullptr, "AcquireEulaList"},
|
{0x000B, nullptr, "AcquireEulaList"},
|
||||||
|
{0x000C, nullptr, "AcquireTimeZoneList"},
|
||||||
{0x000D, nullptr, "GenerateUuid"},
|
{0x000D, nullptr, "GenerateUuid"},
|
||||||
|
{0x000F, nullptr, "FindSlotNoByUuid"},
|
||||||
|
{0x0010, nullptr, "SaveData"},
|
||||||
|
{0x0011, nullptr, "GetTransferableId"},
|
||||||
|
{0x0012, nullptr, "AcquireNexServiceToken"},
|
||||||
|
{0x0013, nullptr, "GetNexServiceToken"},
|
||||||
|
{0x0014, nullptr, "AcquireIndependentServiceToken"},
|
||||||
|
{0x0015, nullptr, "GetIndependentServiceToken"},
|
||||||
|
{0x0016, nullptr, "AcquireAccountInfo"},
|
||||||
|
{0x0017, nullptr, "AcquireAccountIdByPrincipalId"},
|
||||||
|
{0x0018, nullptr, "AcquirePrincipalIdByAccountId"},
|
||||||
|
{0x0019, nullptr, "AcquireMii"},
|
||||||
|
{0x001A, nullptr, "AcquireAccountInfoEx"},
|
||||||
|
{0x001D, nullptr, "InquireMailAddress"},
|
||||||
|
{0x001E, nullptr, "AcquireEula"},
|
||||||
|
{0x001F, nullptr, "AcquireEulaLanguageList"},
|
||||||
// act:a
|
// act:a
|
||||||
|
{0x0402, nullptr, "CreateConsoleAccount"},
|
||||||
|
{0x0403, nullptr, "CommitConsoleAccount"},
|
||||||
|
{0x0404, nullptr, "UnbindServerAccount"},
|
||||||
|
{0x0405, nullptr, "DeleteConsoleAccount"},
|
||||||
|
{0x0407, nullptr, "UnloadConsoleAccount"},
|
||||||
|
{0x0408, nullptr, "EnableAccountPasswordCache"},
|
||||||
|
{0x0409, nullptr, "SetDefaultAccount"},
|
||||||
|
{0x040A, nullptr, "ReplaceAccountId"},
|
||||||
|
{0x040B, nullptr, "GetSupportContext"},
|
||||||
|
{0x0412, nullptr, "UpdateMii"},
|
||||||
{0x0413, nullptr, "UpdateMiiImage"},
|
{0x0413, nullptr, "UpdateMiiImage"},
|
||||||
|
{0x0414, nullptr, "InquireAccountIdAvailability"},
|
||||||
|
{0x0415, nullptr, "BindToNewServerAccount"},
|
||||||
|
{0x0416, nullptr, "BindToExistentServerAccount"},
|
||||||
|
{0x0417, nullptr, "InquireBindingToExistentServerAccount"},
|
||||||
|
{0x041A, nullptr, "AcquireAccountTokenEx"},
|
||||||
{0x041B, nullptr, "AgreeEula"},
|
{0x041B, nullptr, "AgreeEula"},
|
||||||
|
{0x041C, nullptr, "SyncAccountInfo"},
|
||||||
|
{0x041E, nullptr, "UpdateAccountPassword"},
|
||||||
|
{0x041F, nullptr, "ReissueAccountPassword"},
|
||||||
|
{0x0420, nullptr, "SetAccountPasswordInput"},
|
||||||
{0x0421, nullptr, "UploadMii"},
|
{0x0421, nullptr, "UploadMii"},
|
||||||
{0x0423, nullptr, "ValidateMailAddress"},
|
{0x0423, nullptr, "ValidateMailAddress"},
|
||||||
|
{0x0423, nullptr, "SendConfirmationMail"},
|
||||||
|
{0x0428, nullptr, "ApproveByCreditCard"},
|
||||||
|
{0x0428, nullptr, "SendCoppaCodeMail"},
|
||||||
|
{0x042F, nullptr, "UpdateAccountInfoEx"},
|
||||||
|
{0x0430, nullptr, "UpdateAccountMailAddress"},
|
||||||
|
{0x0435, nullptr, "DeleteServerAccount"},
|
||||||
// clang-format on
|
// clang-format on
|
||||||
};
|
};
|
||||||
RegisterHandlers(functions);
|
RegisterHandlers(functions);
|
||||||
|
757
src/core/hle/service/act/act_errors.cpp
Normal file
757
src/core/hle/service/act/act_errors.cpp
Normal file
@ -0,0 +1,757 @@
|
|||||||
|
// Copyright 2024 Citra Emulator Project
|
||||||
|
// Licensed under GPLv2 or any later version
|
||||||
|
// Refer to the license.txt file included.
|
||||||
|
|
||||||
|
#include "core/hle/service/act/act_errors.h"
|
||||||
|
|
||||||
|
namespace Service::ACT {
|
||||||
|
|
||||||
|
u32 GetACTErrorCode(Result result) {
|
||||||
|
u32 error_code = ErrCodes::Unknown;
|
||||||
|
if (result.module == ErrorModule::ACT) {
|
||||||
|
switch (result.description) {
|
||||||
|
case ErrDescriptions::MySuccess:
|
||||||
|
error_code = ErrCodes::MySuccess;
|
||||||
|
break;
|
||||||
|
case ErrDescriptions::MailAddressNotConfirmed:
|
||||||
|
error_code = ErrCodes::MailAddressNotConfirmed;
|
||||||
|
break;
|
||||||
|
case ErrDescriptions::LibraryError:
|
||||||
|
error_code = ErrCodes::LibraryError;
|
||||||
|
break;
|
||||||
|
case ErrDescriptions::NotInitialized:
|
||||||
|
error_code = ErrCodes::NotInitialized;
|
||||||
|
break;
|
||||||
|
case ErrDescriptions::AlreadyInitialized:
|
||||||
|
error_code = ErrCodes::AlreadyInitialized;
|
||||||
|
break;
|
||||||
|
case ErrDescriptions::ErrDesc103:
|
||||||
|
error_code = ErrCodes::ErrCode225103;
|
||||||
|
break;
|
||||||
|
case ErrDescriptions::ErrDesc104:
|
||||||
|
error_code = ErrCodes::ErrCode225104;
|
||||||
|
break;
|
||||||
|
case ErrDescriptions::Busy:
|
||||||
|
error_code = ErrCodes::Busy;
|
||||||
|
break;
|
||||||
|
case ErrDescriptions::ErrDesc112:
|
||||||
|
error_code = ErrCodes::ErrCode225112;
|
||||||
|
break;
|
||||||
|
case ErrDescriptions::NotImplemented:
|
||||||
|
error_code = ErrCodes::NotImplemented;
|
||||||
|
break;
|
||||||
|
case ErrDescriptions::Deprecated:
|
||||||
|
error_code = ErrCodes::Deprecated;
|
||||||
|
break;
|
||||||
|
case ErrDescriptions::DevelopmentOnly:
|
||||||
|
error_code = ErrCodes::DevelopmentOnly;
|
||||||
|
break;
|
||||||
|
case ErrDescriptions::InvalidArgument:
|
||||||
|
error_code = ErrCodes::InvalidArgument;
|
||||||
|
break;
|
||||||
|
case ErrDescriptions::InvalidPointer:
|
||||||
|
error_code = ErrCodes::InvalidPointer;
|
||||||
|
break;
|
||||||
|
case ErrDescriptions::OutOfRange:
|
||||||
|
error_code = ErrCodes::OutOfRange;
|
||||||
|
break;
|
||||||
|
case ErrDescriptions::InvalidSize:
|
||||||
|
error_code = ErrCodes::InvalidSize;
|
||||||
|
break;
|
||||||
|
case ErrDescriptions::InvalidFormat:
|
||||||
|
error_code = ErrCodes::InvalidFormat;
|
||||||
|
break;
|
||||||
|
case ErrDescriptions::InvalidHandle:
|
||||||
|
error_code = ErrCodes::InvalidHandle;
|
||||||
|
break;
|
||||||
|
case ErrDescriptions::InvalidValue:
|
||||||
|
error_code = ErrCodes::InvalidValue;
|
||||||
|
break;
|
||||||
|
case ErrDescriptions::InternalError:
|
||||||
|
error_code = ErrCodes::InternalError;
|
||||||
|
break;
|
||||||
|
case ErrDescriptions::EndOfStream:
|
||||||
|
error_code = ErrCodes::EndOfStream;
|
||||||
|
break;
|
||||||
|
case ErrDescriptions::FileError:
|
||||||
|
error_code = ErrCodes::FileError;
|
||||||
|
break;
|
||||||
|
case ErrDescriptions::FileNotFound:
|
||||||
|
error_code = ErrCodes::FileNotFound;
|
||||||
|
break;
|
||||||
|
case ErrDescriptions::FileVersionMismatch:
|
||||||
|
error_code = ErrCodes::FileVersionMismatch;
|
||||||
|
break;
|
||||||
|
case ErrDescriptions::FileIOError:
|
||||||
|
error_code = ErrCodes::FileIOError;
|
||||||
|
break;
|
||||||
|
case ErrDescriptions::FileTypeMismatch:
|
||||||
|
error_code = ErrCodes::FileTypeMismatch;
|
||||||
|
break;
|
||||||
|
case ErrDescriptions::ErrDesc315:
|
||||||
|
error_code = ErrCodes::ErrCode225315;
|
||||||
|
break;
|
||||||
|
case ErrDescriptions::OutOfResource:
|
||||||
|
error_code = ErrCodes::OutOfResource;
|
||||||
|
break;
|
||||||
|
case ErrDescriptions::ShortOfBuffer:
|
||||||
|
error_code = ErrCodes::ShortOfBuffer;
|
||||||
|
break;
|
||||||
|
case ErrDescriptions::OutOfMemory:
|
||||||
|
error_code = ErrCodes::OutOfMemory;
|
||||||
|
break;
|
||||||
|
case ErrDescriptions::OutOfGlobalHeap:
|
||||||
|
error_code = ErrCodes::OutOfGlobalHeap;
|
||||||
|
break;
|
||||||
|
case ErrDescriptions::ErrDesc350:
|
||||||
|
error_code = ErrCodes::ErrCode225350;
|
||||||
|
break;
|
||||||
|
case ErrDescriptions::ErrDesc351:
|
||||||
|
error_code = ErrCodes::ErrCode225351;
|
||||||
|
break;
|
||||||
|
case ErrDescriptions::ErrDesc352:
|
||||||
|
error_code = ErrCodes::ErrCode225352;
|
||||||
|
break;
|
||||||
|
case ErrDescriptions::ErrDesc360:
|
||||||
|
error_code = ErrCodes::ErrCode225360;
|
||||||
|
break;
|
||||||
|
case ErrDescriptions::ErrDesc361:
|
||||||
|
error_code = ErrCodes::ErrCode225361;
|
||||||
|
break;
|
||||||
|
case ErrDescriptions::ErrDesc362:
|
||||||
|
error_code = ErrCodes::ErrCode225362;
|
||||||
|
break;
|
||||||
|
case ErrDescriptions::ErrDesc363:
|
||||||
|
error_code = ErrCodes::ErrCode225363;
|
||||||
|
break;
|
||||||
|
case ErrDescriptions::AccountManagementError:
|
||||||
|
error_code = ErrCodes::AccountManagementError;
|
||||||
|
break;
|
||||||
|
case ErrDescriptions::AccountNotFound:
|
||||||
|
error_code = ErrCodes::AccountNotFound;
|
||||||
|
break;
|
||||||
|
case ErrDescriptions::SlotsFull:
|
||||||
|
error_code = ErrCodes::SlotsFull;
|
||||||
|
break;
|
||||||
|
case ErrDescriptions::AccountNotLoaded:
|
||||||
|
error_code = ErrCodes::AccountNotLoaded;
|
||||||
|
break;
|
||||||
|
case ErrDescriptions::AccountAlreadyLoaded:
|
||||||
|
error_code = ErrCodes::AccountAlreadyLoaded;
|
||||||
|
break;
|
||||||
|
case ErrDescriptions::AccountLocked:
|
||||||
|
error_code = ErrCodes::AccountLocked;
|
||||||
|
break;
|
||||||
|
case ErrDescriptions::NotNetworkAccount:
|
||||||
|
error_code = ErrCodes::NotNetworkAccount;
|
||||||
|
break;
|
||||||
|
case ErrDescriptions::NotLocalAccount:
|
||||||
|
error_code = ErrCodes::NotLocalAccount;
|
||||||
|
break;
|
||||||
|
case ErrDescriptions::AccountNotCommited:
|
||||||
|
error_code = ErrCodes::AccountCommited;
|
||||||
|
break;
|
||||||
|
case ErrDescriptions::ErrDesc431:
|
||||||
|
error_code = ErrCodes::ErrCode225431;
|
||||||
|
break;
|
||||||
|
case ErrDescriptions::ErrDesc432:
|
||||||
|
error_code = ErrCodes::ErrCode225432;
|
||||||
|
break;
|
||||||
|
case ErrDescriptions::ErrDesc433:
|
||||||
|
error_code = ErrCodes::ErrCode225433;
|
||||||
|
break;
|
||||||
|
case ErrDescriptions::ErrDesc451:
|
||||||
|
error_code = ErrCodes::ErrCode221101;
|
||||||
|
break;
|
||||||
|
case ErrDescriptions::AuthenticationError:
|
||||||
|
error_code = ErrCodes::AuthenticationError;
|
||||||
|
break;
|
||||||
|
case ErrDescriptions::HttpError:
|
||||||
|
error_code = ErrCodes::HttpError;
|
||||||
|
break;
|
||||||
|
case ErrDescriptions::ErrDesc502:
|
||||||
|
error_code = ErrCodes::ErrCode225502;
|
||||||
|
break;
|
||||||
|
case ErrDescriptions::ErrDesc503:
|
||||||
|
error_code = ErrCodes::ErrCode225503;
|
||||||
|
break;
|
||||||
|
case ErrDescriptions::ErrDesc504:
|
||||||
|
error_code = ErrCodes::ErrCode225504;
|
||||||
|
break;
|
||||||
|
case ErrDescriptions::ErrDesc505:
|
||||||
|
error_code = ErrCodes::ErrCode225505;
|
||||||
|
break;
|
||||||
|
case ErrDescriptions::ErrDesc506:
|
||||||
|
error_code = ErrCodes::ErrCode225506;
|
||||||
|
break;
|
||||||
|
case ErrDescriptions::ErrDesc507:
|
||||||
|
error_code = ErrCodes::ErrCode225507;
|
||||||
|
break;
|
||||||
|
case ErrDescriptions::ErrDesc508:
|
||||||
|
error_code = ErrCodes::ErrCode225508;
|
||||||
|
break;
|
||||||
|
case ErrDescriptions::ErrDesc509:
|
||||||
|
error_code = ErrCodes::ErrCode225509;
|
||||||
|
break;
|
||||||
|
case ErrDescriptions::ErrDesc510:
|
||||||
|
error_code = ErrCodes::ErrCode225510;
|
||||||
|
break;
|
||||||
|
case ErrDescriptions::ErrDesc511:
|
||||||
|
error_code = ErrCodes::ErrCode225511;
|
||||||
|
break;
|
||||||
|
case ErrDescriptions::ErrDesc512:
|
||||||
|
error_code = ErrCodes::ErrCode225512;
|
||||||
|
break;
|
||||||
|
case ErrDescriptions::ErrDesc513:
|
||||||
|
error_code = ErrCodes::ErrCode225513;
|
||||||
|
break;
|
||||||
|
case ErrDescriptions::ErrDesc514:
|
||||||
|
error_code = ErrCodes::ErrCode225514;
|
||||||
|
break;
|
||||||
|
case ErrDescriptions::ErrDesc515:
|
||||||
|
error_code = ErrCodes::ErrCode225515;
|
||||||
|
break;
|
||||||
|
case ErrDescriptions::ErrDesc516:
|
||||||
|
error_code = ErrCodes::ErrCode225516;
|
||||||
|
break;
|
||||||
|
case ErrDescriptions::ErrDesc517:
|
||||||
|
error_code = ErrCodes::ErrCode225517;
|
||||||
|
break;
|
||||||
|
case ErrDescriptions::ErrDesc518:
|
||||||
|
error_code = ErrCodes::ErrCode225518;
|
||||||
|
break;
|
||||||
|
case ErrDescriptions::ErrDesc519:
|
||||||
|
error_code = ErrCodes::ErrCode225519;
|
||||||
|
break;
|
||||||
|
case ErrDescriptions::ErrDesc520:
|
||||||
|
error_code = ErrCodes::ErrCode225520;
|
||||||
|
break;
|
||||||
|
case ErrDescriptions::ErrDesc521:
|
||||||
|
error_code = ErrCodes::ErrCode225521;
|
||||||
|
break;
|
||||||
|
case ErrDescriptions::ErrDesc522:
|
||||||
|
error_code = ErrCodes::ErrCode225522;
|
||||||
|
break;
|
||||||
|
case ErrDescriptions::ErrDesc523:
|
||||||
|
error_code = ErrCodes::ErrCode225523;
|
||||||
|
break;
|
||||||
|
case ErrDescriptions::ErrDesc524:
|
||||||
|
error_code = ErrCodes::ErrCode225524;
|
||||||
|
break;
|
||||||
|
case ErrDescriptions::ErrDesc525:
|
||||||
|
error_code = ErrCodes::ErrCode225525;
|
||||||
|
break;
|
||||||
|
case ErrDescriptions::ErrDesc526:
|
||||||
|
error_code = ErrCodes::ErrCode225526;
|
||||||
|
break;
|
||||||
|
case ErrDescriptions::ErrDesc527:
|
||||||
|
error_code = ErrCodes::ErrCode225527;
|
||||||
|
break;
|
||||||
|
case ErrDescriptions::ErrDesc528:
|
||||||
|
error_code = ErrCodes::ErrCode225528;
|
||||||
|
break;
|
||||||
|
case ErrDescriptions::ErrDesc529:
|
||||||
|
error_code = ErrCodes::ErrCode225529;
|
||||||
|
break;
|
||||||
|
case ErrDescriptions::ErrDesc530:
|
||||||
|
error_code = ErrCodes::ErrCode225530;
|
||||||
|
break;
|
||||||
|
case ErrDescriptions::ErrDesc531:
|
||||||
|
error_code = ErrCodes::ErrCode225531;
|
||||||
|
break;
|
||||||
|
case ErrDescriptions::ErrDesc532:
|
||||||
|
error_code = ErrCodes::ErrCode225532;
|
||||||
|
break;
|
||||||
|
case ErrDescriptions::ErrDesc533:
|
||||||
|
error_code = ErrCodes::ErrCode225533;
|
||||||
|
break;
|
||||||
|
case ErrDescriptions::ErrDesc534:
|
||||||
|
error_code = ErrCodes::ErrCode225534;
|
||||||
|
break;
|
||||||
|
case ErrDescriptions::ErrDesc535:
|
||||||
|
error_code = ErrCodes::ErrCode225535;
|
||||||
|
break;
|
||||||
|
case ErrDescriptions::ErrDesc536:
|
||||||
|
error_code = ErrCodes::ErrCode225536;
|
||||||
|
break;
|
||||||
|
case ErrDescriptions::ErrDesc537:
|
||||||
|
error_code = ErrCodes::ErrCode225537;
|
||||||
|
break;
|
||||||
|
case ErrDescriptions::ErrDesc538:
|
||||||
|
error_code = ErrCodes::ErrCode225538;
|
||||||
|
break;
|
||||||
|
case ErrDescriptions::ErrDesc539:
|
||||||
|
error_code = ErrCodes::ErrCode225539;
|
||||||
|
break;
|
||||||
|
case ErrDescriptions::ErrDesc540:
|
||||||
|
error_code = ErrCodes::ErrCode225540;
|
||||||
|
break;
|
||||||
|
case ErrDescriptions::ErrDesc541:
|
||||||
|
error_code = ErrCodes::ErrCode225541;
|
||||||
|
break;
|
||||||
|
case ErrDescriptions::ErrDesc542:
|
||||||
|
error_code = ErrCodes::ErrCode225542;
|
||||||
|
break;
|
||||||
|
case ErrDescriptions::ErrDesc543:
|
||||||
|
error_code = ErrCodes::ErrCode225543;
|
||||||
|
break;
|
||||||
|
case ErrDescriptions::ErrDesc544:
|
||||||
|
error_code = ErrCodes::ErrCode225544;
|
||||||
|
break;
|
||||||
|
case ErrDescriptions::ErrDesc545:
|
||||||
|
error_code = ErrCodes::ErrCode225545;
|
||||||
|
break;
|
||||||
|
case ErrDescriptions::ErrDesc546:
|
||||||
|
error_code = ErrCodes::ErrCode225546;
|
||||||
|
break;
|
||||||
|
case ErrDescriptions::ErrDesc547:
|
||||||
|
error_code = ErrCodes::ErrCode225547;
|
||||||
|
break;
|
||||||
|
case ErrDescriptions::ErrDesc548:
|
||||||
|
error_code = ErrCodes::ErrCode225548;
|
||||||
|
break;
|
||||||
|
case ErrDescriptions::ErrDesc549:
|
||||||
|
error_code = ErrCodes::ErrCode225549;
|
||||||
|
break;
|
||||||
|
case ErrDescriptions::ErrDesc550:
|
||||||
|
error_code = ErrCodes::ErrCode225550;
|
||||||
|
break;
|
||||||
|
case ErrDescriptions::ErrDesc551:
|
||||||
|
error_code = ErrCodes::ErrCode225551;
|
||||||
|
break;
|
||||||
|
case ErrDescriptions::ErrDesc552:
|
||||||
|
error_code = ErrCodes::ErrCode225552;
|
||||||
|
break;
|
||||||
|
case ErrDescriptions::ErrDesc553:
|
||||||
|
error_code = ErrCodes::ErrCode225553;
|
||||||
|
break;
|
||||||
|
case ErrDescriptions::RequestError:
|
||||||
|
error_code = ErrCodes::RequestError;
|
||||||
|
break;
|
||||||
|
case ErrDescriptions::BadFormatParameter:
|
||||||
|
error_code = ErrCodes::BadFormatParameter;
|
||||||
|
break;
|
||||||
|
case ErrDescriptions::BadFormatRequest:
|
||||||
|
error_code = ErrCodes::BadFormatRequest;
|
||||||
|
break;
|
||||||
|
case ErrDescriptions::RequestParameterMissing:
|
||||||
|
error_code = ErrCodes::RequestParameterMissing;
|
||||||
|
break;
|
||||||
|
case ErrDescriptions::WrongHttpMethod:
|
||||||
|
error_code = ErrCodes::WrongHttpMethod;
|
||||||
|
break;
|
||||||
|
case ErrDescriptions::ResponseError:
|
||||||
|
error_code = ErrCodes::ResponseError;
|
||||||
|
break;
|
||||||
|
case ErrDescriptions::BadFormatResponse:
|
||||||
|
error_code = ErrCodes::BadFormatResponse;
|
||||||
|
break;
|
||||||
|
case ErrDescriptions::ResponseItemMissing:
|
||||||
|
error_code = ErrCodes::ResponseItemMissing;
|
||||||
|
break;
|
||||||
|
case ErrDescriptions::ResponseTooLarge:
|
||||||
|
error_code = ErrCodes::ResponseTooLarge;
|
||||||
|
break;
|
||||||
|
case ErrDescriptions::InvalidCommonParameter:
|
||||||
|
error_code = ErrCodes::InvalidCommonParameter;
|
||||||
|
break;
|
||||||
|
case ErrDescriptions::InvalidPlatformId:
|
||||||
|
error_code = ErrCodes::InvalidPlatformId;
|
||||||
|
break;
|
||||||
|
case ErrDescriptions::UnauthorizedDevice:
|
||||||
|
error_code = ErrCodes::UnauthorizedDevice;
|
||||||
|
break;
|
||||||
|
case ErrDescriptions::InvalidSerialId:
|
||||||
|
error_code = ErrCodes::InvalidSerialId;
|
||||||
|
break;
|
||||||
|
case ErrDescriptions::InvalidMacAddress:
|
||||||
|
error_code = ErrCodes::InvalidMacAddress;
|
||||||
|
break;
|
||||||
|
case ErrDescriptions::InvalidRegion:
|
||||||
|
error_code = ErrCodes::InvalidRegion;
|
||||||
|
break;
|
||||||
|
case ErrDescriptions::InvalidCountry:
|
||||||
|
error_code = ErrCodes::InvalidCountry;
|
||||||
|
break;
|
||||||
|
case ErrDescriptions::InvalidLanguage:
|
||||||
|
error_code = ErrCodes::InvalidLanguage;
|
||||||
|
break;
|
||||||
|
case ErrDescriptions::UnauthorizedClient:
|
||||||
|
error_code = ErrCodes::UnauthorizedClient;
|
||||||
|
break;
|
||||||
|
case ErrDescriptions::DeviceIdEmpty:
|
||||||
|
error_code = ErrCodes::DeviceIdEmpty;
|
||||||
|
break;
|
||||||
|
case ErrDescriptions::SerialIdEmpty:
|
||||||
|
error_code = ErrCodes::SerialIdEmpty;
|
||||||
|
break;
|
||||||
|
case ErrDescriptions::PlatformIdEmpty:
|
||||||
|
error_code = ErrCodes::PlatformIdEmpty;
|
||||||
|
break;
|
||||||
|
case ErrDescriptions::InvalidUniqueId:
|
||||||
|
error_code = ErrCodes::InvalidUniqueId;
|
||||||
|
break;
|
||||||
|
case ErrDescriptions::InvalidClientId:
|
||||||
|
error_code = ErrCodes::InvalidClientId;
|
||||||
|
break;
|
||||||
|
case ErrDescriptions::InvalidClientKey:
|
||||||
|
error_code = ErrCodes::InvalidClientKey;
|
||||||
|
break;
|
||||||
|
case ErrDescriptions::InvalidNexClientId:
|
||||||
|
error_code = ErrCodes::InvalidNexClientId;
|
||||||
|
break;
|
||||||
|
case ErrDescriptions::InvalidGameServerId:
|
||||||
|
error_code = ErrCodes::InvalidGameServerId;
|
||||||
|
break;
|
||||||
|
case ErrDescriptions::GameServerIdEnvironmentNotFound:
|
||||||
|
error_code = ErrCodes::GameServerIdEnvironmentNotFound;
|
||||||
|
break;
|
||||||
|
case ErrDescriptions::GameServerIdUniqueIdNotLinked:
|
||||||
|
error_code = ErrCodes::GameServerIdUniqueIdNotLinked;
|
||||||
|
break;
|
||||||
|
case ErrDescriptions::ClientIdUniqueIdNotLinked:
|
||||||
|
error_code = ErrCodes::ClientIdUniqueIdNotLinked;
|
||||||
|
break;
|
||||||
|
case ErrDescriptions::DeviceMismatch:
|
||||||
|
error_code = ErrCodes::DeviceMismatch;
|
||||||
|
break;
|
||||||
|
case ErrDescriptions::CountryMismatch:
|
||||||
|
error_code = ErrCodes::CountryMismatch;
|
||||||
|
break;
|
||||||
|
case ErrDescriptions::EulaNotAccepted:
|
||||||
|
error_code = ErrCodes::EulaNotAccepted;
|
||||||
|
break;
|
||||||
|
case ErrDescriptions::UpdateRequired:
|
||||||
|
error_code = ErrCodes::UpdateRequired;
|
||||||
|
break;
|
||||||
|
case ErrDescriptions::SystemUpdateRequired:
|
||||||
|
error_code = ErrCodes::SystemUpdateRequired;
|
||||||
|
break;
|
||||||
|
case ErrDescriptions::ApplicationUpdateRequired:
|
||||||
|
error_code = ErrCodes::ApplicationUpdateRequired;
|
||||||
|
break;
|
||||||
|
case ErrDescriptions::UnauthorizedRequest:
|
||||||
|
error_code = ErrCodes::UnauthorizedRequest;
|
||||||
|
break;
|
||||||
|
case ErrDescriptions::RequestForbidden:
|
||||||
|
error_code = ErrCodes::RequestForbidden;
|
||||||
|
break;
|
||||||
|
case ErrDescriptions::ResourceNotFound:
|
||||||
|
error_code = ErrCodes::ResourceNotFound;
|
||||||
|
break;
|
||||||
|
case ErrDescriptions::PidNotFound:
|
||||||
|
error_code = ErrCodes::PidNotFound;
|
||||||
|
break;
|
||||||
|
case ErrDescriptions::NexAccountNotFound:
|
||||||
|
error_code = ErrCodes::NexAccountNotFound;
|
||||||
|
break;
|
||||||
|
case ErrDescriptions::GenerateTokenFailure:
|
||||||
|
error_code = ErrCodes::GenerateTokenFailure;
|
||||||
|
break;
|
||||||
|
case ErrDescriptions::RequestNotFound:
|
||||||
|
error_code = ErrCodes::RequestNotFound;
|
||||||
|
break;
|
||||||
|
case ErrDescriptions::MasterPinNotFound:
|
||||||
|
error_code = ErrCodes::MasterPinNotFound;
|
||||||
|
break;
|
||||||
|
case ErrDescriptions::MailTextNotFound:
|
||||||
|
error_code = ErrCodes::MailTextNotFound;
|
||||||
|
break;
|
||||||
|
case ErrDescriptions::SendMailFailure:
|
||||||
|
error_code = ErrCodes::SendMailFailure;
|
||||||
|
break;
|
||||||
|
case ErrDescriptions::ApprovalIdNotFound:
|
||||||
|
error_code = ErrCodes::ApprovalIdNotFound;
|
||||||
|
break;
|
||||||
|
case ErrDescriptions::InvalidEulaParameter:
|
||||||
|
error_code = ErrCodes::InvalidEulaParameter;
|
||||||
|
break;
|
||||||
|
case ErrDescriptions::InvalidEulaCountry:
|
||||||
|
error_code = ErrCodes::InvalidEulaCountry;
|
||||||
|
break;
|
||||||
|
case ErrDescriptions::InvalidEulaCountryAndVersion:
|
||||||
|
error_code = ErrCodes::InvalidEulaCountryAndVersion;
|
||||||
|
break;
|
||||||
|
case ErrDescriptions::EulaNotFound:
|
||||||
|
error_code = ErrCodes::EulaNotFound;
|
||||||
|
break;
|
||||||
|
case ErrDescriptions::PhraseNotAcceptable:
|
||||||
|
error_code = ErrCodes::PhraseNotAcceptable;
|
||||||
|
break;
|
||||||
|
case ErrDescriptions::AccountIdAlreadyExists:
|
||||||
|
error_code = ErrCodes::AccountIdAlreadyExists;
|
||||||
|
break;
|
||||||
|
case ErrDescriptions::AccountIdNotAcceptable:
|
||||||
|
error_code = ErrCodes::AccountIdNotAcceptable;
|
||||||
|
break;
|
||||||
|
case ErrDescriptions::AccountPasswordNotAcceptable:
|
||||||
|
error_code = ErrCodes::AccountPasswordNotAcceptable;
|
||||||
|
break;
|
||||||
|
case ErrDescriptions::MiiNameNotAcceptable:
|
||||||
|
error_code = ErrCodes::MiiNameNotAcceptable;
|
||||||
|
break;
|
||||||
|
case ErrDescriptions::MailAddressNotAcceptable:
|
||||||
|
error_code = ErrCodes::MailAddressNotAcceptable;
|
||||||
|
break;
|
||||||
|
case ErrDescriptions::AccountIdFormatInvalid:
|
||||||
|
error_code = ErrCodes::AccountIdFormatInvalid;
|
||||||
|
break;
|
||||||
|
case ErrDescriptions::AccountIdPasswordSame:
|
||||||
|
error_code = ErrCodes::AccountIdPasswordSame;
|
||||||
|
break;
|
||||||
|
case ErrDescriptions::AccountIdCharNotAcceptable:
|
||||||
|
error_code = ErrCodes::AccountIdCharNotAcceptable;
|
||||||
|
break;
|
||||||
|
case ErrDescriptions::AccountIdSuccessiveSymbol:
|
||||||
|
error_code = ErrCodes::AccountIdSuccessiveSymbol;
|
||||||
|
break;
|
||||||
|
case ErrDescriptions::AccountIdSymbolPositionNotAcceptable:
|
||||||
|
error_code = ErrCodes::AccountIdSymbolPositionNotAcceptable;
|
||||||
|
break;
|
||||||
|
case ErrDescriptions::AccountIdTooManyDigit:
|
||||||
|
error_code = ErrCodes::AccountIdTooManyDigit;
|
||||||
|
break;
|
||||||
|
case ErrDescriptions::AccountPasswordCharNotAcceptable:
|
||||||
|
error_code = ErrCodes::AccountPasswordCharNotAcceptable;
|
||||||
|
break;
|
||||||
|
case ErrDescriptions::AccountPasswordTooFewCharTypes:
|
||||||
|
error_code = ErrCodes::AccountPasswordTooFewCharTypes;
|
||||||
|
break;
|
||||||
|
case ErrDescriptions::AccountPasswordSuccessiveSameChar:
|
||||||
|
error_code = ErrCodes::AccountPasswordSuccessiveSameChar;
|
||||||
|
break;
|
||||||
|
case ErrDescriptions::MailAddressDomainNameNotAcceptable:
|
||||||
|
error_code = ErrCodes::MailAddressDomainNameNotAcceptable;
|
||||||
|
break;
|
||||||
|
case ErrDescriptions::MailAddressDomainNameNotResolved:
|
||||||
|
error_code = ErrCodes::MailAddressDomainNameNotResolved;
|
||||||
|
break;
|
||||||
|
case ErrDescriptions::ErrDesc787:
|
||||||
|
error_code = ErrCodes::ErrCode222587;
|
||||||
|
break;
|
||||||
|
case ErrDescriptions::ReachedAssociationLimit:
|
||||||
|
error_code = ErrCodes::ReachedAssociationLimit;
|
||||||
|
break;
|
||||||
|
case ErrDescriptions::ReachedRegistrationLimit:
|
||||||
|
error_code = ErrCodes::ReachedRegistrationLimit;
|
||||||
|
break;
|
||||||
|
case ErrDescriptions::CoppaNotAccepted:
|
||||||
|
error_code = ErrCodes::CoppaNotAccepted;
|
||||||
|
break;
|
||||||
|
case ErrDescriptions::ParentalControlsRequired:
|
||||||
|
error_code = ErrCodes::ParentalControlsRequired;
|
||||||
|
break;
|
||||||
|
case ErrDescriptions::MiiNotRegistered:
|
||||||
|
error_code = ErrCodes::MiiNotRegistered;
|
||||||
|
break;
|
||||||
|
case ErrDescriptions::DeviceEulaCountryMismatch:
|
||||||
|
error_code = ErrCodes::DeviceEulaCountryMismatch;
|
||||||
|
break;
|
||||||
|
case ErrDescriptions::PendingMigration:
|
||||||
|
error_code = ErrCodes::PendingMigration;
|
||||||
|
break;
|
||||||
|
case ErrDescriptions::WrongUserInput:
|
||||||
|
error_code = ErrCodes::WrongUserInput;
|
||||||
|
break;
|
||||||
|
case ErrDescriptions::WrongAccountPassword:
|
||||||
|
error_code = ErrCodes::WrongAccountPassword;
|
||||||
|
break;
|
||||||
|
case ErrDescriptions::WrongMailAddress:
|
||||||
|
error_code = ErrCodes::WrongMailAddress;
|
||||||
|
break;
|
||||||
|
case ErrDescriptions::WrongAccountPasswordOrMailAddress:
|
||||||
|
error_code = ErrCodes::WrongAccountPasswordOrMailAddress;
|
||||||
|
break;
|
||||||
|
case ErrDescriptions::WrongConfirmationCode:
|
||||||
|
error_code = ErrCodes::WrongConfirmationCode;
|
||||||
|
break;
|
||||||
|
case ErrDescriptions::WrongBirthDateOrMailAddress:
|
||||||
|
error_code = ErrCodes::WrongBirthDateOrMailAddress;
|
||||||
|
break;
|
||||||
|
case ErrDescriptions::WrongAccountMail:
|
||||||
|
error_code = ErrCodes::WrongAccountMail;
|
||||||
|
break;
|
||||||
|
case ErrDescriptions::AccountAlreadyDeleted:
|
||||||
|
error_code = ErrCodes::AccountAlreadyDeleted;
|
||||||
|
break;
|
||||||
|
case ErrDescriptions::AccountIdChanged:
|
||||||
|
error_code = ErrCodes::AccountIdChanged;
|
||||||
|
break;
|
||||||
|
case ErrDescriptions::AuthenticationLocked:
|
||||||
|
error_code = ErrCodes::AuthenticationLocked;
|
||||||
|
break;
|
||||||
|
case ErrDescriptions::DeviceInactive:
|
||||||
|
error_code = ErrCodes::DeviceInactive;
|
||||||
|
break;
|
||||||
|
case ErrDescriptions::CoppaAgreementCanceled:
|
||||||
|
error_code = ErrCodes::CoppaAgreementCanceled;
|
||||||
|
break;
|
||||||
|
case ErrDescriptions::DomainAccountAlreadyExists:
|
||||||
|
error_code = ErrCodes::DomainAccountAlreadyExists;
|
||||||
|
break;
|
||||||
|
case ErrDescriptions::AccountTokenExpired:
|
||||||
|
error_code = ErrCodes::AccountTokenExpired;
|
||||||
|
break;
|
||||||
|
case ErrDescriptions::InvalidAccountToken:
|
||||||
|
error_code = ErrCodes::InvalidAccountToken;
|
||||||
|
break;
|
||||||
|
case ErrDescriptions::AuthenticationRequired:
|
||||||
|
error_code = ErrCodes::AuthenticationRequired;
|
||||||
|
break;
|
||||||
|
case ErrDescriptions::ErrDesc844:
|
||||||
|
error_code = ErrCodes::ErrCode225844;
|
||||||
|
break;
|
||||||
|
case ErrDescriptions::ConfirmationCodeExpired:
|
||||||
|
error_code = ErrCodes::ConfirmationCodeExpired;
|
||||||
|
break;
|
||||||
|
case ErrDescriptions::MailAddressNotValidated:
|
||||||
|
error_code = ErrCodes::MailAddressNotValidated;
|
||||||
|
break;
|
||||||
|
case ErrDescriptions::ExcessiveMailSendRequest:
|
||||||
|
error_code = ErrCodes::ExcessiveMailSendRequest;
|
||||||
|
break;
|
||||||
|
case ErrDescriptions::CreditCardError:
|
||||||
|
error_code = ErrCodes::CreditCardError;
|
||||||
|
break;
|
||||||
|
case ErrDescriptions::CreditCardGeneralFailure:
|
||||||
|
error_code = ErrCodes::CreditCardGeneralFailure;
|
||||||
|
break;
|
||||||
|
case ErrDescriptions::CreditCardDeclined:
|
||||||
|
error_code = ErrCodes::CreditCardDeclined;
|
||||||
|
break;
|
||||||
|
case ErrDescriptions::CreditCardBlacklisted:
|
||||||
|
error_code = ErrCodes::CreditCardBlacklisted;
|
||||||
|
break;
|
||||||
|
case ErrDescriptions::InvalidCreditCardNumber:
|
||||||
|
error_code = ErrCodes::InvalidCreditCardNumber;
|
||||||
|
break;
|
||||||
|
case ErrDescriptions::InvalidCreditCardDate:
|
||||||
|
error_code = ErrCodes::InvalidCreditCardDate;
|
||||||
|
break;
|
||||||
|
case ErrDescriptions::InvalidCreditCardPin:
|
||||||
|
error_code = ErrCodes::InvalidCreditCardPin;
|
||||||
|
break;
|
||||||
|
case ErrDescriptions::InvalidPostalCode:
|
||||||
|
error_code = ErrCodes::InvalidPostalCode;
|
||||||
|
break;
|
||||||
|
case ErrDescriptions::InvalidLocation:
|
||||||
|
error_code = ErrCodes::InvalidLocation;
|
||||||
|
break;
|
||||||
|
case ErrDescriptions::CreditCardDateExpired:
|
||||||
|
error_code = ErrCodes::CreditCardDateExpired;
|
||||||
|
break;
|
||||||
|
case ErrDescriptions::CreditCardNumberWrong:
|
||||||
|
error_code = ErrCodes::CreditCardNumberWrong;
|
||||||
|
break;
|
||||||
|
case ErrDescriptions::CreditCardPinWrong:
|
||||||
|
error_code = ErrCodes::CreditCardPinWrong;
|
||||||
|
break;
|
||||||
|
case ErrDescriptions::Banned:
|
||||||
|
error_code = ErrCodes::Banned;
|
||||||
|
break;
|
||||||
|
case ErrDescriptions::BannedAccount:
|
||||||
|
error_code = ErrCodes::BannedAccount;
|
||||||
|
break;
|
||||||
|
case ErrDescriptions::BannedAccountAll:
|
||||||
|
error_code = ErrCodes::BannedAccountAll;
|
||||||
|
break;
|
||||||
|
case ErrDescriptions::BannedAccountInApplication:
|
||||||
|
error_code = ErrCodes::BannedAccountInApplication;
|
||||||
|
break;
|
||||||
|
case ErrDescriptions::BannedAccountInNexService:
|
||||||
|
error_code = ErrCodes::BannedAccountInNexService;
|
||||||
|
break;
|
||||||
|
case ErrDescriptions::BannedAccountInIndependentService:
|
||||||
|
error_code = ErrCodes::BannedAccountInIndependentService;
|
||||||
|
break;
|
||||||
|
case ErrDescriptions::BannedDevice:
|
||||||
|
error_code = ErrCodes::BannedDevice;
|
||||||
|
break;
|
||||||
|
case ErrDescriptions::BannedDeviceAll:
|
||||||
|
error_code = ErrCodes::BannedDeviceAll;
|
||||||
|
break;
|
||||||
|
case ErrDescriptions::BannedDeviceInApplication:
|
||||||
|
error_code = ErrCodes::BannedDeviceInApplication;
|
||||||
|
break;
|
||||||
|
case ErrDescriptions::BannedDeviceInNexService:
|
||||||
|
error_code = ErrCodes::BannedDeviceInNexService;
|
||||||
|
break;
|
||||||
|
case ErrDescriptions::BannedDeviceInIndependentService:
|
||||||
|
error_code = ErrCodes::BannedDeviceInIndependentService;
|
||||||
|
break;
|
||||||
|
case ErrDescriptions::BannedAccountTemporarily:
|
||||||
|
error_code = ErrCodes::BannedAccountTemporarily;
|
||||||
|
break;
|
||||||
|
case ErrDescriptions::BannedAccountAllTemporarily:
|
||||||
|
error_code = ErrCodes::BannedAccountAllTemporarily;
|
||||||
|
break;
|
||||||
|
case ErrDescriptions::BannedAccountInApplicationTemporarily:
|
||||||
|
error_code = ErrCodes::BannedAccountInApplicationTemporarily;
|
||||||
|
break;
|
||||||
|
case ErrDescriptions::BannedAccountInNexServiceTemporarily:
|
||||||
|
error_code = ErrCodes::BannedAccountInNexServiceTemporarily;
|
||||||
|
break;
|
||||||
|
case ErrDescriptions::BannedAccountInIndependentServiceTemporarily:
|
||||||
|
error_code = ErrCodes::BannedAccountInIndependentServiceTemporarily;
|
||||||
|
break;
|
||||||
|
case ErrDescriptions::BannedDeviceTemporarily:
|
||||||
|
error_code = ErrCodes::BannedDeviceTemporarily;
|
||||||
|
break;
|
||||||
|
case ErrDescriptions::BannedDeviceAllTemporarily:
|
||||||
|
error_code = ErrCodes::BannedDeviceAllTemporarily;
|
||||||
|
break;
|
||||||
|
case ErrDescriptions::BannedDeviceInApplicationTemporarily:
|
||||||
|
error_code = ErrCodes::BannedDeviceInApplicationTemporarily;
|
||||||
|
break;
|
||||||
|
case ErrDescriptions::BannedDeviceInNexServiceTemporarily:
|
||||||
|
error_code = ErrCodes::BannedDeviceInNexServiceTemporarily;
|
||||||
|
break;
|
||||||
|
case ErrDescriptions::BannedDeviceInIndependentServiceTemporarily:
|
||||||
|
error_code = ErrCodes::BannedDeviceInIndependentServiceTemporarily;
|
||||||
|
break;
|
||||||
|
case ErrDescriptions::ServiceNotProvided:
|
||||||
|
error_code = ErrCodes::ServiceNotProvided;
|
||||||
|
break;
|
||||||
|
case ErrDescriptions::UnderMaintenance:
|
||||||
|
error_code = ErrCodes::UnderMaintenance;
|
||||||
|
break;
|
||||||
|
case ErrDescriptions::ServiceClosed:
|
||||||
|
error_code = ErrCodes::ServiceClosed;
|
||||||
|
break;
|
||||||
|
case ErrDescriptions::NintendoNetworkClosed:
|
||||||
|
error_code = ErrCodes::NintendoNetworkClosed;
|
||||||
|
break;
|
||||||
|
case ErrDescriptions::NotProvidedCountry:
|
||||||
|
error_code = ErrCodes::NotProvidedCountry;
|
||||||
|
break;
|
||||||
|
case ErrDescriptions::RestrictionError:
|
||||||
|
error_code = ErrCodes::RestrictionError;
|
||||||
|
break;
|
||||||
|
case ErrDescriptions::RestrictedByAge:
|
||||||
|
error_code = ErrCodes::RestrictedByAge;
|
||||||
|
break;
|
||||||
|
case ErrDescriptions::RestrictedByParentalControls:
|
||||||
|
error_code = ErrCodes::RestrictedByParentalControls;
|
||||||
|
break;
|
||||||
|
case ErrDescriptions::OnGameInternetCommunicationRestricted:
|
||||||
|
error_code = ErrCodes::OnGameInternetCommunicationRestricted;
|
||||||
|
break;
|
||||||
|
case ErrDescriptions::InternalServerError:
|
||||||
|
error_code = ErrCodes::InternalServerError;
|
||||||
|
break;
|
||||||
|
case ErrDescriptions::UnknownServerError:
|
||||||
|
error_code = ErrCodes::UnknownServerError;
|
||||||
|
break;
|
||||||
|
case ErrDescriptions::UnauthenticatedAfterSalvage:
|
||||||
|
error_code = ErrCodes::UnauthenticatedAfterSalvage;
|
||||||
|
break;
|
||||||
|
case ErrDescriptions::AuthenticationFailureUnknown:
|
||||||
|
error_code = ErrCodes::AuthenticationFailureUnknown;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return error_code;
|
||||||
|
}
|
||||||
|
|
||||||
|
} // namespace Service::ACT
|
613
src/core/hle/service/act/act_errors.h
Normal file
613
src/core/hle/service/act/act_errors.h
Normal file
@ -0,0 +1,613 @@
|
|||||||
|
// Copyright 2024 Citra Emulator Project
|
||||||
|
// Licensed under GPLv2 or any later version
|
||||||
|
// Refer to the license.txt file included.
|
||||||
|
|
||||||
|
#pragma once
|
||||||
|
|
||||||
|
#include "core/hle/service/service.h"
|
||||||
|
|
||||||
|
namespace Service::ACT {
|
||||||
|
|
||||||
|
namespace ErrDescriptions {
|
||||||
|
enum {
|
||||||
|
MySuccess = 0,
|
||||||
|
MailAddressNotConfirmed = 1,
|
||||||
|
|
||||||
|
// Library errors
|
||||||
|
LibraryError = 100,
|
||||||
|
NotInitialized = 101,
|
||||||
|
AlreadyInitialized = 102,
|
||||||
|
ErrDesc103 = 103,
|
||||||
|
ErrDesc104 = 104,
|
||||||
|
Busy = 111,
|
||||||
|
ErrDesc112 = 112,
|
||||||
|
NotImplemented = 191,
|
||||||
|
Deprecated = 192,
|
||||||
|
DevelopmentOnly = 193,
|
||||||
|
|
||||||
|
InvalidArgument = 200,
|
||||||
|
InvalidPointer = 201,
|
||||||
|
OutOfRange = 202,
|
||||||
|
InvalidSize = 203,
|
||||||
|
InvalidFormat = 204,
|
||||||
|
InvalidHandle = 205,
|
||||||
|
InvalidValue = 206,
|
||||||
|
|
||||||
|
InternalError = 300,
|
||||||
|
EndOfStream = 301,
|
||||||
|
FileError = 310,
|
||||||
|
FileNotFound = 311,
|
||||||
|
FileVersionMismatch = 312,
|
||||||
|
FileIOError = 313,
|
||||||
|
FileTypeMismatch = 314,
|
||||||
|
ErrDesc315 = 315,
|
||||||
|
|
||||||
|
OutOfResource = 330,
|
||||||
|
ShortOfBuffer = 331,
|
||||||
|
OutOfMemory = 340,
|
||||||
|
OutOfGlobalHeap = 341,
|
||||||
|
|
||||||
|
ErrDesc350 = 350,
|
||||||
|
ErrDesc351 = 351,
|
||||||
|
ErrDesc352 = 352,
|
||||||
|
ErrDesc360 = 360,
|
||||||
|
ErrDesc361 = 361,
|
||||||
|
ErrDesc362 = 362,
|
||||||
|
ErrDesc363 = 363,
|
||||||
|
|
||||||
|
// Account management errors
|
||||||
|
AccountManagementError = 400,
|
||||||
|
AccountNotFound = 401,
|
||||||
|
SlotsFull = 402,
|
||||||
|
AccountNotLoaded = 411,
|
||||||
|
AccountAlreadyLoaded = 412,
|
||||||
|
AccountLocked = 413,
|
||||||
|
NotNetworkAccount = 421,
|
||||||
|
NotLocalAccount = 422,
|
||||||
|
AccountNotCommited = 423,
|
||||||
|
|
||||||
|
ErrDesc431 = 431,
|
||||||
|
ErrDesc432 = 432,
|
||||||
|
ErrDesc433 = 433,
|
||||||
|
|
||||||
|
ErrDesc451 = 451,
|
||||||
|
|
||||||
|
AuthenticationError = 500,
|
||||||
|
|
||||||
|
// HTTP errors
|
||||||
|
HttpError = 501,
|
||||||
|
ErrDesc502 = 502,
|
||||||
|
ErrDesc503 = 503,
|
||||||
|
ErrDesc504 = 504,
|
||||||
|
ErrDesc505 = 505,
|
||||||
|
ErrDesc506 = 506,
|
||||||
|
ErrDesc507 = 507,
|
||||||
|
ErrDesc508 = 508,
|
||||||
|
ErrDesc509 = 509,
|
||||||
|
ErrDesc510 = 510,
|
||||||
|
ErrDesc511 = 511,
|
||||||
|
ErrDesc512 = 512,
|
||||||
|
ErrDesc513 = 513,
|
||||||
|
ErrDesc514 = 514,
|
||||||
|
ErrDesc515 = 515,
|
||||||
|
ErrDesc516 = 516,
|
||||||
|
ErrDesc517 = 517,
|
||||||
|
ErrDesc518 = 518,
|
||||||
|
ErrDesc519 = 519,
|
||||||
|
ErrDesc520 = 520,
|
||||||
|
ErrDesc521 = 521,
|
||||||
|
ErrDesc522 = 522,
|
||||||
|
ErrDesc523 = 523,
|
||||||
|
ErrDesc524 = 524,
|
||||||
|
ErrDesc525 = 525,
|
||||||
|
ErrDesc526 = 526,
|
||||||
|
ErrDesc527 = 527,
|
||||||
|
ErrDesc528 = 528,
|
||||||
|
ErrDesc529 = 529,
|
||||||
|
ErrDesc530 = 530,
|
||||||
|
ErrDesc531 = 531,
|
||||||
|
ErrDesc532 = 532,
|
||||||
|
ErrDesc533 = 533,
|
||||||
|
ErrDesc534 = 534,
|
||||||
|
ErrDesc535 = 535,
|
||||||
|
ErrDesc536 = 536,
|
||||||
|
ErrDesc537 = 537,
|
||||||
|
ErrDesc538 = 538,
|
||||||
|
ErrDesc539 = 539,
|
||||||
|
ErrDesc540 = 540,
|
||||||
|
ErrDesc541 = 541,
|
||||||
|
ErrDesc542 = 542,
|
||||||
|
ErrDesc543 = 543,
|
||||||
|
ErrDesc544 = 544,
|
||||||
|
ErrDesc545 = 545,
|
||||||
|
ErrDesc546 = 546,
|
||||||
|
ErrDesc547 = 547,
|
||||||
|
ErrDesc548 = 548,
|
||||||
|
ErrDesc549 = 549,
|
||||||
|
ErrDesc550 = 550,
|
||||||
|
ErrDesc551 = 551,
|
||||||
|
ErrDesc552 = 552,
|
||||||
|
ErrDesc553 = 553,
|
||||||
|
|
||||||
|
// Request errors
|
||||||
|
RequestError = 600,
|
||||||
|
BadFormatParameter = 601,
|
||||||
|
BadFormatRequest = 602,
|
||||||
|
RequestParameterMissing = 603,
|
||||||
|
WrongHttpMethod = 604,
|
||||||
|
|
||||||
|
// Response errors
|
||||||
|
ResponseError = 620,
|
||||||
|
BadFormatResponse = 621,
|
||||||
|
ResponseItemMissing = 622,
|
||||||
|
ResponseTooLarge = 623,
|
||||||
|
|
||||||
|
// Invalid parameter errors
|
||||||
|
InvalidCommonParameter = 650,
|
||||||
|
InvalidPlatformId = 651,
|
||||||
|
UnauthorizedDevice = 652,
|
||||||
|
InvalidSerialId = 653,
|
||||||
|
InvalidMacAddress = 654,
|
||||||
|
InvalidRegion = 655,
|
||||||
|
InvalidCountry = 656,
|
||||||
|
InvalidLanguage = 657,
|
||||||
|
UnauthorizedClient = 658,
|
||||||
|
DeviceIdEmpty = 659,
|
||||||
|
SerialIdEmpty = 660,
|
||||||
|
PlatformIdEmpty = 661,
|
||||||
|
|
||||||
|
InvalidUniqueId = 671,
|
||||||
|
InvalidClientId = 672,
|
||||||
|
InvalidClientKey = 673,
|
||||||
|
|
||||||
|
InvalidNexClientId = 681,
|
||||||
|
InvalidGameServerId = 682,
|
||||||
|
GameServerIdEnvironmentNotFound = 683,
|
||||||
|
GameServerIdUniqueIdNotLinked = 684,
|
||||||
|
ClientIdUniqueIdNotLinked = 685,
|
||||||
|
|
||||||
|
DeviceMismatch = 701,
|
||||||
|
CountryMismatch = 702,
|
||||||
|
EulaNotAccepted = 703,
|
||||||
|
|
||||||
|
// Update required errors
|
||||||
|
UpdateRequired = 710,
|
||||||
|
SystemUpdateRequired = 711,
|
||||||
|
ApplicationUpdateRequired = 712,
|
||||||
|
|
||||||
|
UnauthorizedRequest = 720,
|
||||||
|
RequestForbidden = 722,
|
||||||
|
|
||||||
|
// Resource not found errors
|
||||||
|
ResourceNotFound = 730,
|
||||||
|
PidNotFound = 731,
|
||||||
|
NexAccountNotFound = 732,
|
||||||
|
GenerateTokenFailure = 733,
|
||||||
|
RequestNotFound = 734,
|
||||||
|
MasterPinNotFound = 735,
|
||||||
|
MailTextNotFound = 736,
|
||||||
|
SendMailFailure = 737,
|
||||||
|
ApprovalIdNotFound = 738,
|
||||||
|
|
||||||
|
// EULA errors
|
||||||
|
InvalidEulaParameter = 740,
|
||||||
|
InvalidEulaCountry = 741,
|
||||||
|
InvalidEulaCountryAndVersion = 742,
|
||||||
|
EulaNotFound = 743,
|
||||||
|
|
||||||
|
// Not acceptable errors
|
||||||
|
PhraseNotAcceptable = 770,
|
||||||
|
AccountIdAlreadyExists = 771,
|
||||||
|
AccountIdNotAcceptable = 772,
|
||||||
|
AccountPasswordNotAcceptable = 773,
|
||||||
|
MiiNameNotAcceptable = 774,
|
||||||
|
MailAddressNotAcceptable = 775,
|
||||||
|
AccountIdFormatInvalid = 776,
|
||||||
|
AccountIdPasswordSame = 777,
|
||||||
|
AccountIdCharNotAcceptable = 778,
|
||||||
|
AccountIdSuccessiveSymbol = 779,
|
||||||
|
AccountIdSymbolPositionNotAcceptable = 780,
|
||||||
|
AccountIdTooManyDigit = 781,
|
||||||
|
AccountPasswordCharNotAcceptable = 782,
|
||||||
|
AccountPasswordTooFewCharTypes = 783,
|
||||||
|
AccountPasswordSuccessiveSameChar = 784,
|
||||||
|
MailAddressDomainNameNotAcceptable = 785,
|
||||||
|
MailAddressDomainNameNotResolved = 786,
|
||||||
|
ErrDesc787 = 787,
|
||||||
|
|
||||||
|
ReachedAssociationLimit = 791,
|
||||||
|
ReachedRegistrationLimit = 792,
|
||||||
|
CoppaNotAccepted = 793,
|
||||||
|
ParentalControlsRequired = 794,
|
||||||
|
MiiNotRegistered = 795,
|
||||||
|
DeviceEulaCountryMismatch = 796,
|
||||||
|
PendingMigration = 797,
|
||||||
|
|
||||||
|
// Wrong user input errors
|
||||||
|
WrongUserInput = 810,
|
||||||
|
WrongAccountPassword = 811,
|
||||||
|
WrongMailAddress = 812,
|
||||||
|
WrongAccountPasswordOrMailAddress = 813,
|
||||||
|
WrongConfirmationCode = 814,
|
||||||
|
WrongBirthDateOrMailAddress = 815,
|
||||||
|
WrongAccountMail = 816,
|
||||||
|
|
||||||
|
AccountAlreadyDeleted = 831,
|
||||||
|
AccountIdChanged = 832,
|
||||||
|
AuthenticationLocked = 833,
|
||||||
|
DeviceInactive = 834,
|
||||||
|
CoppaAgreementCanceled = 835,
|
||||||
|
DomainAccountAlreadyExists = 836,
|
||||||
|
|
||||||
|
AccountTokenExpired = 841,
|
||||||
|
InvalidAccountToken = 842,
|
||||||
|
AuthenticationRequired = 843,
|
||||||
|
ErrDesc844 = 844,
|
||||||
|
|
||||||
|
ConfirmationCodeExpired = 851,
|
||||||
|
|
||||||
|
MailAddressNotValidated = 861,
|
||||||
|
ExcessiveMailSendRequest = 862,
|
||||||
|
|
||||||
|
// Credit card errors
|
||||||
|
CreditCardError = 870,
|
||||||
|
CreditCardGeneralFailure = 871,
|
||||||
|
CreditCardDeclined = 872,
|
||||||
|
CreditCardBlacklisted = 873,
|
||||||
|
InvalidCreditCardNumber = 874,
|
||||||
|
InvalidCreditCardDate = 875,
|
||||||
|
InvalidCreditCardPin = 876,
|
||||||
|
InvalidPostalCode = 877,
|
||||||
|
InvalidLocation = 878,
|
||||||
|
CreditCardDateExpired = 879,
|
||||||
|
CreditCardNumberWrong = 880,
|
||||||
|
CreditCardPinWrong = 881,
|
||||||
|
|
||||||
|
// Ban errors
|
||||||
|
Banned = 900,
|
||||||
|
BannedAccount = 901,
|
||||||
|
BannedAccountAll = 902,
|
||||||
|
BannedAccountInApplication = 903,
|
||||||
|
BannedAccountInNexService = 904,
|
||||||
|
BannedAccountInIndependentService = 905,
|
||||||
|
BannedDevice = 911,
|
||||||
|
BannedDeviceAll = 912,
|
||||||
|
BannedDeviceInApplication = 913,
|
||||||
|
BannedDeviceInNexService = 914,
|
||||||
|
BannedDeviceInIndependentService = 915,
|
||||||
|
BannedAccountTemporarily = 921,
|
||||||
|
BannedAccountAllTemporarily = 922,
|
||||||
|
BannedAccountInApplicationTemporarily = 923,
|
||||||
|
BannedAccountInNexServiceTemporarily = 924,
|
||||||
|
BannedAccountInIndependentServiceTemporarily = 925,
|
||||||
|
BannedDeviceTemporarily = 931,
|
||||||
|
BannedDeviceAllTemporarily = 932,
|
||||||
|
BannedDeviceInApplicationTemporarily = 933,
|
||||||
|
BannedDeviceInNexServiceTemporarily = 934,
|
||||||
|
BannedDeviceInIndependentServiceTemporarily = 935,
|
||||||
|
|
||||||
|
// Service not provided errors
|
||||||
|
ServiceNotProvided = 950,
|
||||||
|
UnderMaintenance = 951,
|
||||||
|
ServiceClosed = 952,
|
||||||
|
NintendoNetworkClosed = 953,
|
||||||
|
NotProvidedCountry = 954,
|
||||||
|
|
||||||
|
// Restriction errors
|
||||||
|
RestrictionError = 970,
|
||||||
|
RestrictedByAge = 971,
|
||||||
|
RestrictedByParentalControls = 980,
|
||||||
|
OnGameInternetCommunicationRestricted = 981,
|
||||||
|
|
||||||
|
InternalServerError = 991,
|
||||||
|
UnknownServerError = 992,
|
||||||
|
|
||||||
|
UnauthenticatedAfterSalvage = 998,
|
||||||
|
AuthenticationFailureUnknown = 999,
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
|
namespace ErrCodes {
|
||||||
|
enum {
|
||||||
|
MySuccess = 220000, // 022-0000
|
||||||
|
MailAddressNotConfirmed = 220001, // 022-0001
|
||||||
|
|
||||||
|
// Library errors
|
||||||
|
LibraryError = 220500, // 022-0500
|
||||||
|
NotInitialized = 220501, // 022-0501
|
||||||
|
AlreadyInitialized = 220502, // 022-0502
|
||||||
|
ErrCode225103 = 225103, // 022-5103
|
||||||
|
ErrCode225104 = 225104, // 022-5104
|
||||||
|
Busy = 220511, // 022-0511
|
||||||
|
ErrCode225112 = 225112, // 022-5112
|
||||||
|
NotImplemented = 220591, // 022-0591
|
||||||
|
Deprecated = 220592, // 022-0592
|
||||||
|
DevelopmentOnly = 220593, // 022-0593
|
||||||
|
|
||||||
|
InvalidArgument = 220600, // 022-0600
|
||||||
|
InvalidPointer = 220601, // 022-0601
|
||||||
|
OutOfRange = 220602, // 022-0602
|
||||||
|
InvalidSize = 220603, // 022-0603
|
||||||
|
InvalidFormat = 220604, // 022-0604
|
||||||
|
InvalidHandle = 220605, // 022-0605
|
||||||
|
InvalidValue = 220606, // 022-0606
|
||||||
|
|
||||||
|
InternalError = 220700, // 022-0700
|
||||||
|
EndOfStream = 220701, // 022-0701
|
||||||
|
FileError = 220710, // 022-0710
|
||||||
|
FileNotFound = 220711, // 022-0711
|
||||||
|
FileVersionMismatch = 220712, // 022-0712
|
||||||
|
FileIOError = 220713, // 022-0713
|
||||||
|
FileTypeMismatch = 220714, // 022-0714
|
||||||
|
ErrCode225315 = 225315, // 022-5315
|
||||||
|
|
||||||
|
OutOfResource = 220730, // 022-0730
|
||||||
|
ShortOfBuffer = 220731, // 022-0731
|
||||||
|
OutOfMemory = 220740, // 022-0740
|
||||||
|
OutOfGlobalHeap = 220741, // 022-0741
|
||||||
|
|
||||||
|
ErrCode225350 = 225350, // 022-5350
|
||||||
|
ErrCode225351 = 225351, // 022-5351
|
||||||
|
ErrCode225352 = 225352, // 022-5352
|
||||||
|
ErrCode225360 = 225360, // 022-5360
|
||||||
|
ErrCode225361 = 225361, // 022-5361
|
||||||
|
ErrCode225362 = 225362, // 022-5362
|
||||||
|
ErrCode225363 = 225363, // 022-5363
|
||||||
|
|
||||||
|
// Account management errors
|
||||||
|
AccountManagementError = 221000, // 022-1000
|
||||||
|
AccountNotFound = 221001, // 022-1001
|
||||||
|
SlotsFull = 221002, // 022-1002
|
||||||
|
AccountNotLoaded = 221011, // 022-1011
|
||||||
|
AccountAlreadyLoaded = 221012, // 022-1012
|
||||||
|
AccountLocked = 221013, // 022-1013
|
||||||
|
NotNetworkAccount = 221021, // 022-1021
|
||||||
|
NotLocalAccount = 221022, // 022-1022
|
||||||
|
AccountCommited = 221023, // 022-1023
|
||||||
|
|
||||||
|
ErrCode225431 = 225431, // 022-5431
|
||||||
|
ErrCode225432 = 225432, // 022-5432
|
||||||
|
ErrCode225433 = 225433, // 022-5433
|
||||||
|
|
||||||
|
ErrCode221101 = 221101, // 022-1101
|
||||||
|
|
||||||
|
AuthenticationError = 222000, // 022-2000
|
||||||
|
|
||||||
|
// HTTP errors
|
||||||
|
HttpError = 222100, // 022-2100
|
||||||
|
ErrCode225502 = 225502, // 022-5502
|
||||||
|
ErrCode225503 = 225503, // 022-5503
|
||||||
|
ErrCode225504 = 225504, // 022-5504
|
||||||
|
ErrCode225505 = 225505, // 022-5505
|
||||||
|
ErrCode225506 = 225506, // 022-5506
|
||||||
|
ErrCode225507 = 225507, // 022-5507
|
||||||
|
ErrCode225508 = 225508, // 022-5508
|
||||||
|
ErrCode225509 = 225509, // 022-5509
|
||||||
|
ErrCode225510 = 225510, // 022-5510
|
||||||
|
ErrCode225511 = 225511, // 022-5511
|
||||||
|
ErrCode225512 = 225512, // 022-5512
|
||||||
|
ErrCode225513 = 225513, // 022-5513
|
||||||
|
ErrCode225514 = 225514, // 022-5514
|
||||||
|
ErrCode225515 = 225515, // 022-5515
|
||||||
|
ErrCode225516 = 225516, // 022-5516
|
||||||
|
ErrCode225517 = 225517, // 022-5517
|
||||||
|
ErrCode225518 = 225518, // 022-5518
|
||||||
|
ErrCode225519 = 225519, // 022-5519
|
||||||
|
ErrCode225520 = 225520, // 022-5520
|
||||||
|
ErrCode225521 = 225521, // 022-5521
|
||||||
|
ErrCode225522 = 225522, // 022-5522
|
||||||
|
ErrCode225523 = 225523, // 022-5523
|
||||||
|
ErrCode225524 = 225524, // 022-5524
|
||||||
|
ErrCode225525 = 225525, // 022-5525
|
||||||
|
ErrCode225526 = 225526, // 022-5526
|
||||||
|
ErrCode225527 = 225527, // 022-5527
|
||||||
|
ErrCode225528 = 225528, // 022-5528
|
||||||
|
ErrCode225529 = 225529, // 022-5529
|
||||||
|
ErrCode225530 = 225530, // 022-5530
|
||||||
|
ErrCode225531 = 225531, // 022-5531
|
||||||
|
ErrCode225532 = 225532, // 022-5532
|
||||||
|
ErrCode225533 = 225533, // 022-5533
|
||||||
|
ErrCode225534 = 225534, // 022-5534
|
||||||
|
ErrCode225535 = 225535, // 022-5535
|
||||||
|
ErrCode225536 = 225536, // 022-5536
|
||||||
|
ErrCode225537 = 225537, // 022-5537
|
||||||
|
ErrCode225538 = 225538, // 022-5538
|
||||||
|
ErrCode225539 = 225539, // 022-5539
|
||||||
|
ErrCode225540 = 225540, // 022-5540
|
||||||
|
ErrCode225541 = 225541, // 022-5541
|
||||||
|
ErrCode225542 = 225542, // 022-5542
|
||||||
|
ErrCode225543 = 225543, // 022-5543
|
||||||
|
ErrCode225544 = 225544, // 022-5544
|
||||||
|
ErrCode225545 = 225545, // 022-5545
|
||||||
|
ErrCode225546 = 225546, // 022-5546
|
||||||
|
ErrCode225547 = 225547, // 022-5547
|
||||||
|
ErrCode225548 = 225548, // 022-5548
|
||||||
|
ErrCode225549 = 225549, // 022-5549
|
||||||
|
ErrCode225550 = 225550, // 022-5550
|
||||||
|
ErrCode225551 = 225551, // 022-5551
|
||||||
|
ErrCode225552 = 225552, // 022-5552
|
||||||
|
ErrCode225553 = 225553, // 022-5553
|
||||||
|
|
||||||
|
// Request errors
|
||||||
|
RequestError = 222400, // 022-2400
|
||||||
|
BadFormatParameter = 222401, // 022-2401
|
||||||
|
BadFormatRequest = 222402, // 022-2402
|
||||||
|
RequestParameterMissing = 222403, // 022-2403
|
||||||
|
WrongHttpMethod = 222404, // 022-2404
|
||||||
|
|
||||||
|
// Response errors
|
||||||
|
ResponseError = 222420, // 022-2420
|
||||||
|
BadFormatResponse = 222421, // 022-2421
|
||||||
|
ResponseItemMissing = 222422, // 022-2422
|
||||||
|
ResponseTooLarge = 222423, // 022-2423
|
||||||
|
|
||||||
|
// Invalid parameter errors
|
||||||
|
InvalidCommonParameter = 222450, // 022-2450
|
||||||
|
InvalidPlatformId = 222451, // 022-2451
|
||||||
|
UnauthorizedDevice = 222452, // 022-2452
|
||||||
|
InvalidSerialId = 222453, // 022-2453
|
||||||
|
InvalidMacAddress = 222454, // 022-2454
|
||||||
|
InvalidRegion = 222455, // 022-2455
|
||||||
|
InvalidCountry = 222456, // 022-2456
|
||||||
|
InvalidLanguage = 222457, // 022-2457
|
||||||
|
UnauthorizedClient = 222458, // 022-2458
|
||||||
|
DeviceIdEmpty = 222459, // 022-2459
|
||||||
|
SerialIdEmpty = 222460, // 022-2460
|
||||||
|
PlatformIdEmpty = 222461, // 022-2461
|
||||||
|
|
||||||
|
InvalidUniqueId = 222471, // 022-2471
|
||||||
|
InvalidClientId = 222472, // 022-2472
|
||||||
|
InvalidClientKey = 222473, // 022-2473
|
||||||
|
|
||||||
|
InvalidNexClientId = 222481, // 022-2481
|
||||||
|
InvalidGameServerId = 222482, // 022-2482
|
||||||
|
GameServerIdEnvironmentNotFound = 222483, // 022-2483
|
||||||
|
GameServerIdUniqueIdNotLinked = 222484, // 022-2484
|
||||||
|
ClientIdUniqueIdNotLinked = 222485, // 022-2485
|
||||||
|
|
||||||
|
DeviceMismatch = 222501, // 022-2501
|
||||||
|
CountryMismatch = 222502, // 022-2502
|
||||||
|
EulaNotAccepted = 222503, // 022-2503
|
||||||
|
|
||||||
|
// Update required errors
|
||||||
|
UpdateRequired = 222510, // 022-2510
|
||||||
|
SystemUpdateRequired = 222511, // 022-2511
|
||||||
|
ApplicationUpdateRequired = 222512, // 022-2512
|
||||||
|
|
||||||
|
UnauthorizedRequest = 222520, // 022-2520
|
||||||
|
RequestForbidden = 222522, // 022-2522
|
||||||
|
|
||||||
|
// Resource not found errors
|
||||||
|
ResourceNotFound = 222530, // 022-2530
|
||||||
|
PidNotFound = 222531, // 022-2531
|
||||||
|
NexAccountNotFound = 222532, // 022-2532
|
||||||
|
GenerateTokenFailure = 222533, // 022-2533
|
||||||
|
RequestNotFound = 222534, // 022-2534
|
||||||
|
MasterPinNotFound = 222535, // 022-2535
|
||||||
|
MailTextNotFound = 222536, // 022-2536
|
||||||
|
SendMailFailure = 222537, // 022-2537
|
||||||
|
ApprovalIdNotFound = 222538, // 022-2538
|
||||||
|
|
||||||
|
// EULA errors
|
||||||
|
InvalidEulaParameter = 222540, // 022-2540
|
||||||
|
InvalidEulaCountry = 222541, // 022-2541
|
||||||
|
InvalidEulaCountryAndVersion = 222542, // 022-2542
|
||||||
|
EulaNotFound = 222543, // 022-2543
|
||||||
|
|
||||||
|
// Not acceptable errors
|
||||||
|
PhraseNotAcceptable = 222570, // 022-2570
|
||||||
|
AccountIdAlreadyExists = 222571, // 022-2571
|
||||||
|
AccountIdNotAcceptable = 222572, // 022-2572
|
||||||
|
AccountPasswordNotAcceptable = 222573, // 022-2573
|
||||||
|
MiiNameNotAcceptable = 222574, // 022-2574
|
||||||
|
MailAddressNotAcceptable = 222575, // 022-2575
|
||||||
|
AccountIdFormatInvalid = 222576, // 022-2576
|
||||||
|
AccountIdPasswordSame = 222577, // 022-2577
|
||||||
|
AccountIdCharNotAcceptable = 222578, // 022-2578
|
||||||
|
AccountIdSuccessiveSymbol = 222579, // 022-2579
|
||||||
|
AccountIdSymbolPositionNotAcceptable = 222580, // 022-2580
|
||||||
|
AccountIdTooManyDigit = 222581, // 022-2581
|
||||||
|
AccountPasswordCharNotAcceptable = 222582, // 022-2582
|
||||||
|
AccountPasswordTooFewCharTypes = 222583, // 022-2583
|
||||||
|
AccountPasswordSuccessiveSameChar = 222584, // 022-2584
|
||||||
|
MailAddressDomainNameNotAcceptable = 222585, // 022-2585
|
||||||
|
MailAddressDomainNameNotResolved = 222586, // 022-2586
|
||||||
|
ErrCode222587 = 222587, // 022-2587
|
||||||
|
|
||||||
|
ReachedAssociationLimit = 222591, // 022-2591
|
||||||
|
ReachedRegistrationLimit = 222592, // 022-2592
|
||||||
|
CoppaNotAccepted = 222593, // 022-2593
|
||||||
|
ParentalControlsRequired = 222594, // 022-2594
|
||||||
|
MiiNotRegistered = 222595, // 022-2595
|
||||||
|
DeviceEulaCountryMismatch = 222596, // 022-2596
|
||||||
|
PendingMigration = 222597, // 022-2597
|
||||||
|
|
||||||
|
// Wrong user input errors
|
||||||
|
WrongUserInput = 222610, // 022-2610
|
||||||
|
WrongAccountPassword = 222611, // 022-2611
|
||||||
|
WrongMailAddress = 222612, // 022-2612
|
||||||
|
WrongAccountPasswordOrMailAddress = 222613, // 022-2613
|
||||||
|
WrongConfirmationCode = 222614, // 022-2614
|
||||||
|
WrongBirthDateOrMailAddress = 222615, // 022-2615
|
||||||
|
WrongAccountMail = 222616, // 022-2616
|
||||||
|
|
||||||
|
AccountAlreadyDeleted = 222631, // 022-2631
|
||||||
|
AccountIdChanged = 222632, // 022-2632
|
||||||
|
AuthenticationLocked = 222633, // 022-2633
|
||||||
|
DeviceInactive = 222634, // 022-2634
|
||||||
|
CoppaAgreementCanceled = 222635, // 022-2635
|
||||||
|
DomainAccountAlreadyExists = 222636, // 022-2636
|
||||||
|
|
||||||
|
AccountTokenExpired = 222641, // 022-2641
|
||||||
|
InvalidAccountToken = 222642, // 022-2642
|
||||||
|
AuthenticationRequired = 222643, // 022-2643
|
||||||
|
ErrCode225844 = 225844, // 022-5844
|
||||||
|
|
||||||
|
ConfirmationCodeExpired = 222651, // 022-2651
|
||||||
|
|
||||||
|
MailAddressNotValidated = 222661, // 022-2661
|
||||||
|
ExcessiveMailSendRequest = 222662, // 022-2662
|
||||||
|
|
||||||
|
// Credit card errors
|
||||||
|
CreditCardError = 222670, // 022-2670
|
||||||
|
CreditCardGeneralFailure = 222671, // 022-2671
|
||||||
|
CreditCardDeclined = 222672, // 022-2672
|
||||||
|
CreditCardBlacklisted = 222673, // 022-2673
|
||||||
|
InvalidCreditCardNumber = 222674, // 022-2674
|
||||||
|
InvalidCreditCardDate = 222675, // 022-2675
|
||||||
|
InvalidCreditCardPin = 222676, // 022-2676
|
||||||
|
InvalidPostalCode = 222677, // 022-2677
|
||||||
|
InvalidLocation = 222678, // 022-2678
|
||||||
|
CreditCardDateExpired = 222679, // 022-2679
|
||||||
|
CreditCardNumberWrong = 222680, // 022-2680
|
||||||
|
CreditCardPinWrong = 222681, // 022-2681
|
||||||
|
|
||||||
|
// Ban errors
|
||||||
|
Banned = 222800, // 022-2800
|
||||||
|
BannedAccount = 222801, // 022-2801
|
||||||
|
BannedAccountAll = 222802, // 022-2802
|
||||||
|
BannedAccountInApplication = 222803, // 022-2803
|
||||||
|
BannedAccountInNexService = 222804, // 022-2804
|
||||||
|
BannedAccountInIndependentService = 222805, // 022-2805
|
||||||
|
BannedDevice = 222811, // 022-2811
|
||||||
|
BannedDeviceAll = 222812, // 022-2812
|
||||||
|
BannedDeviceInApplication = 222813, // 022-2813
|
||||||
|
BannedDeviceInNexService = 222814, // 022-2814
|
||||||
|
BannedDeviceInIndependentService = 222815, // 022-2815
|
||||||
|
BannedAccountTemporarily = 222821, // 022-2821
|
||||||
|
BannedAccountAllTemporarily = 222822, // 022-2822
|
||||||
|
BannedAccountInApplicationTemporarily = 222823, // 022-2823
|
||||||
|
BannedAccountInNexServiceTemporarily = 222824, // 022-2824
|
||||||
|
BannedAccountInIndependentServiceTemporarily = 222825, // 022-2825
|
||||||
|
BannedDeviceTemporarily = 222831, // 022-2831
|
||||||
|
BannedDeviceAllTemporarily = 222832, // 022-2832
|
||||||
|
BannedDeviceInApplicationTemporarily = 222833, // 022-2833
|
||||||
|
BannedDeviceInNexServiceTemporarily = 222834, // 022-2834
|
||||||
|
BannedDeviceInIndependentServiceTemporarily = 222835, // 022-2835
|
||||||
|
|
||||||
|
// Service not provided errors
|
||||||
|
ServiceNotProvided = 222880, // 022-2880
|
||||||
|
UnderMaintenance = 222881, // 022-2881
|
||||||
|
ServiceClosed = 222882, // 022-2882
|
||||||
|
NintendoNetworkClosed = 222883, // 022-2883
|
||||||
|
NotProvidedCountry = 222884, // 022-2884
|
||||||
|
|
||||||
|
// Restriction errors
|
||||||
|
RestrictionError = 222900, // 022-2900
|
||||||
|
RestrictedByAge = 222901, // 022-2901
|
||||||
|
RestrictedByParentalControls = 222910, // 022-2910
|
||||||
|
OnGameInternetCommunicationRestricted = 222911, // 022-2911
|
||||||
|
|
||||||
|
InternalServerError = 222931, // 022-2931
|
||||||
|
UnknownServerError = 222932, // 022-2932
|
||||||
|
|
||||||
|
UnauthenticatedAfterSalvage = 222998, // 022-2998
|
||||||
|
AuthenticationFailureUnknown = 222999, // 022-2999
|
||||||
|
Unknown = 229999, // 022-9999
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
|
/// Gets the ACT error code for the given result
|
||||||
|
u32 GetACTErrorCode(Result result);
|
||||||
|
|
||||||
|
} // namespace Service::ACT
|
@ -11,10 +11,31 @@ ACT_U::ACT_U(std::shared_ptr<Module> act) : Module::Interface(std::move(act), "a
|
|||||||
static const FunctionInfo functions[] = {
|
static const FunctionInfo functions[] = {
|
||||||
// clang-format off
|
// clang-format off
|
||||||
{0x0001, &ACT_U::Initialize, "Initialize"},
|
{0x0001, &ACT_U::Initialize, "Initialize"},
|
||||||
{0x0002, nullptr, "GetErrorCode"},
|
{0x0002, &ACT_U::GetErrorCode, "GetErrorCode"},
|
||||||
{0x0006, &ACT_U::GetAccountDataBlock, "GetAccountDataBlock"},
|
{0x0003, nullptr, "GetLastResponseCode"},
|
||||||
|
{0x0005, nullptr, "GetCommonInfo"},
|
||||||
|
{0x0006, &ACT_U::GetAccountInfo, "GetAccountInfo"},
|
||||||
|
{0x0007, nullptr, "GetResultAsync"},
|
||||||
|
{0x0008, nullptr, "GetMiiImageData"},
|
||||||
|
{0x0009, nullptr, "SetNfsPassword"},
|
||||||
{0x000B, nullptr, "AcquireEulaList"},
|
{0x000B, nullptr, "AcquireEulaList"},
|
||||||
|
{0x000C, nullptr, "AcquireTimeZoneList"},
|
||||||
{0x000D, nullptr, "GenerateUuid"},
|
{0x000D, nullptr, "GenerateUuid"},
|
||||||
|
{0x000F, nullptr, "FindSlotNoByUuid"},
|
||||||
|
{0x0010, nullptr, "SaveData"},
|
||||||
|
{0x0011, nullptr, "GetTransferableId"},
|
||||||
|
{0x0012, nullptr, "AcquireNexServiceToken"},
|
||||||
|
{0x0013, nullptr, "GetNexServiceToken"},
|
||||||
|
{0x0014, nullptr, "AcquireIndependentServiceToken"},
|
||||||
|
{0x0015, nullptr, "GetIndependentServiceToken"},
|
||||||
|
{0x0016, nullptr, "AcquireAccountInfo"},
|
||||||
|
{0x0017, nullptr, "AcquireAccountIdByPrincipalId"},
|
||||||
|
{0x0018, nullptr, "AcquirePrincipalIdByAccountId"},
|
||||||
|
{0x0019, nullptr, "AcquireMii"},
|
||||||
|
{0x001A, nullptr, "AcquireAccountInfoEx"},
|
||||||
|
{0x001D, nullptr, "InquireMailAddress"},
|
||||||
|
{0x001E, nullptr, "AcquireEula"},
|
||||||
|
{0x001F, nullptr, "AcquireEulaLanguageList"},
|
||||||
// clang-format on
|
// clang-format on
|
||||||
};
|
};
|
||||||
RegisterHandlers(functions);
|
RegisterHandlers(functions);
|
||||||
|
File diff suppressed because it is too large
Load Diff
@ -20,6 +20,7 @@
|
|||||||
#include "core/hle/kernel/mutex.h"
|
#include "core/hle/kernel/mutex.h"
|
||||||
#include "core/hle/result.h"
|
#include "core/hle/result.h"
|
||||||
#include "core/hle/service/service.h"
|
#include "core/hle/service/service.h"
|
||||||
|
#include "network/artic_base/artic_base_client.h"
|
||||||
|
|
||||||
namespace Core {
|
namespace Core {
|
||||||
class System;
|
class System;
|
||||||
@ -245,7 +246,13 @@ public:
|
|||||||
return am;
|
return am;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void UseArticClient(std::shared_ptr<Network::ArticBase::Client>& client) {
|
||||||
|
artic_client = client;
|
||||||
|
}
|
||||||
|
|
||||||
protected:
|
protected:
|
||||||
|
void GetProgramInfosImpl(Kernel::HLERequestContext& ctx, bool ignore_platform);
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* AM::GetNumPrograms service function
|
* AM::GetNumPrograms service function
|
||||||
* Gets the number of installed titles in the requested media type
|
* Gets the number of installed titles in the requested media type
|
||||||
@ -753,6 +760,9 @@ public:
|
|||||||
|
|
||||||
protected:
|
protected:
|
||||||
std::shared_ptr<Module> am;
|
std::shared_ptr<Module> am;
|
||||||
|
|
||||||
|
// Placed on the interface level so that only am:net and am:app have it.
|
||||||
|
std::shared_ptr<Network::ArticBase::Client> artic_client = nullptr;
|
||||||
};
|
};
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
@ -544,6 +544,7 @@ void Y2R_U::StopConversion(Kernel::HLERequestContext& ctx) {
|
|||||||
IPC::RequestParser rp(ctx);
|
IPC::RequestParser rp(ctx);
|
||||||
|
|
||||||
if (is_busy_conversion) {
|
if (is_busy_conversion) {
|
||||||
|
is_busy_conversion = false;
|
||||||
system.CoreTiming().RemoveEvent(completion_signal_event);
|
system.CoreTiming().RemoveEvent(completion_signal_event);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -9,7 +9,7 @@
|
|||||||
#include <boost/serialization/unique_ptr.hpp>
|
#include <boost/serialization/unique_ptr.hpp>
|
||||||
#include <cryptopp/osrng.h>
|
#include <cryptopp/osrng.h>
|
||||||
#include <cryptopp/sha.h>
|
#include <cryptopp/sha.h>
|
||||||
#include <fmt/format.h>
|
#include <fmt/ranges.h>
|
||||||
#include "common/archives.h"
|
#include "common/archives.h"
|
||||||
#include "common/file_util.h"
|
#include "common/file_util.h"
|
||||||
#include "common/logging/log.h"
|
#include "common/logging/log.h"
|
||||||
@ -278,7 +278,7 @@ void Module::Interface::GetTransferableId(Kernel::HLERequestContext& ctx) {
|
|||||||
|
|
||||||
std::array<u8, 12> buffer;
|
std::array<u8, 12> buffer;
|
||||||
const Result result =
|
const Result result =
|
||||||
cfg->GetConfigBlock(ConsoleUniqueID2BlockID, 8, AccessFlag::SystemRead, buffer.data());
|
cfg->GetConfigBlock(ConsoleUniqueID2BlockID, 8, AccessFlag::Global, buffer.data());
|
||||||
rb.Push(result);
|
rb.Push(result);
|
||||||
if (result.IsSuccess()) {
|
if (result.IsSuccess()) {
|
||||||
std::memcpy(&buffer[8], &app_id_salt, sizeof(u32));
|
std::memcpy(&buffer[8], &app_id_salt, sizeof(u32));
|
||||||
@ -502,11 +502,42 @@ ResultVal<void*> Module::GetConfigBlockPointer(u32 block_id, u32 size, AccessFla
|
|||||||
}
|
}
|
||||||
|
|
||||||
Result Module::GetConfigBlock(u32 block_id, u32 size, AccessFlag accesss_flag, void* output) {
|
Result Module::GetConfigBlock(u32 block_id, u32 size, AccessFlag accesss_flag, void* output) {
|
||||||
void* pointer = nullptr;
|
bool get_from_artic =
|
||||||
CASCADE_RESULT(pointer, GetConfigBlockPointer(block_id, size, accesss_flag));
|
block_id == ConsoleUniqueID2BlockID &&
|
||||||
std::memcpy(output, pointer, size);
|
(static_cast<u16>(accesss_flag) & static_cast<u16>(AccessFlag::UserRead)) != 0;
|
||||||
|
|
||||||
return ResultSuccess;
|
if (get_from_artic && artic_client.get()) {
|
||||||
|
auto req = artic_client->NewRequest("CFGU_GetConfigInfoBlk2");
|
||||||
|
|
||||||
|
req.AddParameterS32(block_id);
|
||||||
|
req.AddParameterU32(size);
|
||||||
|
|
||||||
|
auto resp = artic_client->Send(req);
|
||||||
|
|
||||||
|
if (!resp.has_value() || !resp->Succeeded())
|
||||||
|
return Result(-1);
|
||||||
|
|
||||||
|
auto res = Result(static_cast<u32>(resp->GetMethodResult()));
|
||||||
|
if (res.IsError())
|
||||||
|
return res;
|
||||||
|
|
||||||
|
auto buff = resp->GetResponseBuffer(0);
|
||||||
|
if (!buff.has_value())
|
||||||
|
return Result(-1);
|
||||||
|
size_t actually_read = buff->second;
|
||||||
|
if (actually_read > size)
|
||||||
|
return Result(-1);
|
||||||
|
|
||||||
|
memcpy(output, buff->first, actually_read);
|
||||||
|
return ResultSuccess;
|
||||||
|
|
||||||
|
} else {
|
||||||
|
void* pointer = nullptr;
|
||||||
|
CASCADE_RESULT(pointer, GetConfigBlockPointer(block_id, size, accesss_flag));
|
||||||
|
std::memcpy(output, pointer, size);
|
||||||
|
|
||||||
|
return ResultSuccess;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
Result Module::SetConfigBlock(u32 block_id, u32 size, AccessFlag accesss_flag, const void* input) {
|
Result Module::SetConfigBlock(u32 block_id, u32 size, AccessFlag accesss_flag, const void* input) {
|
||||||
|
@ -11,6 +11,7 @@
|
|||||||
#include <utility>
|
#include <utility>
|
||||||
#include "common/common_types.h"
|
#include "common/common_types.h"
|
||||||
#include "core/hle/service/service.h"
|
#include "core/hle/service/service.h"
|
||||||
|
#include "network/artic_base/artic_base_client.h"
|
||||||
|
|
||||||
namespace FileSys {
|
namespace FileSys {
|
||||||
class ArchiveBackend;
|
class ArchiveBackend;
|
||||||
@ -210,6 +211,10 @@ public:
|
|||||||
|
|
||||||
std::shared_ptr<Module> GetModule() const;
|
std::shared_ptr<Module> GetModule() const;
|
||||||
|
|
||||||
|
void UseArticClient(std::shared_ptr<Network::ArticBase::Client>& client) {
|
||||||
|
GetModule()->artic_client = client;
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* CFG::GetCountryCodeString service function
|
* CFG::GetCountryCodeString service function
|
||||||
* Inputs:
|
* Inputs:
|
||||||
@ -680,6 +685,8 @@ private:
|
|||||||
bool preferred_region_chosen = false;
|
bool preferred_region_chosen = false;
|
||||||
MCUData mcu_data{};
|
MCUData mcu_data{};
|
||||||
|
|
||||||
|
std::shared_ptr<Network::ArticBase::Client> artic_client = nullptr;
|
||||||
|
|
||||||
template <class Archive>
|
template <class Archive>
|
||||||
void serialize(Archive& ar, const unsigned int);
|
void serialize(Archive& ar, const unsigned int);
|
||||||
friend class boost::serialization::access;
|
friend class boost::serialization::access;
|
||||||
|
@ -298,18 +298,22 @@ Result ArchiveManager::DeleteSystemSaveData(u32 high, u32 low) {
|
|||||||
return ResultSuccess;
|
return ResultSuccess;
|
||||||
}
|
}
|
||||||
|
|
||||||
Result ArchiveManager::CreateSystemSaveData(u32 high, u32 low) {
|
Result ArchiveManager::CreateSystemSaveData(u32 high, u32 low, u32 total_size, u32 block_size,
|
||||||
// Construct the binary path to the archive first
|
u32 number_directories, u32 number_files,
|
||||||
const FileSys::Path path = FileSys::ConstructSystemSaveDataBinaryPath(high, low);
|
u32 number_directory_buckets, u32 number_file_buckets,
|
||||||
|
u8 duplicate_data) {
|
||||||
|
|
||||||
const std::string& nand_directory = FileUtil::GetUserPath(FileUtil::UserPath::NANDDir);
|
auto archive = id_code_map.find(ArchiveIdCode::SystemSaveData);
|
||||||
const std::string base_path = FileSys::GetSystemSaveDataContainerPath(nand_directory);
|
|
||||||
const std::string systemsavedata_path = FileSys::GetSystemSaveDataPath(base_path, path);
|
if (archive == id_code_map.end()) {
|
||||||
if (!FileUtil::CreateFullPath(systemsavedata_path)) {
|
return UnimplementedFunction(ErrorModule::FS); // TODO(Subv): Find the right error
|
||||||
return ResultUnknown; // TODO(Subv): Find the right error code
|
|
||||||
}
|
}
|
||||||
|
|
||||||
return ResultSuccess;
|
auto sys_savedata = static_cast<FileSys::ArchiveFactory_SystemSaveData*>(archive->second.get());
|
||||||
|
|
||||||
|
return sys_savedata->FormatAsSysData(high, low, total_size, block_size, number_directories,
|
||||||
|
number_files, number_directory_buckets,
|
||||||
|
number_file_buckets, duplicate_data);
|
||||||
}
|
}
|
||||||
|
|
||||||
ResultVal<ArchiveResource> ArchiveManager::GetArchiveResource(MediaType media_type) const {
|
ResultVal<ArchiveResource> ArchiveManager::GetArchiveResource(MediaType media_type) const {
|
||||||
@ -454,6 +458,16 @@ void ArchiveManager::RegisterArticNCCH(std::shared_ptr<Network::ArticBase::Clien
|
|||||||
reinterpret_cast<FileSys::ArchiveFactory_NCCH*>(itr->second.get())->RegisterArtic(client);
|
reinterpret_cast<FileSys::ArchiveFactory_NCCH*>(itr->second.get())->RegisterArtic(client);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void ArchiveManager::RegisterArticSystemSaveData(
|
||||||
|
std::shared_ptr<Network::ArticBase::Client>& client) {
|
||||||
|
auto itr = id_code_map.find(ArchiveIdCode::SystemSaveData);
|
||||||
|
if (itr == id_code_map.end() || itr->second.get() == nullptr) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
reinterpret_cast<FileSys::ArchiveFactory_SystemSaveData*>(itr->second.get())
|
||||||
|
->RegisterArtic(client);
|
||||||
|
}
|
||||||
|
|
||||||
ArchiveManager::ArchiveManager(Core::System& system) : system(system) {
|
ArchiveManager::ArchiveManager(Core::System& system) : system(system) {
|
||||||
RegisterArchiveTypes();
|
RegisterArchiveTypes();
|
||||||
}
|
}
|
||||||
|
@ -264,11 +264,12 @@ public:
|
|||||||
|
|
||||||
/**
|
/**
|
||||||
* Creates the SystemSaveData archive folder for the specified save data id
|
* Creates the SystemSaveData archive folder for the specified save data id
|
||||||
* @param high The high word of the SystemSaveData archive to create
|
|
||||||
* @param low The low word of the SystemSaveData archive to create
|
|
||||||
* @return Result 0 on success or the corresponding code on error
|
* @return Result 0 on success or the corresponding code on error
|
||||||
*/
|
*/
|
||||||
Result CreateSystemSaveData(u32 high, u32 low);
|
Result CreateSystemSaveData(u32 high, u32 low, u32 total_size, u32 block_size,
|
||||||
|
u32 number_directories, u32 number_files,
|
||||||
|
u32 number_directory_buckets, u32 number_file_buckets,
|
||||||
|
u8 duplicate_data);
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Returns capacity and free space information about the given media type.
|
* Returns capacity and free space information about the given media type.
|
||||||
@ -296,6 +297,8 @@ public:
|
|||||||
|
|
||||||
void RegisterArticNCCH(std::shared_ptr<Network::ArticBase::Client>& client);
|
void RegisterArticNCCH(std::shared_ptr<Network::ArticBase::Client>& client);
|
||||||
|
|
||||||
|
void RegisterArticSystemSaveData(std::shared_ptr<Network::ArticBase::Client>& client);
|
||||||
|
|
||||||
private:
|
private:
|
||||||
Core::System& system;
|
Core::System& system;
|
||||||
|
|
||||||
|
@ -1026,7 +1026,9 @@ void FS_USER::CreateSystemSaveData(Kernel::HLERequestContext& ctx) {
|
|||||||
file_buckets, duplicate);
|
file_buckets, duplicate);
|
||||||
|
|
||||||
IPC::RequestBuilder rb = rp.MakeBuilder(1, 0);
|
IPC::RequestBuilder rb = rp.MakeBuilder(1, 0);
|
||||||
rb.Push(archives.CreateSystemSaveData(savedata_high, savedata_low));
|
rb.Push(archives.CreateSystemSaveData(savedata_high, savedata_low, total_size, block_size,
|
||||||
|
directories, files, directory_buckets, file_buckets,
|
||||||
|
duplicate ? 1 : 0));
|
||||||
}
|
}
|
||||||
|
|
||||||
void FS_USER::CreateLegacySystemSaveData(Kernel::HLERequestContext& ctx) {
|
void FS_USER::CreateLegacySystemSaveData(Kernel::HLERequestContext& ctx) {
|
||||||
@ -1048,7 +1050,8 @@ void FS_USER::CreateLegacySystemSaveData(Kernel::HLERequestContext& ctx) {
|
|||||||
|
|
||||||
IPC::RequestBuilder rb = rp.MakeBuilder(1, 0);
|
IPC::RequestBuilder rb = rp.MakeBuilder(1, 0);
|
||||||
// With this command, the SystemSaveData always has save_high = 0 (Always created in the NAND)
|
// With this command, the SystemSaveData always has save_high = 0 (Always created in the NAND)
|
||||||
rb.Push(archives.CreateSystemSaveData(0, savedata_id));
|
rb.Push(archives.CreateSystemSaveData(0, savedata_id, total_size, block_size, directories,
|
||||||
|
files, directory_buckets, file_buckets, duplicate));
|
||||||
}
|
}
|
||||||
|
|
||||||
void FS_USER::InitializeWithSdkVersion(Kernel::HLERequestContext& ctx) {
|
void FS_USER::InitializeWithSdkVersion(Kernel::HLERequestContext& ctx) {
|
||||||
|
@ -71,7 +71,12 @@ struct CacheFlushCommand {
|
|||||||
|
|
||||||
/// GSP command
|
/// GSP command
|
||||||
struct Command {
|
struct Command {
|
||||||
BitField<0, 8, CommandId> id;
|
union {
|
||||||
|
BitField<0, 8, CommandId> id;
|
||||||
|
BitField<8, 8, u32> unknown1;
|
||||||
|
BitField<16, 8, u32> stop;
|
||||||
|
BitField<24, 8, u32> unknown2;
|
||||||
|
};
|
||||||
union {
|
union {
|
||||||
DmaCommand dma_request;
|
DmaCommand dma_request;
|
||||||
SubmitCmdListCommand submit_gpu_cmdlist;
|
SubmitCmdListCommand submit_gpu_cmdlist;
|
||||||
@ -86,6 +91,8 @@ static_assert(sizeof(Command) == 0x20, "Command struct has incorrect size");
|
|||||||
|
|
||||||
/// GSP shared memory GX command buffer header
|
/// GSP shared memory GX command buffer header
|
||||||
struct CommandBuffer {
|
struct CommandBuffer {
|
||||||
|
static constexpr u32 STATUS_STOPPED = 0x1;
|
||||||
|
static constexpr u32 STATUS_CMD_FAILED = 0x80;
|
||||||
union {
|
union {
|
||||||
u32 hex;
|
u32 hex;
|
||||||
|
|
||||||
@ -99,6 +106,11 @@ struct CommandBuffer {
|
|||||||
// application when writing a command to shared memory, after increasing this value
|
// application when writing a command to shared memory, after increasing this value
|
||||||
// TriggerCmdReqQueue is only used if this field is value 1.
|
// TriggerCmdReqQueue is only used if this field is value 1.
|
||||||
BitField<8, 8, u32> number_commands;
|
BitField<8, 8, u32> number_commands;
|
||||||
|
|
||||||
|
// When any of the following flags are set to 1, the GSP module stops processing the
|
||||||
|
// commands in the command buffer.
|
||||||
|
BitField<16, 8, u32> status;
|
||||||
|
BitField<24, 8, u32> should_stop;
|
||||||
};
|
};
|
||||||
|
|
||||||
u32 unk[7];
|
u32 unk[7];
|
||||||
|
@ -9,6 +9,7 @@
|
|||||||
#include <boost/serialization/shared_ptr.hpp>
|
#include <boost/serialization/shared_ptr.hpp>
|
||||||
#include "common/archives.h"
|
#include "common/archives.h"
|
||||||
#include "common/bit_field.h"
|
#include "common/bit_field.h"
|
||||||
|
#include "common/settings.h"
|
||||||
#include "core/core.h"
|
#include "core/core.h"
|
||||||
#include "core/hle/ipc_helpers.h"
|
#include "core/hle/ipc_helpers.h"
|
||||||
#include "core/hle/kernel/shared_memory.h"
|
#include "core/hle/kernel/shared_memory.h"
|
||||||
@ -408,21 +409,54 @@ void GSP_GPU::SetLcdForceBlack(Kernel::HLERequestContext& ctx) {
|
|||||||
void GSP_GPU::TriggerCmdReqQueue(Kernel::HLERequestContext& ctx) {
|
void GSP_GPU::TriggerCmdReqQueue(Kernel::HLERequestContext& ctx) {
|
||||||
IPC::RequestParser rp(ctx);
|
IPC::RequestParser rp(ctx);
|
||||||
|
|
||||||
// Iterate through each command.
|
|
||||||
auto* command_buffer = GetCommandBuffer(active_thread_id);
|
auto* command_buffer = GetCommandBuffer(active_thread_id);
|
||||||
auto& gpu = system.GPU();
|
auto& gpu = system.GPU();
|
||||||
for (u32 i = 0; i < command_buffer->number_commands; i++) {
|
|
||||||
gpu.Debugger().GXCommandProcessed(command_buffer->commands[i]);
|
bool requires_delay = false;
|
||||||
|
|
||||||
|
while (command_buffer->number_commands) {
|
||||||
|
if (command_buffer->should_stop) {
|
||||||
|
command_buffer->status.Assign(CommandBuffer::STATUS_STOPPED);
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
if (command_buffer->status == CommandBuffer::STATUS_STOPPED) {
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
Command command = command_buffer->commands[command_buffer->index];
|
||||||
|
if (command.id == CommandId::SubmitCmdList && !requires_delay &&
|
||||||
|
Settings::values.delay_game_render_thread_us.GetValue() != 0) {
|
||||||
|
requires_delay = true;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Decrease the number of commands remaining and increase the current index
|
||||||
|
command_buffer->number_commands.Assign(command_buffer->number_commands - 1);
|
||||||
|
command_buffer->index.Assign((command_buffer->index + 1) % 0xF);
|
||||||
|
|
||||||
|
gpu.Debugger().GXCommandProcessed(command);
|
||||||
|
|
||||||
// Decode and execute command
|
// Decode and execute command
|
||||||
gpu.Execute(command_buffer->commands[i]);
|
gpu.Execute(command);
|
||||||
|
|
||||||
// Indicates that command has completed
|
if (command.stop) {
|
||||||
command_buffer->number_commands.Assign(command_buffer->number_commands - 1);
|
command_buffer->should_stop.Assign(1);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
IPC::RequestBuilder rb = rp.MakeBuilder(1, 0);
|
if (requires_delay) {
|
||||||
rb.Push(ResultSuccess);
|
ctx.RunAsync(
|
||||||
|
[](Kernel::HLERequestContext& ctx) {
|
||||||
|
return Settings::values.delay_game_render_thread_us.GetValue() * 1000;
|
||||||
|
},
|
||||||
|
[](Kernel::HLERequestContext& ctx) {
|
||||||
|
IPC::RequestBuilder rb(ctx, 1, 0);
|
||||||
|
rb.Push(ResultSuccess);
|
||||||
|
},
|
||||||
|
false);
|
||||||
|
} else {
|
||||||
|
IPC::RequestBuilder rb = rp.MakeBuilder(1, 0);
|
||||||
|
rb.Push(ResultSuccess);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void GSP_GPU::ImportDisplayCaptureInfo(Kernel::HLERequestContext& ctx) {
|
void GSP_GPU::ImportDisplayCaptureInfo(Kernel::HLERequestContext& ctx) {
|
||||||
|
@ -20,6 +20,8 @@
|
|||||||
#include "core/hle/service/hid/hid.h"
|
#include "core/hle/service/hid/hid.h"
|
||||||
#include "core/hle/service/hid/hid_spvr.h"
|
#include "core/hle/service/hid/hid_spvr.h"
|
||||||
#include "core/hle/service/hid/hid_user.h"
|
#include "core/hle/service/hid/hid_user.h"
|
||||||
|
#include "core/hle/service/ir/ir_rst.h"
|
||||||
|
#include "core/hle/service/ir/ir_user.h"
|
||||||
#include "core/hle/service/service.h"
|
#include "core/hle/service/service.h"
|
||||||
#include "core/movie.h"
|
#include "core/movie.h"
|
||||||
|
|
||||||
@ -53,6 +55,32 @@ void Module::serialize(Archive& ar, const unsigned int file_version) {
|
|||||||
}
|
}
|
||||||
SERIALIZE_IMPL(Module)
|
SERIALIZE_IMPL(Module)
|
||||||
|
|
||||||
|
ArticBaseController::ArticBaseController(
|
||||||
|
const std::shared_ptr<Network::ArticBase::Client>& client) {
|
||||||
|
|
||||||
|
udp_stream =
|
||||||
|
client->NewUDPStream("ArticController", sizeof(ArticBaseController::ControllerData),
|
||||||
|
std::chrono::milliseconds(2));
|
||||||
|
if (udp_stream.get()) {
|
||||||
|
udp_stream->Start();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
ArticBaseController::ControllerData ArticBaseController::GetControllerData() {
|
||||||
|
|
||||||
|
if (udp_stream.get() && udp_stream->IsReady()) {
|
||||||
|
auto data = udp_stream->GetLastPacket();
|
||||||
|
if (data.size() == sizeof(ControllerData)) {
|
||||||
|
u32 id = *reinterpret_cast<u32*>(data.data());
|
||||||
|
if ((id - last_packet_id) < (std::numeric_limits<u32>::max() / 2)) {
|
||||||
|
last_packet_id = id;
|
||||||
|
memcpy(&last_controller_data, data.data(), data.size());
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return last_controller_data;
|
||||||
|
}
|
||||||
|
|
||||||
constexpr float accelerometer_coef = 512.0f; // measured from hw test result
|
constexpr float accelerometer_coef = 512.0f; // measured from hw test result
|
||||||
constexpr float gyroscope_coef = 14.375f; // got from hwtest GetGyroscopeLowRawToDpsCoefficient call
|
constexpr float gyroscope_coef = 14.375f; // got from hwtest GetGyroscopeLowRawToDpsCoefficient call
|
||||||
|
|
||||||
@ -111,96 +139,151 @@ void Module::UpdatePadCallback(std::uintptr_t user_data, s64 cycles_late) {
|
|||||||
LoadInputDevices();
|
LoadInputDevices();
|
||||||
|
|
||||||
using namespace Settings::NativeButton;
|
using namespace Settings::NativeButton;
|
||||||
state.a.Assign(buttons[A - BUTTON_HID_BEGIN]->GetStatus());
|
|
||||||
state.b.Assign(buttons[B - BUTTON_HID_BEGIN]->GetStatus());
|
|
||||||
state.x.Assign(buttons[X - BUTTON_HID_BEGIN]->GetStatus());
|
|
||||||
state.y.Assign(buttons[Y - BUTTON_HID_BEGIN]->GetStatus());
|
|
||||||
state.right.Assign(buttons[Right - BUTTON_HID_BEGIN]->GetStatus());
|
|
||||||
state.left.Assign(buttons[Left - BUTTON_HID_BEGIN]->GetStatus());
|
|
||||||
state.up.Assign(buttons[Up - BUTTON_HID_BEGIN]->GetStatus());
|
|
||||||
state.down.Assign(buttons[Down - BUTTON_HID_BEGIN]->GetStatus());
|
|
||||||
state.l.Assign(buttons[L - BUTTON_HID_BEGIN]->GetStatus());
|
|
||||||
state.r.Assign(buttons[R - BUTTON_HID_BEGIN]->GetStatus());
|
|
||||||
state.start.Assign(buttons[Start - BUTTON_HID_BEGIN]->GetStatus());
|
|
||||||
state.select.Assign(buttons[Select - BUTTON_HID_BEGIN]->GetStatus());
|
|
||||||
state.debug.Assign(buttons[Debug - BUTTON_HID_BEGIN]->GetStatus());
|
|
||||||
state.gpio14.Assign(buttons[Gpio14 - BUTTON_HID_BEGIN]->GetStatus());
|
|
||||||
|
|
||||||
// Get current circle pad position and update circle pad direction
|
if (artic_controller.get() && artic_controller->IsReady()) {
|
||||||
float circle_pad_x_f, circle_pad_y_f;
|
constexpr u32 HID_VALID_KEYS = 0xF0003FFF;
|
||||||
std::tie(circle_pad_x_f, circle_pad_y_f) = circle_pad->GetStatus();
|
constexpr u32 LIBCTRU_TOUCH_KEY = (1 << 20);
|
||||||
|
|
||||||
// xperia64: 0x9A seems to be the calibrated limit of the circle pad
|
ArticBaseController::ControllerData data = artic_controller->GetControllerData();
|
||||||
// Verified by using Input Redirector with very large-value digital inputs
|
|
||||||
// on the circle pad and calibrating using the system settings application
|
|
||||||
constexpr int MAX_CIRCLEPAD_POS = 0x9A; // Max value for a circle pad position
|
|
||||||
|
|
||||||
// These are rounded rather than truncated on actual hardware
|
state.hex = data.pad & HID_VALID_KEYS;
|
||||||
s16 circle_pad_new_x = static_cast<s16>(std::roundf(circle_pad_x_f * MAX_CIRCLEPAD_POS));
|
|
||||||
s16 circle_pad_new_y = static_cast<s16>(std::roundf(circle_pad_y_f * MAX_CIRCLEPAD_POS));
|
|
||||||
s16 circle_pad_x =
|
|
||||||
(circle_pad_new_x + std::accumulate(circle_pad_old_x.begin(), circle_pad_old_x.end(), 0)) /
|
|
||||||
CIRCLE_PAD_AVERAGING;
|
|
||||||
s16 circle_pad_y =
|
|
||||||
(circle_pad_new_y + std::accumulate(circle_pad_old_y.begin(), circle_pad_old_y.end(), 0)) /
|
|
||||||
CIRCLE_PAD_AVERAGING;
|
|
||||||
circle_pad_old_x.erase(circle_pad_old_x.begin());
|
|
||||||
circle_pad_old_x.push_back(circle_pad_new_x);
|
|
||||||
circle_pad_old_y.erase(circle_pad_old_y.begin());
|
|
||||||
circle_pad_old_y.push_back(circle_pad_new_y);
|
|
||||||
|
|
||||||
system.Movie().HandlePadAndCircleStatus(state, circle_pad_x, circle_pad_y);
|
s16 circle_pad_x = data.c_pad_x;
|
||||||
|
s16 circle_pad_y = data.c_pad_y;
|
||||||
|
|
||||||
const DirectionState direction = GetStickDirectionState(circle_pad_x, circle_pad_y);
|
system.Movie().HandlePadAndCircleStatus(state, circle_pad_x, circle_pad_y);
|
||||||
state.circle_up.Assign(direction.up);
|
|
||||||
state.circle_down.Assign(direction.down);
|
|
||||||
state.circle_left.Assign(direction.left);
|
|
||||||
state.circle_right.Assign(direction.right);
|
|
||||||
|
|
||||||
mem->pad.current_state.hex = state.hex;
|
mem->pad.current_state.hex = state.hex;
|
||||||
mem->pad.index = next_pad_index;
|
mem->pad.index = next_pad_index;
|
||||||
next_pad_index = (next_pad_index + 1) % mem->pad.entries.size();
|
next_pad_index = (next_pad_index + 1) % mem->pad.entries.size();
|
||||||
|
|
||||||
// Get the previous Pad state
|
// Get the previous Pad state
|
||||||
u32 last_entry_index = (mem->pad.index - 1) % mem->pad.entries.size();
|
u32 last_entry_index = (mem->pad.index - 1) % mem->pad.entries.size();
|
||||||
PadState old_state = mem->pad.entries[last_entry_index].current_state;
|
PadState old_state = mem->pad.entries[last_entry_index].current_state;
|
||||||
|
|
||||||
// Compute bitmask with 1s for bits different from the old state
|
// Compute bitmask with 1s for bits different from the old state
|
||||||
PadState changed = {{(state.hex ^ old_state.hex)}};
|
PadState changed = {{(state.hex ^ old_state.hex)}};
|
||||||
|
|
||||||
// Get the current Pad entry
|
// Get the current Pad entry
|
||||||
PadDataEntry& pad_entry = mem->pad.entries[mem->pad.index];
|
PadDataEntry& pad_entry = mem->pad.entries[mem->pad.index];
|
||||||
|
|
||||||
// Update entry properties
|
// Update entry properties
|
||||||
pad_entry.current_state.hex = state.hex;
|
pad_entry.current_state.hex = state.hex;
|
||||||
pad_entry.delta_additions.hex = changed.hex & state.hex;
|
pad_entry.delta_additions.hex = changed.hex & state.hex;
|
||||||
pad_entry.delta_removals.hex = changed.hex & old_state.hex;
|
pad_entry.delta_removals.hex = changed.hex & old_state.hex;
|
||||||
pad_entry.circle_pad_x = circle_pad_x;
|
pad_entry.circle_pad_x = circle_pad_x;
|
||||||
pad_entry.circle_pad_y = circle_pad_y;
|
pad_entry.circle_pad_y = circle_pad_y;
|
||||||
|
|
||||||
// If we just updated index 0, provide a new timestamp
|
// If we just updated index 0, provide a new timestamp
|
||||||
if (mem->pad.index == 0) {
|
if (mem->pad.index == 0) {
|
||||||
mem->pad.index_reset_ticks_previous = mem->pad.index_reset_ticks;
|
mem->pad.index_reset_ticks_previous = mem->pad.index_reset_ticks;
|
||||||
mem->pad.index_reset_ticks = (s64)system.CoreTiming().GetTicks();
|
mem->pad.index_reset_ticks = (s64)system.CoreTiming().GetTicks();
|
||||||
|
}
|
||||||
|
|
||||||
|
mem->touch.index = next_touch_index;
|
||||||
|
next_touch_index = (next_touch_index + 1) % mem->touch.entries.size();
|
||||||
|
|
||||||
|
// Get the current touch entry
|
||||||
|
TouchDataEntry& touch_entry = mem->touch.entries[mem->touch.index];
|
||||||
|
bool pressed = (data.pad & LIBCTRU_TOUCH_KEY) != 0;
|
||||||
|
|
||||||
|
touch_entry.x = static_cast<u16>(data.touch_x);
|
||||||
|
touch_entry.y = static_cast<u16>(data.touch_y);
|
||||||
|
touch_entry.valid.Assign(pressed ? 1 : 0);
|
||||||
|
|
||||||
|
system.Movie().HandleTouchStatus(touch_entry);
|
||||||
|
} else {
|
||||||
|
state.a.Assign(buttons[A - BUTTON_HID_BEGIN]->GetStatus());
|
||||||
|
state.b.Assign(buttons[B - BUTTON_HID_BEGIN]->GetStatus());
|
||||||
|
state.x.Assign(buttons[X - BUTTON_HID_BEGIN]->GetStatus());
|
||||||
|
state.y.Assign(buttons[Y - BUTTON_HID_BEGIN]->GetStatus());
|
||||||
|
state.right.Assign(buttons[Right - BUTTON_HID_BEGIN]->GetStatus());
|
||||||
|
state.left.Assign(buttons[Left - BUTTON_HID_BEGIN]->GetStatus());
|
||||||
|
state.up.Assign(buttons[Up - BUTTON_HID_BEGIN]->GetStatus());
|
||||||
|
state.down.Assign(buttons[Down - BUTTON_HID_BEGIN]->GetStatus());
|
||||||
|
state.l.Assign(buttons[L - BUTTON_HID_BEGIN]->GetStatus());
|
||||||
|
state.r.Assign(buttons[R - BUTTON_HID_BEGIN]->GetStatus());
|
||||||
|
state.start.Assign(buttons[Start - BUTTON_HID_BEGIN]->GetStatus());
|
||||||
|
state.select.Assign(buttons[Select - BUTTON_HID_BEGIN]->GetStatus());
|
||||||
|
state.debug.Assign(buttons[Debug - BUTTON_HID_BEGIN]->GetStatus());
|
||||||
|
state.gpio14.Assign(buttons[Gpio14 - BUTTON_HID_BEGIN]->GetStatus());
|
||||||
|
|
||||||
|
// Get current circle pad position and update circle pad direction
|
||||||
|
float circle_pad_x_f, circle_pad_y_f;
|
||||||
|
std::tie(circle_pad_x_f, circle_pad_y_f) = circle_pad->GetStatus();
|
||||||
|
|
||||||
|
// xperia64: 0x9A seems to be the calibrated limit of the circle pad
|
||||||
|
// Verified by using Input Redirector with very large-value digital inputs
|
||||||
|
// on the circle pad and calibrating using the system settings application
|
||||||
|
constexpr int MAX_CIRCLEPAD_POS = 0x9A; // Max value for a circle pad position
|
||||||
|
|
||||||
|
// These are rounded rather than truncated on actual hardware
|
||||||
|
s16 circle_pad_new_x = static_cast<s16>(std::roundf(circle_pad_x_f * MAX_CIRCLEPAD_POS));
|
||||||
|
s16 circle_pad_new_y = static_cast<s16>(std::roundf(circle_pad_y_f * MAX_CIRCLEPAD_POS));
|
||||||
|
s16 circle_pad_x = (circle_pad_new_x +
|
||||||
|
std::accumulate(circle_pad_old_x.begin(), circle_pad_old_x.end(), 0)) /
|
||||||
|
CIRCLE_PAD_AVERAGING;
|
||||||
|
s16 circle_pad_y = (circle_pad_new_y +
|
||||||
|
std::accumulate(circle_pad_old_y.begin(), circle_pad_old_y.end(), 0)) /
|
||||||
|
CIRCLE_PAD_AVERAGING;
|
||||||
|
circle_pad_old_x.erase(circle_pad_old_x.begin());
|
||||||
|
circle_pad_old_x.push_back(circle_pad_new_x);
|
||||||
|
circle_pad_old_y.erase(circle_pad_old_y.begin());
|
||||||
|
circle_pad_old_y.push_back(circle_pad_new_y);
|
||||||
|
|
||||||
|
system.Movie().HandlePadAndCircleStatus(state, circle_pad_x, circle_pad_y);
|
||||||
|
|
||||||
|
const DirectionState direction = GetStickDirectionState(circle_pad_x, circle_pad_y);
|
||||||
|
state.circle_up.Assign(direction.up);
|
||||||
|
state.circle_down.Assign(direction.down);
|
||||||
|
state.circle_left.Assign(direction.left);
|
||||||
|
state.circle_right.Assign(direction.right);
|
||||||
|
|
||||||
|
mem->pad.current_state.hex = state.hex;
|
||||||
|
mem->pad.index = next_pad_index;
|
||||||
|
next_pad_index = (next_pad_index + 1) % mem->pad.entries.size();
|
||||||
|
|
||||||
|
// Get the previous Pad state
|
||||||
|
u32 last_entry_index = (mem->pad.index - 1) % mem->pad.entries.size();
|
||||||
|
PadState old_state = mem->pad.entries[last_entry_index].current_state;
|
||||||
|
|
||||||
|
// Compute bitmask with 1s for bits different from the old state
|
||||||
|
PadState changed = {{(state.hex ^ old_state.hex)}};
|
||||||
|
|
||||||
|
// Get the current Pad entry
|
||||||
|
PadDataEntry& pad_entry = mem->pad.entries[mem->pad.index];
|
||||||
|
|
||||||
|
// Update entry properties
|
||||||
|
pad_entry.current_state.hex = state.hex;
|
||||||
|
pad_entry.delta_additions.hex = changed.hex & state.hex;
|
||||||
|
pad_entry.delta_removals.hex = changed.hex & old_state.hex;
|
||||||
|
pad_entry.circle_pad_x = circle_pad_x;
|
||||||
|
pad_entry.circle_pad_y = circle_pad_y;
|
||||||
|
|
||||||
|
// If we just updated index 0, provide a new timestamp
|
||||||
|
if (mem->pad.index == 0) {
|
||||||
|
mem->pad.index_reset_ticks_previous = mem->pad.index_reset_ticks;
|
||||||
|
mem->pad.index_reset_ticks = (s64)system.CoreTiming().GetTicks();
|
||||||
|
}
|
||||||
|
|
||||||
|
mem->touch.index = next_touch_index;
|
||||||
|
next_touch_index = (next_touch_index + 1) % mem->touch.entries.size();
|
||||||
|
|
||||||
|
// Get the current touch entry
|
||||||
|
TouchDataEntry& touch_entry = mem->touch.entries[mem->touch.index];
|
||||||
|
bool pressed = false;
|
||||||
|
float x, y;
|
||||||
|
std::tie(x, y, pressed) = touch_device->GetStatus();
|
||||||
|
if (!pressed && touch_btn_device) {
|
||||||
|
std::tie(x, y, pressed) = touch_btn_device->GetStatus();
|
||||||
|
}
|
||||||
|
touch_entry.x = static_cast<u16>(x * Core::kScreenBottomWidth);
|
||||||
|
touch_entry.y = static_cast<u16>(y * Core::kScreenBottomHeight);
|
||||||
|
touch_entry.valid.Assign(pressed ? 1 : 0);
|
||||||
|
|
||||||
|
system.Movie().HandleTouchStatus(touch_entry);
|
||||||
}
|
}
|
||||||
|
|
||||||
mem->touch.index = next_touch_index;
|
|
||||||
next_touch_index = (next_touch_index + 1) % mem->touch.entries.size();
|
|
||||||
|
|
||||||
// Get the current touch entry
|
|
||||||
TouchDataEntry& touch_entry = mem->touch.entries[mem->touch.index];
|
|
||||||
bool pressed = false;
|
|
||||||
float x, y;
|
|
||||||
std::tie(x, y, pressed) = touch_device->GetStatus();
|
|
||||||
if (!pressed && touch_btn_device) {
|
|
||||||
std::tie(x, y, pressed) = touch_btn_device->GetStatus();
|
|
||||||
}
|
|
||||||
touch_entry.x = static_cast<u16>(x * Core::kScreenBottomWidth);
|
|
||||||
touch_entry.y = static_cast<u16>(y * Core::kScreenBottomHeight);
|
|
||||||
touch_entry.valid.Assign(pressed ? 1 : 0);
|
|
||||||
|
|
||||||
system.Movie().HandleTouchStatus(touch_entry);
|
|
||||||
|
|
||||||
// TODO(bunnei): We're not doing anything with offset 0xA8 + 0x18 of HID SharedMemory, which
|
// TODO(bunnei): We're not doing anything with offset 0xA8 + 0x18 of HID SharedMemory, which
|
||||||
// supposedly is "Touch-screen entry, which contains the raw coordinate data prior to being
|
// supposedly is "Touch-screen entry, which contains the raw coordinate data prior to being
|
||||||
// converted to pixel coordinates." (http://3dbrew.org/wiki/HID_Shared_Memory#Offset_0xA8).
|
// converted to pixel coordinates." (http://3dbrew.org/wiki/HID_Shared_Memory#Offset_0xA8).
|
||||||
@ -231,19 +314,27 @@ void Module::UpdateAccelerometerCallback(std::uintptr_t user_data, s64 cycles_la
|
|||||||
mem->accelerometer.index = next_accelerometer_index;
|
mem->accelerometer.index = next_accelerometer_index;
|
||||||
next_accelerometer_index = (next_accelerometer_index + 1) % mem->accelerometer.entries.size();
|
next_accelerometer_index = (next_accelerometer_index + 1) % mem->accelerometer.entries.size();
|
||||||
|
|
||||||
Common::Vec3<float> accel;
|
|
||||||
std::tie(accel, std::ignore) = motion_device->GetStatus();
|
|
||||||
accel *= accelerometer_coef;
|
|
||||||
// TODO(wwylele): do a time stretch like the one in UpdateGyroscopeCallback
|
|
||||||
// The time stretch formula should be like
|
|
||||||
// stretched_vector = (raw_vector - gravity) * stretch_ratio + gravity
|
|
||||||
|
|
||||||
AccelerometerDataEntry& accelerometer_entry =
|
AccelerometerDataEntry& accelerometer_entry =
|
||||||
mem->accelerometer.entries[mem->accelerometer.index];
|
mem->accelerometer.entries[mem->accelerometer.index];
|
||||||
|
|
||||||
accelerometer_entry.x = static_cast<s16>(accel.x);
|
if (artic_controller.get() && artic_controller->IsReady()) {
|
||||||
accelerometer_entry.y = static_cast<s16>(accel.y);
|
ArticBaseController::ControllerData data = artic_controller->GetControllerData();
|
||||||
accelerometer_entry.z = static_cast<s16>(accel.z);
|
|
||||||
|
accelerometer_entry.x = data.accel_x;
|
||||||
|
accelerometer_entry.y = data.accel_y;
|
||||||
|
accelerometer_entry.z = data.accel_z;
|
||||||
|
} else {
|
||||||
|
Common::Vec3<float> accel;
|
||||||
|
std::tie(accel, std::ignore) = motion_device->GetStatus();
|
||||||
|
accel *= accelerometer_coef;
|
||||||
|
// TODO(wwylele): do a time stretch like the one in UpdateGyroscopeCallback
|
||||||
|
// The time stretch formula should be like
|
||||||
|
// stretched_vector = (raw_vector - gravity) * stretch_ratio + gravity
|
||||||
|
|
||||||
|
accelerometer_entry.x = static_cast<s16>(accel.x);
|
||||||
|
accelerometer_entry.y = static_cast<s16>(accel.y);
|
||||||
|
accelerometer_entry.z = static_cast<s16>(accel.z);
|
||||||
|
}
|
||||||
|
|
||||||
system.Movie().HandleAccelerometerStatus(accelerometer_entry);
|
system.Movie().HandleAccelerometerStatus(accelerometer_entry);
|
||||||
|
|
||||||
@ -278,13 +369,21 @@ void Module::UpdateGyroscopeCallback(std::uintptr_t user_data, s64 cycles_late)
|
|||||||
|
|
||||||
GyroscopeDataEntry& gyroscope_entry = mem->gyroscope.entries[mem->gyroscope.index];
|
GyroscopeDataEntry& gyroscope_entry = mem->gyroscope.entries[mem->gyroscope.index];
|
||||||
|
|
||||||
Common::Vec3<float> gyro;
|
if (artic_controller.get() && artic_controller->IsReady()) {
|
||||||
std::tie(std::ignore, gyro) = motion_device->GetStatus();
|
ArticBaseController::ControllerData data = artic_controller->GetControllerData();
|
||||||
double stretch = system.perf_stats->GetLastFrameTimeScale();
|
|
||||||
gyro *= gyroscope_coef * static_cast<float>(stretch);
|
gyroscope_entry.x = data.gyro_x;
|
||||||
gyroscope_entry.x = static_cast<s16>(gyro.x);
|
gyroscope_entry.y = data.gyro_y;
|
||||||
gyroscope_entry.y = static_cast<s16>(gyro.y);
|
gyroscope_entry.z = data.gyro_z;
|
||||||
gyroscope_entry.z = static_cast<s16>(gyro.z);
|
} else {
|
||||||
|
Common::Vec3<float> gyro;
|
||||||
|
std::tie(std::ignore, gyro) = motion_device->GetStatus();
|
||||||
|
double stretch = system.perf_stats->GetLastFrameTimeScale();
|
||||||
|
gyro *= gyroscope_coef * static_cast<float>(stretch);
|
||||||
|
gyroscope_entry.x = static_cast<s16>(gyro.x);
|
||||||
|
gyroscope_entry.y = static_cast<s16>(gyro.y);
|
||||||
|
gyroscope_entry.z = static_cast<s16>(gyro.z);
|
||||||
|
}
|
||||||
|
|
||||||
system.Movie().HandleGyroscopeStatus(gyroscope_entry);
|
system.Movie().HandleGyroscopeStatus(gyroscope_entry);
|
||||||
|
|
||||||
@ -316,6 +415,23 @@ void Module::Interface::GetIPCHandles(Kernel::HLERequestContext& ctx) {
|
|||||||
void Module::Interface::EnableAccelerometer(Kernel::HLERequestContext& ctx) {
|
void Module::Interface::EnableAccelerometer(Kernel::HLERequestContext& ctx) {
|
||||||
IPC::RequestParser rp(ctx);
|
IPC::RequestParser rp(ctx);
|
||||||
|
|
||||||
|
IPC::RequestBuilder rb = rp.MakeBuilder(1, 0);
|
||||||
|
|
||||||
|
auto& artic_client = GetModule()->artic_client;
|
||||||
|
if (artic_client.get()) {
|
||||||
|
auto req = artic_client->NewRequest("HIDUSER_EnableAccelerometer");
|
||||||
|
|
||||||
|
auto resp = artic_client->Send(req);
|
||||||
|
|
||||||
|
if (!resp.has_value()) {
|
||||||
|
rb.Push(ResultUnknown);
|
||||||
|
} else {
|
||||||
|
rb.Push(Result{static_cast<u32>(resp->GetMethodResult())});
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
rb.Push(ResultSuccess);
|
||||||
|
}
|
||||||
|
|
||||||
++hid->enable_accelerometer_count;
|
++hid->enable_accelerometer_count;
|
||||||
|
|
||||||
// Schedules the accelerometer update event if the accelerometer was just enabled
|
// Schedules the accelerometer update event if the accelerometer was just enabled
|
||||||
@ -324,15 +440,29 @@ void Module::Interface::EnableAccelerometer(Kernel::HLERequestContext& ctx) {
|
|||||||
hid->accelerometer_update_event);
|
hid->accelerometer_update_event);
|
||||||
}
|
}
|
||||||
|
|
||||||
IPC::RequestBuilder rb = rp.MakeBuilder(1, 0);
|
|
||||||
rb.Push(ResultSuccess);
|
|
||||||
|
|
||||||
LOG_DEBUG(Service_HID, "called");
|
LOG_DEBUG(Service_HID, "called");
|
||||||
}
|
}
|
||||||
|
|
||||||
void Module::Interface::DisableAccelerometer(Kernel::HLERequestContext& ctx) {
|
void Module::Interface::DisableAccelerometer(Kernel::HLERequestContext& ctx) {
|
||||||
IPC::RequestParser rp(ctx);
|
IPC::RequestParser rp(ctx);
|
||||||
|
|
||||||
|
IPC::RequestBuilder rb = rp.MakeBuilder(1, 0);
|
||||||
|
|
||||||
|
auto& artic_client = GetModule()->artic_client;
|
||||||
|
if (artic_client.get()) {
|
||||||
|
auto req = artic_client->NewRequest("HIDUSER_DisableAccelerometer");
|
||||||
|
|
||||||
|
auto resp = artic_client->Send(req);
|
||||||
|
|
||||||
|
if (!resp.has_value()) {
|
||||||
|
rb.Push(ResultUnknown);
|
||||||
|
} else {
|
||||||
|
rb.Push(Result{static_cast<u32>(resp->GetMethodResult())});
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
rb.Push(ResultSuccess);
|
||||||
|
}
|
||||||
|
|
||||||
--hid->enable_accelerometer_count;
|
--hid->enable_accelerometer_count;
|
||||||
|
|
||||||
// Unschedules the accelerometer update event if the accelerometer was just disabled
|
// Unschedules the accelerometer update event if the accelerometer was just disabled
|
||||||
@ -340,15 +470,29 @@ void Module::Interface::DisableAccelerometer(Kernel::HLERequestContext& ctx) {
|
|||||||
hid->system.CoreTiming().UnscheduleEvent(hid->accelerometer_update_event, 0);
|
hid->system.CoreTiming().UnscheduleEvent(hid->accelerometer_update_event, 0);
|
||||||
}
|
}
|
||||||
|
|
||||||
IPC::RequestBuilder rb = rp.MakeBuilder(1, 0);
|
|
||||||
rb.Push(ResultSuccess);
|
|
||||||
|
|
||||||
LOG_DEBUG(Service_HID, "called");
|
LOG_DEBUG(Service_HID, "called");
|
||||||
}
|
}
|
||||||
|
|
||||||
void Module::Interface::EnableGyroscopeLow(Kernel::HLERequestContext& ctx) {
|
void Module::Interface::EnableGyroscopeLow(Kernel::HLERequestContext& ctx) {
|
||||||
IPC::RequestParser rp(ctx);
|
IPC::RequestParser rp(ctx);
|
||||||
|
|
||||||
|
IPC::RequestBuilder rb = rp.MakeBuilder(1, 0);
|
||||||
|
|
||||||
|
auto& artic_client = GetModule()->artic_client;
|
||||||
|
if (artic_client.get()) {
|
||||||
|
auto req = artic_client->NewRequest("HIDUSER_EnableGyroscope");
|
||||||
|
|
||||||
|
auto resp = artic_client->Send(req);
|
||||||
|
|
||||||
|
if (!resp.has_value()) {
|
||||||
|
rb.Push(ResultUnknown);
|
||||||
|
} else {
|
||||||
|
rb.Push(Result{static_cast<u32>(resp->GetMethodResult())});
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
rb.Push(ResultSuccess);
|
||||||
|
}
|
||||||
|
|
||||||
++hid->enable_gyroscope_count;
|
++hid->enable_gyroscope_count;
|
||||||
|
|
||||||
// Schedules the gyroscope update event if the gyroscope was just enabled
|
// Schedules the gyroscope update event if the gyroscope was just enabled
|
||||||
@ -356,15 +500,29 @@ void Module::Interface::EnableGyroscopeLow(Kernel::HLERequestContext& ctx) {
|
|||||||
hid->system.CoreTiming().ScheduleEvent(gyroscope_update_ticks, hid->gyroscope_update_event);
|
hid->system.CoreTiming().ScheduleEvent(gyroscope_update_ticks, hid->gyroscope_update_event);
|
||||||
}
|
}
|
||||||
|
|
||||||
IPC::RequestBuilder rb = rp.MakeBuilder(1, 0);
|
|
||||||
rb.Push(ResultSuccess);
|
|
||||||
|
|
||||||
LOG_DEBUG(Service_HID, "called");
|
LOG_DEBUG(Service_HID, "called");
|
||||||
}
|
}
|
||||||
|
|
||||||
void Module::Interface::DisableGyroscopeLow(Kernel::HLERequestContext& ctx) {
|
void Module::Interface::DisableGyroscopeLow(Kernel::HLERequestContext& ctx) {
|
||||||
IPC::RequestParser rp(ctx);
|
IPC::RequestParser rp(ctx);
|
||||||
|
|
||||||
|
IPC::RequestBuilder rb = rp.MakeBuilder(1, 0);
|
||||||
|
|
||||||
|
auto& artic_client = GetModule()->artic_client;
|
||||||
|
if (artic_client.get()) {
|
||||||
|
auto req = artic_client->NewRequest("HIDUSER_DisableGyroscope");
|
||||||
|
|
||||||
|
auto resp = artic_client->Send(req);
|
||||||
|
|
||||||
|
if (!resp.has_value()) {
|
||||||
|
rb.Push(ResultUnknown);
|
||||||
|
} else {
|
||||||
|
rb.Push(Result{static_cast<u32>(resp->GetMethodResult())});
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
rb.Push(ResultSuccess);
|
||||||
|
}
|
||||||
|
|
||||||
--hid->enable_gyroscope_count;
|
--hid->enable_gyroscope_count;
|
||||||
|
|
||||||
// Unschedules the gyroscope update event if the gyroscope was just disabled
|
// Unschedules the gyroscope update event if the gyroscope was just disabled
|
||||||
@ -372,9 +530,6 @@ void Module::Interface::DisableGyroscopeLow(Kernel::HLERequestContext& ctx) {
|
|||||||
hid->system.CoreTiming().UnscheduleEvent(hid->gyroscope_update_event, 0);
|
hid->system.CoreTiming().UnscheduleEvent(hid->gyroscope_update_event, 0);
|
||||||
}
|
}
|
||||||
|
|
||||||
IPC::RequestBuilder rb = rp.MakeBuilder(1, 0);
|
|
||||||
rb.Push(ResultSuccess);
|
|
||||||
|
|
||||||
LOG_DEBUG(Service_HID, "called");
|
LOG_DEBUG(Service_HID, "called");
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -382,25 +537,90 @@ void Module::Interface::GetGyroscopeLowRawToDpsCoefficient(Kernel::HLERequestCon
|
|||||||
IPC::RequestParser rp(ctx);
|
IPC::RequestParser rp(ctx);
|
||||||
|
|
||||||
IPC::RequestBuilder rb = rp.MakeBuilder(2, 0);
|
IPC::RequestBuilder rb = rp.MakeBuilder(2, 0);
|
||||||
rb.Push(ResultSuccess);
|
|
||||||
rb.Push(gyroscope_coef);
|
auto& artic_client = GetModule()->artic_client;
|
||||||
|
if (artic_client.get()) {
|
||||||
|
auto req = artic_client->NewRequest("HIDUSER_GetGyroRawToDpsCoef");
|
||||||
|
|
||||||
|
auto resp = artic_client->Send(req);
|
||||||
|
|
||||||
|
if (!resp.has_value()) {
|
||||||
|
rb.Push(ResultUnknown);
|
||||||
|
rb.Push(0.f);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
Result res = Result{static_cast<u32>(resp->GetMethodResult())};
|
||||||
|
if (res.IsError()) {
|
||||||
|
rb.Push(res);
|
||||||
|
rb.Push(0.f);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
auto coef = resp->GetResponseFloat(0);
|
||||||
|
if (!coef.has_value()) {
|
||||||
|
rb.Push(ResultUnknown);
|
||||||
|
rb.Push(0.f);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
rb.Push(res);
|
||||||
|
rb.Push(*coef);
|
||||||
|
} else {
|
||||||
|
rb.Push(ResultSuccess);
|
||||||
|
rb.Push(gyroscope_coef);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void Module::Interface::GetGyroscopeLowCalibrateParam(Kernel::HLERequestContext& ctx) {
|
void Module::Interface::GetGyroscopeLowCalibrateParam(Kernel::HLERequestContext& ctx) {
|
||||||
IPC::RequestParser rp(ctx);
|
IPC::RequestParser rp(ctx);
|
||||||
|
|
||||||
IPC::RequestBuilder rb = rp.MakeBuilder(6, 0);
|
IPC::RequestBuilder rb = rp.MakeBuilder(6, 0);
|
||||||
rb.Push(ResultSuccess);
|
|
||||||
|
|
||||||
const s16 param_unit = 6700; // an approximate value taken from hw
|
auto& artic_client = GetModule()->artic_client;
|
||||||
GyroscopeCalibrateParam param = {
|
if (artic_client.get()) {
|
||||||
{0, param_unit, -param_unit},
|
GyroscopeCalibrateParam param;
|
||||||
{0, param_unit, -param_unit},
|
|
||||||
{0, param_unit, -param_unit},
|
|
||||||
};
|
|
||||||
rb.PushRaw(param);
|
|
||||||
|
|
||||||
LOG_WARNING(Service_HID, "(STUBBED) called");
|
auto req = artic_client->NewRequest("HIDUSER_GetGyroCalibrateParam");
|
||||||
|
|
||||||
|
auto resp = artic_client->Send(req);
|
||||||
|
|
||||||
|
if (!resp.has_value()) {
|
||||||
|
rb.Push(ResultUnknown);
|
||||||
|
rb.PushRaw(param);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
Result res = Result{static_cast<u32>(resp->GetMethodResult())};
|
||||||
|
if (res.IsError()) {
|
||||||
|
rb.Push(res);
|
||||||
|
rb.PushRaw(param);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
auto param_buf = resp->GetResponseBuffer(0);
|
||||||
|
if (!param_buf.has_value() || param_buf->second != sizeof(param)) {
|
||||||
|
rb.Push(ResultUnknown);
|
||||||
|
rb.PushRaw(param);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
memcpy(¶m, param_buf->first, sizeof(param));
|
||||||
|
|
||||||
|
rb.Push(res);
|
||||||
|
rb.PushRaw(param);
|
||||||
|
} else {
|
||||||
|
rb.Push(ResultSuccess);
|
||||||
|
|
||||||
|
const s16 param_unit = 6700; // an approximate value taken from hw
|
||||||
|
GyroscopeCalibrateParam param = {
|
||||||
|
{0, param_unit, -param_unit},
|
||||||
|
{0, param_unit, -param_unit},
|
||||||
|
{0, param_unit, -param_unit},
|
||||||
|
};
|
||||||
|
rb.PushRaw(param);
|
||||||
|
|
||||||
|
LOG_WARNING(Service_HID, "(STUBBED) called");
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void Module::Interface::GetSoundVolume(Kernel::HLERequestContext& ctx) {
|
void Module::Interface::GetSoundVolume(Kernel::HLERequestContext& ctx) {
|
||||||
@ -454,6 +674,24 @@ Module::Module(Core::System& system) : system(system) {
|
|||||||
timing.ScheduleEvent(pad_update_ticks, pad_update_event);
|
timing.ScheduleEvent(pad_update_ticks, pad_update_event);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void Module::UseArticClient(const std::shared_ptr<Network::ArticBase::Client>& client) {
|
||||||
|
artic_client = client;
|
||||||
|
artic_controller = std::make_shared<ArticBaseController>(client);
|
||||||
|
if (!artic_controller->IsCreated()) {
|
||||||
|
artic_controller.reset();
|
||||||
|
} else {
|
||||||
|
auto ir_user = system.ServiceManager().GetService<Service::IR::IR_USER>("ir:USER");
|
||||||
|
if (ir_user.get()) {
|
||||||
|
ir_user->UseArticController(artic_controller);
|
||||||
|
}
|
||||||
|
|
||||||
|
auto ir_rst = system.ServiceManager().GetService<Service::IR::IR_RST>("ir:rst");
|
||||||
|
if (ir_rst.get()) {
|
||||||
|
ir_rst->UseArticController(artic_controller);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
void Module::ReloadInputDevices() {
|
void Module::ReloadInputDevices() {
|
||||||
is_device_reload_pending.store(true);
|
is_device_reload_pending.store(true);
|
||||||
}
|
}
|
||||||
|
@ -14,13 +14,11 @@
|
|||||||
#include "common/common_funcs.h"
|
#include "common/common_funcs.h"
|
||||||
#include "common/common_types.h"
|
#include "common/common_types.h"
|
||||||
#include "common/settings.h"
|
#include "common/settings.h"
|
||||||
|
#include "core/core.h"
|
||||||
#include "core/core_timing.h"
|
#include "core/core_timing.h"
|
||||||
#include "core/frontend/input.h"
|
#include "core/frontend/input.h"
|
||||||
#include "core/hle/service/service.h"
|
#include "core/hle/service/service.h"
|
||||||
|
#include "network/artic_base/artic_base_client.h"
|
||||||
namespace Core {
|
|
||||||
class System;
|
|
||||||
}
|
|
||||||
|
|
||||||
namespace Kernel {
|
namespace Kernel {
|
||||||
class Event;
|
class Event;
|
||||||
@ -199,6 +197,44 @@ struct DirectionState {
|
|||||||
/// Translates analog stick axes to directions. This is exposed for ir_rst module to use.
|
/// Translates analog stick axes to directions. This is exposed for ir_rst module to use.
|
||||||
DirectionState GetStickDirectionState(s16 circle_pad_x, s16 circle_pad_y);
|
DirectionState GetStickDirectionState(s16 circle_pad_x, s16 circle_pad_y);
|
||||||
|
|
||||||
|
class ArticBaseController {
|
||||||
|
public:
|
||||||
|
struct ControllerData {
|
||||||
|
u32 index{};
|
||||||
|
u32 pad{};
|
||||||
|
s16 c_pad_x{};
|
||||||
|
s16 c_pad_y{};
|
||||||
|
u16 touch_x{};
|
||||||
|
u16 touch_y{};
|
||||||
|
s16 c_stick_x{};
|
||||||
|
s16 c_stick_y{};
|
||||||
|
s16 accel_x{};
|
||||||
|
s16 accel_y{};
|
||||||
|
s16 accel_z{};
|
||||||
|
s16 gyro_x{};
|
||||||
|
s16 gyro_y{};
|
||||||
|
s16 gyro_z{};
|
||||||
|
};
|
||||||
|
static_assert(sizeof(ControllerData) == 0x20, "Incorrect ControllerData size");
|
||||||
|
|
||||||
|
ArticBaseController(const std::shared_ptr<Network::ArticBase::Client>& client);
|
||||||
|
|
||||||
|
bool IsCreated() {
|
||||||
|
return udp_stream.get();
|
||||||
|
}
|
||||||
|
|
||||||
|
bool IsReady() {
|
||||||
|
return udp_stream.get() ? udp_stream->IsReady() : false;
|
||||||
|
}
|
||||||
|
|
||||||
|
ControllerData GetControllerData();
|
||||||
|
|
||||||
|
private:
|
||||||
|
std::shared_ptr<Network::ArticBase::Client::UDPStream> udp_stream;
|
||||||
|
u32 last_packet_id{};
|
||||||
|
ControllerData last_controller_data{};
|
||||||
|
};
|
||||||
|
|
||||||
class Module final {
|
class Module final {
|
||||||
public:
|
public:
|
||||||
explicit Module(Core::System& system);
|
explicit Module(Core::System& system);
|
||||||
@ -296,6 +332,8 @@ public:
|
|||||||
std::shared_ptr<Module> hid;
|
std::shared_ptr<Module> hid;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
void UseArticClient(const std::shared_ptr<Network::ArticBase::Client>& client);
|
||||||
|
|
||||||
void ReloadInputDevices();
|
void ReloadInputDevices();
|
||||||
|
|
||||||
const PadState& GetState() const;
|
const PadState& GetState() const;
|
||||||
@ -355,6 +393,9 @@ private:
|
|||||||
std::unique_ptr<Input::TouchDevice> touch_device;
|
std::unique_ptr<Input::TouchDevice> touch_device;
|
||||||
std::unique_ptr<Input::TouchDevice> touch_btn_device;
|
std::unique_ptr<Input::TouchDevice> touch_btn_device;
|
||||||
|
|
||||||
|
std::shared_ptr<ArticBaseController> artic_controller;
|
||||||
|
std::shared_ptr<Network::ArticBase::Client> artic_client;
|
||||||
|
|
||||||
template <class Archive>
|
template <class Archive>
|
||||||
void serialize(Archive& ar, const unsigned int);
|
void serialize(Archive& ar, const unsigned int);
|
||||||
friend class boost::serialization::access;
|
friend class boost::serialization::access;
|
||||||
|
@ -381,10 +381,10 @@ void Context::MakeRequestNonSSL(httplib::Request& request, const URLInfo& url_in
|
|||||||
|
|
||||||
if (!client->send(request, response, error)) {
|
if (!client->send(request, response, error)) {
|
||||||
LOG_ERROR(Service_HTTP, "Request failed: {}: {}", error, httplib::to_string(error));
|
LOG_ERROR(Service_HTTP, "Request failed: {}: {}", error, httplib::to_string(error));
|
||||||
state = RequestState::TimedOut;
|
state = RequestState::Completed;
|
||||||
} else {
|
} else {
|
||||||
LOG_DEBUG(Service_HTTP, "Request successful");
|
LOG_DEBUG(Service_HTTP, "Request successful");
|
||||||
state = RequestState::ReadyToDownloadContent;
|
state = RequestState::ReceivingBody;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -439,10 +439,10 @@ void Context::MakeRequestSSL(httplib::Request& request, const URLInfo& url_info,
|
|||||||
|
|
||||||
if (!client->send(request, response, error)) {
|
if (!client->send(request, response, error)) {
|
||||||
LOG_ERROR(Service_HTTP, "Request failed: {}: {}", error, httplib::to_string(error));
|
LOG_ERROR(Service_HTTP, "Request failed: {}: {}", error, httplib::to_string(error));
|
||||||
state = RequestState::TimedOut;
|
state = RequestState::Completed;
|
||||||
} else {
|
} else {
|
||||||
LOG_DEBUG(Service_HTTP, "Request successful");
|
LOG_DEBUG(Service_HTTP, "Request successful");
|
||||||
state = RequestState::ReadyToDownloadContent;
|
state = RequestState::ReceivingBody;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -696,6 +696,7 @@ void HTTP_C::ReceiveDataImpl(Kernel::HLERequestContext& ctx, bool timeout) {
|
|||||||
http_context.current_copied_data,
|
http_context.current_copied_data,
|
||||||
0, remaining_data);
|
0, remaining_data);
|
||||||
http_context.current_copied_data += remaining_data;
|
http_context.current_copied_data += remaining_data;
|
||||||
|
http_context.state = RequestState::Completed;
|
||||||
rb.Push(ResultSuccess);
|
rb.Push(ResultSuccess);
|
||||||
} else {
|
} else {
|
||||||
async_data->buffer->Write(http_context.response.body.data() +
|
async_data->buffer->Write(http_context.response.body.data() +
|
||||||
|
@ -48,12 +48,29 @@ enum class RequestMethod : u8 {
|
|||||||
constexpr u32 TotalRequestMethods = 8;
|
constexpr u32 TotalRequestMethods = 8;
|
||||||
|
|
||||||
enum class RequestState : u8 {
|
enum class RequestState : u8 {
|
||||||
NotStarted = 0x1, // Request has not started yet.
|
/// Request has not started yet.
|
||||||
ConnectingToServer = 0x5, // Request in progress, connecting to server.
|
NotStarted = 0x1,
|
||||||
SendingRequest = 0x6, // Request in progress, sending HTTP request.
|
|
||||||
ReceivingResponse = 0x7, // Request in progress, receiving HTTP response.
|
/// Request in progress, connecting to server.
|
||||||
ReadyToDownloadContent = 0x8, // Ready to download the content.
|
ConnectingToServer = 0x5,
|
||||||
TimedOut = 0xA, // Request timed out?
|
|
||||||
|
/// Request in progress, sending HTTP request.
|
||||||
|
SendingRequest = 0x6,
|
||||||
|
|
||||||
|
// Request in progress, receiving HTTP response and headers.
|
||||||
|
ReceivingResponse = 0x7,
|
||||||
|
|
||||||
|
/// Request in progress, receiving HTTP body. The HTTP module may
|
||||||
|
/// get stuck in this state if the internal receive buffer gets full.
|
||||||
|
/// Once the user calls ReceiveData it will get unstuck.
|
||||||
|
ReceivingBody = 0x8,
|
||||||
|
|
||||||
|
/// Request is finished and all data has been received. HTTP transitions
|
||||||
|
/// to the Completed state shortly afterwards after some cleanup.
|
||||||
|
Received = 0x9,
|
||||||
|
|
||||||
|
/// Request is completed.
|
||||||
|
Completed = 0xA,
|
||||||
};
|
};
|
||||||
|
|
||||||
enum class PostDataEncoding : u8 {
|
enum class PostDataEncoding : u8 {
|
||||||
|
@ -2,10 +2,11 @@
|
|||||||
// Licensed under GPLv2 or any later version
|
// Licensed under GPLv2 or any later version
|
||||||
// Refer to the license.txt file included.
|
// Refer to the license.txt file included.
|
||||||
|
|
||||||
#include <fmt/format.h>
|
#include <fmt/ranges.h>
|
||||||
#include "common/alignment.h"
|
#include "common/alignment.h"
|
||||||
#include "common/settings.h"
|
#include "common/settings.h"
|
||||||
#include "core/core_timing.h"
|
#include "core/core_timing.h"
|
||||||
|
#include "core/hle/service/hid/hid.h"
|
||||||
#include "core/hle/service/ir/extra_hid.h"
|
#include "core/hle/service/ir/extra_hid.h"
|
||||||
#include "core/movie.h"
|
#include "core/movie.h"
|
||||||
|
|
||||||
@ -230,23 +231,47 @@ void ExtraHID::SendHIDStatus() {
|
|||||||
if (is_device_reload_pending.exchange(false))
|
if (is_device_reload_pending.exchange(false))
|
||||||
LoadInputDevices();
|
LoadInputDevices();
|
||||||
|
|
||||||
|
constexpr u32 ZL_BUTTON = (1 << 14);
|
||||||
|
constexpr u32 ZR_BUTTON = (1 << 15);
|
||||||
|
|
||||||
constexpr int C_STICK_CENTER = 0x800;
|
constexpr int C_STICK_CENTER = 0x800;
|
||||||
// TODO(wwylele): this value is not accurately measured. We currently assume that the axis can
|
// TODO(wwylele): this value is not accurately measured. We currently assume that the axis can
|
||||||
// take values in the whole range of a 12-bit integer.
|
// take values in the whole range of a 12-bit integer.
|
||||||
constexpr int C_STICK_RADIUS = 0x7FF;
|
constexpr int C_STICK_RADIUS = 0x7FF;
|
||||||
|
|
||||||
float x, y;
|
|
||||||
std::tie(x, y) = c_stick->GetStatus();
|
|
||||||
|
|
||||||
ExtraHIDResponse response{};
|
ExtraHIDResponse response{};
|
||||||
response.c_stick.header.Assign(static_cast<u8>(ResponseID::PollHID));
|
|
||||||
response.c_stick.c_stick_x.Assign(static_cast<u32>(C_STICK_CENTER + C_STICK_RADIUS * x));
|
if (artic_controller.get() && artic_controller->IsReady()) {
|
||||||
response.c_stick.c_stick_y.Assign(static_cast<u32>(C_STICK_CENTER + C_STICK_RADIUS * y));
|
Service::HID::ArticBaseController::ControllerData data =
|
||||||
response.buttons.battery_level.Assign(0x1F);
|
artic_controller->GetControllerData();
|
||||||
response.buttons.zl_not_held.Assign(!zl->GetStatus());
|
|
||||||
response.buttons.zr_not_held.Assign(!zr->GetStatus());
|
constexpr int MAX_CSTICK_RADIUS = 0x9C; // Max value for a c-stick radius
|
||||||
response.buttons.r_not_held.Assign(1);
|
|
||||||
response.unknown = 0;
|
response.c_stick.header.Assign(static_cast<u8>(ResponseID::PollHID));
|
||||||
|
response.c_stick.c_stick_x.Assign(static_cast<u32>(
|
||||||
|
(static_cast<float>(data.c_stick_x) / MAX_CSTICK_RADIUS) * C_STICK_RADIUS +
|
||||||
|
C_STICK_CENTER));
|
||||||
|
response.c_stick.c_stick_y.Assign(static_cast<u32>(
|
||||||
|
(static_cast<float>(data.c_stick_y) / MAX_CSTICK_RADIUS) * C_STICK_RADIUS +
|
||||||
|
C_STICK_CENTER));
|
||||||
|
response.buttons.battery_level.Assign(0x1F);
|
||||||
|
response.buttons.zl_not_held.Assign((data.pad & ZL_BUTTON) == 0);
|
||||||
|
response.buttons.zr_not_held.Assign((data.pad & ZR_BUTTON) == 0);
|
||||||
|
response.buttons.r_not_held.Assign(1);
|
||||||
|
response.unknown = 0;
|
||||||
|
} else {
|
||||||
|
float x, y;
|
||||||
|
std::tie(x, y) = c_stick->GetStatus();
|
||||||
|
|
||||||
|
response.c_stick.header.Assign(static_cast<u8>(ResponseID::PollHID));
|
||||||
|
response.c_stick.c_stick_x.Assign(static_cast<u32>(C_STICK_CENTER + C_STICK_RADIUS * x));
|
||||||
|
response.c_stick.c_stick_y.Assign(static_cast<u32>(C_STICK_CENTER + C_STICK_RADIUS * y));
|
||||||
|
response.buttons.battery_level.Assign(0x1F);
|
||||||
|
response.buttons.zl_not_held.Assign(!zl->GetStatus());
|
||||||
|
response.buttons.zr_not_held.Assign(!zr->GetStatus());
|
||||||
|
response.buttons.r_not_held.Assign(1);
|
||||||
|
response.unknown = 0;
|
||||||
|
}
|
||||||
|
|
||||||
movie.HandleExtraHidResponse(response);
|
movie.HandleExtraHidResponse(response);
|
||||||
|
|
||||||
|
@ -19,6 +19,10 @@ class Timing;
|
|||||||
class Movie;
|
class Movie;
|
||||||
} // namespace Core
|
} // namespace Core
|
||||||
|
|
||||||
|
namespace Service::HID {
|
||||||
|
class ArticBaseController;
|
||||||
|
};
|
||||||
|
|
||||||
namespace Service::IR {
|
namespace Service::IR {
|
||||||
|
|
||||||
struct ExtraHIDResponse {
|
struct ExtraHIDResponse {
|
||||||
@ -54,6 +58,10 @@ public:
|
|||||||
/// Requests input devices reload from current settings. Called when the input settings change.
|
/// Requests input devices reload from current settings. Called when the input settings change.
|
||||||
void RequestInputDevicesReload();
|
void RequestInputDevicesReload();
|
||||||
|
|
||||||
|
void UseArticController(const std::shared_ptr<Service::HID::ArticBaseController>& ac) {
|
||||||
|
artic_controller = ac;
|
||||||
|
}
|
||||||
|
|
||||||
private:
|
private:
|
||||||
void SendHIDStatus();
|
void SendHIDStatus();
|
||||||
void HandleConfigureHIDPollingRequest(std::span<const u8> request);
|
void HandleConfigureHIDPollingRequest(std::span<const u8> request);
|
||||||
@ -70,6 +78,8 @@ private:
|
|||||||
std::unique_ptr<Input::AnalogDevice> c_stick;
|
std::unique_ptr<Input::AnalogDevice> c_stick;
|
||||||
std::atomic<bool> is_device_reload_pending;
|
std::atomic<bool> is_device_reload_pending;
|
||||||
|
|
||||||
|
std::shared_ptr<Service::HID::ArticBaseController> artic_controller = nullptr;
|
||||||
|
|
||||||
template <class Archive>
|
template <class Archive>
|
||||||
void serialize(Archive& ar, const unsigned int) {
|
void serialize(Archive& ar, const unsigned int) {
|
||||||
ar& hid_period;
|
ar& hid_period;
|
||||||
|
@ -72,25 +72,41 @@ void IR_RST::UpdateCallback(std::uintptr_t user_data, s64 cycles_late) {
|
|||||||
if (is_device_reload_pending.exchange(false))
|
if (is_device_reload_pending.exchange(false))
|
||||||
LoadInputDevices();
|
LoadInputDevices();
|
||||||
|
|
||||||
|
constexpr u32 VALID_EXTRAHID_KEYS = 0xF00C000;
|
||||||
|
|
||||||
PadState state;
|
PadState state;
|
||||||
state.zl.Assign(zl_button->GetStatus());
|
s16 c_stick_x, c_stick_y;
|
||||||
state.zr.Assign(zr_button->GetStatus());
|
|
||||||
|
|
||||||
// Get current c-stick position and update c-stick direction
|
if (artic_controller.get() && artic_controller->IsReady()) {
|
||||||
float c_stick_x_f, c_stick_y_f;
|
Service::HID::ArticBaseController::ControllerData data =
|
||||||
std::tie(c_stick_x_f, c_stick_y_f) = c_stick->GetStatus();
|
artic_controller->GetControllerData();
|
||||||
constexpr int MAX_CSTICK_RADIUS = 0x9C; // Max value for a c-stick radius
|
|
||||||
s16 c_stick_x = static_cast<s16>(c_stick_x_f * MAX_CSTICK_RADIUS);
|
|
||||||
s16 c_stick_y = static_cast<s16>(c_stick_y_f * MAX_CSTICK_RADIUS);
|
|
||||||
|
|
||||||
system.Movie().HandleIrRst(state, c_stick_x, c_stick_y);
|
state.hex = data.pad & VALID_EXTRAHID_KEYS;
|
||||||
|
|
||||||
if (!raw_c_stick) {
|
c_stick_x = data.c_stick_x;
|
||||||
const HID::DirectionState direction = HID::GetStickDirectionState(c_stick_x, c_stick_y);
|
c_stick_y = data.c_stick_y;
|
||||||
state.c_stick_up.Assign(direction.up);
|
|
||||||
state.c_stick_down.Assign(direction.down);
|
system.Movie().HandleIrRst(state, c_stick_x, c_stick_y);
|
||||||
state.c_stick_left.Assign(direction.left);
|
} else {
|
||||||
state.c_stick_right.Assign(direction.right);
|
state.zl.Assign(zl_button->GetStatus());
|
||||||
|
state.zr.Assign(zr_button->GetStatus());
|
||||||
|
|
||||||
|
// Get current c-stick position and update c-stick direction
|
||||||
|
float c_stick_x_f, c_stick_y_f;
|
||||||
|
std::tie(c_stick_x_f, c_stick_y_f) = c_stick->GetStatus();
|
||||||
|
constexpr int MAX_CSTICK_RADIUS = 0x9C; // Max value for a c-stick radius
|
||||||
|
c_stick_x = static_cast<s16>(c_stick_x_f * MAX_CSTICK_RADIUS);
|
||||||
|
c_stick_y = static_cast<s16>(c_stick_y_f * MAX_CSTICK_RADIUS);
|
||||||
|
|
||||||
|
system.Movie().HandleIrRst(state, c_stick_x, c_stick_y);
|
||||||
|
|
||||||
|
if (!raw_c_stick) {
|
||||||
|
const HID::DirectionState direction = HID::GetStickDirectionState(c_stick_x, c_stick_y);
|
||||||
|
state.c_stick_up.Assign(direction.up);
|
||||||
|
state.c_stick_down.Assign(direction.down);
|
||||||
|
state.c_stick_left.Assign(direction.left);
|
||||||
|
state.c_stick_right.Assign(direction.right);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// TODO (wwylele): implement raw C-stick data for raw_c_stick = true
|
// TODO (wwylele): implement raw C-stick data for raw_c_stick = true
|
||||||
|
@ -21,6 +21,10 @@ namespace Core {
|
|||||||
struct TimingEventType;
|
struct TimingEventType;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
namespace Service::HID {
|
||||||
|
class ArticBaseController;
|
||||||
|
};
|
||||||
|
|
||||||
namespace Service::IR {
|
namespace Service::IR {
|
||||||
|
|
||||||
union PadState {
|
union PadState {
|
||||||
@ -42,6 +46,10 @@ public:
|
|||||||
~IR_RST();
|
~IR_RST();
|
||||||
void ReloadInputDevices();
|
void ReloadInputDevices();
|
||||||
|
|
||||||
|
void UseArticController(const std::shared_ptr<Service::HID::ArticBaseController>& ac) {
|
||||||
|
artic_controller = ac;
|
||||||
|
}
|
||||||
|
|
||||||
private:
|
private:
|
||||||
/**
|
/**
|
||||||
* GetHandles service function
|
* GetHandles service function
|
||||||
@ -88,6 +96,8 @@ private:
|
|||||||
bool raw_c_stick{false};
|
bool raw_c_stick{false};
|
||||||
int update_period{0};
|
int update_period{0};
|
||||||
|
|
||||||
|
std::shared_ptr<Service::HID::ArticBaseController> artic_controller = nullptr;
|
||||||
|
|
||||||
template <class Archive>
|
template <class Archive>
|
||||||
void serialize(Archive& ar, const unsigned int);
|
void serialize(Archive& ar, const unsigned int);
|
||||||
friend class boost::serialization::access;
|
friend class boost::serialization::access;
|
||||||
|
@ -8,7 +8,7 @@
|
|||||||
#include <boost/serialization/base_object.hpp>
|
#include <boost/serialization/base_object.hpp>
|
||||||
#include <boost/serialization/shared_ptr.hpp>
|
#include <boost/serialization/shared_ptr.hpp>
|
||||||
#include <boost/serialization/unique_ptr.hpp>
|
#include <boost/serialization/unique_ptr.hpp>
|
||||||
#include <fmt/format.h>
|
#include <fmt/ranges.h>
|
||||||
#include "common/archives.h"
|
#include "common/archives.h"
|
||||||
#include "common/swap.h"
|
#include "common/swap.h"
|
||||||
#include "core/core.h"
|
#include "core/core.h"
|
||||||
@ -480,6 +480,12 @@ void IR_USER::ReloadInputDevices() {
|
|||||||
extra_hid->RequestInputDevicesReload();
|
extra_hid->RequestInputDevicesReload();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void IR_USER::UseArticController(const std::shared_ptr<Service::HID::ArticBaseController>& ac) {
|
||||||
|
if (extra_hid.get()) {
|
||||||
|
extra_hid->UseArticController(ac);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
IRDevice::IRDevice(SendFunc send_func_) : send_func(send_func_) {}
|
IRDevice::IRDevice(SendFunc send_func_) : send_func(send_func_) {}
|
||||||
IRDevice::~IRDevice() = default;
|
IRDevice::~IRDevice() = default;
|
||||||
|
|
||||||
|
@ -14,6 +14,10 @@ class Event;
|
|||||||
class SharedMemory;
|
class SharedMemory;
|
||||||
} // namespace Kernel
|
} // namespace Kernel
|
||||||
|
|
||||||
|
namespace Service::HID {
|
||||||
|
class ArticBaseController;
|
||||||
|
};
|
||||||
|
|
||||||
namespace Service::IR {
|
namespace Service::IR {
|
||||||
|
|
||||||
class BufferManager;
|
class BufferManager;
|
||||||
@ -57,6 +61,8 @@ public:
|
|||||||
|
|
||||||
void ReloadInputDevices();
|
void ReloadInputDevices();
|
||||||
|
|
||||||
|
void UseArticController(const std::shared_ptr<Service::HID::ArticBaseController>& ac);
|
||||||
|
|
||||||
private:
|
private:
|
||||||
/**
|
/**
|
||||||
* InitializeIrNopShared service function
|
* InitializeIrNopShared service function
|
||||||
|
@ -38,7 +38,7 @@ SERVICE_CONSTRUCT_IMPL(Service::PLGLDR::PLG_LDR)
|
|||||||
|
|
||||||
namespace Service::PLGLDR {
|
namespace Service::PLGLDR {
|
||||||
|
|
||||||
static const Kernel::CoreVersion plgldr_version = Kernel::CoreVersion(1, 0, 0);
|
static const Kernel::CoreVersion plgldr_version = Kernel::CoreVersion(1, 0, 2);
|
||||||
|
|
||||||
PLG_LDR::PLG_LDR(Core::System& system_) : ServiceFramework{"plg:ldr", 1}, system(system_) {
|
PLG_LDR::PLG_LDR(Core::System& system_) : ServiceFramework{"plg:ldr", 1}, system(system_) {
|
||||||
static const FunctionInfo functions[] = {
|
static const FunctionInfo functions[] = {
|
||||||
@ -91,7 +91,11 @@ void PLG_LDR::serialize(Archive& ar, const unsigned int) {
|
|||||||
SERIALIZE_IMPL(PLG_LDR)
|
SERIALIZE_IMPL(PLG_LDR)
|
||||||
|
|
||||||
void PLG_LDR::OnProcessRun(Kernel::Process& process, Kernel::KernelSystem& kernel) {
|
void PLG_LDR::OnProcessRun(Kernel::Process& process, Kernel::KernelSystem& kernel) {
|
||||||
if (!plgldr_context.is_enabled || plgldr_context.plugin_loaded) {
|
constexpr u32 TITLE_ID_APP_MASK = 0xFFFFFFED;
|
||||||
|
constexpr u32 TITLE_ID_APP_VALUE = 0x04000000;
|
||||||
|
if (!plgldr_context.is_enabled || plgldr_context.plugin_loaded ||
|
||||||
|
(static_cast<u32>(process.codeset->program_id >> 32) & TITLE_ID_APP_MASK) !=
|
||||||
|
TITLE_ID_APP_VALUE) {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
{
|
{
|
||||||
|
Some files were not shown because too many files have changed in this diff Show More
Loading…
x
Reference in New Issue
Block a user