Replace ThreadToDo and the something_to_do condvar with four boolean
flags: exit_requested, delete_requested, suspend_requested,
single_stepping. run_loop() returns void.
call_level brackets each frame: incremented on entry, decremented just
before return.
All call-level exits (normal exit, guest return, delete) converge on a
single block at the top of the loop that fires the end callback and parks
dormant. This wakes wait_thread_end waiters on every exit path.
If deleted, return completely from all run_loop() nested levels.
Replace `exit_delete_all_threads_and_wait()` with two separate operations:
- `process_exit()` blocks until all guest threads have exited (host-only)
- `request_process_exit()` fires the registered callback and returns immediately, safe to call from guest threads.
Threads are now SDL_DetachThread'd at creation. `thread_deleted_cond` on `KernelState` is used for join semantics in `process_exit()`.
Remove `shutting_down` from sync primitives; `exit_delete()` wakes blocked threads via `update_status(run)`, which all `status_cond` predicates already check.
`process_exit_callback` carries an `optional<AppLaunchRequest>` so `LoadExec` relaunches flow through the same path as normal exits. `AppLaunchRequest`/`AppLaunchReason` extracted to `emuenv/app_launch_request.h` so kernel can include it without a circular dependency.
After this, further simplification to `ThreadStatus` will be done in https://github.com/Vita3K/Vita3K/pull/3922.
- Add V3KN account management dialog wtih create/login/logout/delete account, change avatar/panel/password/online id/server, quota refresh.
- Add show server error/success popup inside V3KN account management dialog.
- Add Cloud screen to LiveArea with cloud button for upload/download savedata on V3KN
- Add "Please wait" and "Connecting… Please wait." dialogs for network operations (upload/download, auth)
- Add overwrite confirmation dialog and "Copying" progress dialogs for cloud/local saves.
- Draw Cloud icons.
util/net_utils: Some refactor and protocol improvements.
- Add Upload file func with multipart/form-data support
- Add keep-alive support for (download/upload)file.
- Refactor get_web_response() to support POST bodies and return server-side errors
- Refactor download_file() for stability and clearer error handling
- Clean up duplicated logic and unify request handling.
Each thread was allocating its own identical 4-byte NOP+WFI block.
Since all threads point LR at the same sentinel, one allocation in KernelState is sufficient.
Note that this is a Dynarmic-specific "hack" to make it stop execution (`jit->Run()`) after the guest code returns (jumps back LR):
- Prior JIT execution, we prepare LR to point to this NOP+WFI block.
- When the guest function returns, it will jump into this NOP+WFI block and `Dynarmic::A32::Exception::WaitForInterrupt` will be called. Then we call `cpu->jit->HaltExecution()` which will make `jit->Run()` return
`CPUProtocol::get_watch_memory_addr` is never used, so we can drop it.
After that, `CPUProtocol` only has `call_svc`, whose implementation is
just 3 lines: read the NID, call `call_import`, and `clear_exclusive`.
We can inline those at the call site and get rid of `CPUProtocol`
completely.
The Debugger trampoline API (`Trampoline` struct, `TrampolineCallback`,
`add_trampoline` / `get_trampoline` / `remove_trampoline`, `TRAMPOLINE_JUMPER_SVC`
and `TRAMPOLINE_HANDLER_SVC`, plus the two SVC-dispatch branches in
`CPUProtocol::call_svc`) has never had a caller.
Only DABT (type 0) is dispatched from run_loop. PABT (1) and UNDEF (2)
are stored in exception_handlers[] but never triggered. Log a warning
so it's obvious when a plugin expects a type we don't dispatch yet.
ksceKernelAllocRemoteProcessHeap returned 0 (invalid UID on Vita) and
ksceKernelRegisterProcEventHandler returned the same hardcoded 0x40001
on every call. Use atomic counters to return distinct UIDs so callers
that pass them back to the corresponding Free/Unregister don't collide.
- Trim find_import_stub segment-address dump to a one-liner (fires per NID)
- Remove module_get_offset success log (fires on every offset query)
- Remove module_get_export_func cache-hit log (fires on every export lookup)
- Promote dynamic SVC stub creation to LOG_INFO (one-time per NID, useful)
Raw new/delete across three allocation sites and one release site was
error-prone. Switched map to unique_ptr, removed the unused `next`
chain pointer, and eliminated the manual delete.
The computed MemPerm was logged but ignored — the function always called
unprotect_inner regardless of the protection flags. Now it mirrors the
kuKernelMemProtect logic: restrictive perms use add_protect so the fault
handler can catch violations; ReadWrite unprotects as before.
set_current_cpu_state was set on entry but never cleared. A recycled host
thread would carry a stale CPUState pointer into the next vita thread's
signal handler. Use a scope guard to clear it on all exit paths.
Using a single `dummy` field meant any unhandled MCR/MRC would read back
whatever the last unhandled write stored, silently corrupting guest reads.
Return CallbackOrAccessOneWord{} (no-op) instead.
- SceCpuForDriver: ksceKernelCpuIcacheInvalidateRange and
ksceKernelCpuIcacheAndL2WritebackInvalidateRange now call
invalidate_jit_cache() to properly invalidate dynarmic's JIT cache
- taiHEN: All loaded_modules accesses now protected by kernel.mutex
using scoped locks to avoid deadlocks with state->mutex and
export_nids_mutex (lock order: kernel.mutex -> export_nids_mutex -> state->mutex)
- kuKernelMemProtect: converts ku flags to MemPerm, calls protect_inner
- kuKernelMemCommit: applies requested protection via protect_inner
- kuKernelMemDecommit: marks range as MemPerm::None via protect_inner
24/24 tests passing.
Add HLE implementations for kubridge exports that cannot run as LLE
(they depend on firmware-specific offsets and ARM MMU manipulation):
- kuKernelMemProtect: validates args, returns success (Option B stub)
- kuKernelMemReserve: allocates memory via alloc_at/alloc, tracks in vm_blocks
- kuKernelMemCommit: no-op stub (warns if baseBlock mirrors requested)
- kuKernelMemDecommit: no-op stub
- kuKernelRegisterExceptionHandler: stub returns success
- kuKernelReleaseExceptionHandler: stub void return
Dynamic override mechanism:
- apply_plugin_hle_overrides() iterates all LLE export_nids and automatically
overrides any that have a matching HLE implementation (via has_hle_implementation)
- register_hle_override() creates SVC stubs and re-patches func_binding_infos
- No hardcoded NID lists — new HLE modules are picked up automatically
24/24 tests passing.
Search loaded modules by name and return the module UID.
Used by game ports (e.g. ff3_vita) to check if plugins like
kubridge are loaded before proceeding.
Implement the core taiHEN plugin framework as HLE in SceLibTaihen:
Hooks:
- taiHookFunctionExportForUser/ForKernel: inline hooks via substitute's
transform-dis for ARM/Thumb instruction relocation, with fallback to
import stub patching when inline hooking fails (FUNC_TOO_SHORT)
- taiHookFunctionImportForUser/ForKernel: import stub patching (12-byte
ARM stubs: movw/movt/bx)
- taiHookFunctionOffsetForUser/ForKernel: hook at module segment+offset
- taiHookRelease/ForKernel: restore original bytes/stubs, free trampoline
- Hook chaining with TAI_CONTINUE support via TaiHookUser structs
Injections:
- taiInjectAbs/ForKernel: arbitrary memory patching with save/restore
- taiInjectDataForUser/ForKernel: inject data at module segment+offset
- taiInjectRelease/ForKernel: restore original bytes
Module utils:
- taiGetModuleInfo/ForKernel: query module info by name
- module_get_offset: resolve segment+offset to address
- module_get_export_func: resolve NID to export address
Plugin loading:
- taiLoadKernelModule, taiLoadStartKernelModuleForUser,
taiLoadStartModuleForPidForUser: load plugin .skprx/.suprx files
- Config parsing: ux0:tai/config.txt format (*KERNEL, *TITLEID sections)
External dependency:
- Add Vita3K/substitute as git submodule (forked from comex/substitute,
LGPLv2.1+). Only the ARM transform-dis component is used for
instruction relocation in inline hooks.
Tested with 10 integration tests covering all implemented APIs.
Call load_taihen_plugins_for_title() in load_app_impl() after system
modules are loaded. This loads KERNEL plugins (once) and title-specific
plugins from ux0:tai/config.txt before the app's entry point runs.