Skip to content

feat(user-service): add a guest user a share can log in and out - #30

Open
AlxcBTW wants to merge 6 commits into
mainfrom
feat/second-user
Open

AlxcBTW wants to merge 6 commits into
mainfrom
feat/second-user

Conversation

@AlxcBTW

@AlxcBTW AlxcBTW commented Oct 27, 2026 •

Copy link
Copy Markdown
Member

What

Adds a guest user to libSceUserService, the second user a game needs to see before it lets a second player join locally. Share play's together mode (#29) will log it in when the mode starts and out when it ends.

  • UserServiceSetGuestUser_nid_postfix(userIndex, name) and UserServiceClearGuestUser_nid_postfix(userIndex) in UserService.hpp. This is the seam: nothing in this PR calls it, the share code does later.
  • The guest is the slot's existing user id (0x10000000 + index), so scePadOpen for that user already returns the handle of the pad on the same port. Pad 2 of a share is port 1, therefore user index 1. No libScePad change is needed.
  • A user is logged in while a controller on the slot or a guest claim holds it. Login and logout events, the login list and the registered list change only when that combined state changes, so a physical controller plugging in or out on the slot cannot log the guest out, and the other way round.
  • sceUserServiceGetUserName returns the display name the caller gave, cut to 16 bytes at a UTF-8 character boundary, control characters and invalid UTF-8 dropped, trimmed. With no name, or one that is empty after that, it returns the slot's default name (Player2).
  • sceUserServiceGetNpAccountId returns 0 for a guest. The host's PSN account must not be handed to another person.
  • The spec's bridge messages (share open, share mode, share pad) carry no guest handle, so the name is a parameter the share code fills when the bridge learns it. Until a name field exists, the default applies. A guest_name string on share mode would be the smallest addition; that is a network spec change, not part of this PR.

Based on main, not on #29: no API of the share branch is used. Once #29 lands, its together handling calls these two functions, and the "Share play guest pad" debt entry in libScePad (Closes when: the user service has a second user) can be closed.

Tested

Not tested on a title. New host test guest_user_service_guest_user (GuestUserServiceGuestUser.cpp): claim before and after sceUserServiceInitialize, event order and collapsing of a claim that ends before it is read, login and registered lists, user number, age level, account id 0, name sanitising (truncation at a character boundary, control characters, invalid UTF-8, empty, whitespace), claim and hotplug on the same slot in both orders, out-of-range slots ignored. The Windows and Linux build and test jobs of this PR run it with the existing user service tests. tools/check_conventions.py passes locally; the C++ tree was not built locally, only syntax-checked.

Needs a real game: whether a title's local-multiplayer join flow accepts a user with no PSN account, and what it does on the logout event while it is in a match. Recorded in docs/dev/debt/libSceUserService.md.

Checklist

  • Based on current main; no other open PR implements the same functions
  • One topic per PR; follow-ups go in a new PR
  • No comments in code except technical debt
  • Unimplemented paths throw (NotImplemented_nid_no_patch); silent stubs are listed under Silent stubs in their library's technical debt file
  • No notes, investigation .md files or images added to the repository (attach them to this PR)
  • New third-party code is a submodule built from source
  • Generic behaviour, not specific to one title
  • Depends on: none
  • Fixes: none
  • Unblocks: the together mode of feat(bridge): share play frame ring, guest pad and host override #29
  • GPUs tested: n/a
  • AI-assisted: yes

View with [code]smith Autofix with [code]smith
Need help on this PR? Tag @codesmith-bot with what you need.

A second user with a caller-given display name that appears for the length of a share and coexists with controller hotplug on the same slot. It reports no PSN account.
@AlxcBTW

AlxcBTW commented Oct 28, 2026

Copy link
Copy Markdown
Member Author

@parl0v, #30 is merged with current main and green, ready for your re-review. I have not merged it.

What changed in the merge: main merged in with a merge commit (no rebase, no force push; head a18a3b7). There were no conflicts. I also merged the fix from PR #40 into this branch, because every full build.yml run has been red since #9: bridge_e2e_game skips without a net service and check_skips.py rejects that skip. That is unrelated to the guest user.

Build: dispatch run https://github.com/anyplaynet/AnyPS5/actions/runs/40604915342 on this head: Windows, Linux and the relinker jobs (macOS arm64 and x86_64, asan) are all green.

Note for the order of merging: #29 has a TODO at the together mode switch that calls UserServiceSetGuestUser_nid_postfix(1, name) and clears it on leaving, closing and a lost connection. Whichever of #29 and #30 merges second wires it. The guest's display name is not in the bridge messages yet; the proposed follow-up is a guest_name field on share mode.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant