Skip to content

RetroAchievements: Full integration and in-game OSD dialogs for achievements and leaderboards#147

Closed
sunlollyking wants to merge 3 commits into
garbear:retroachievements-basefrom
sunlollyking:retroplayer-22alpha3-leaderboards
Closed

RetroAchievements: Full integration and in-game OSD dialogs for achievements and leaderboards#147
sunlollyking wants to merge 3 commits into
garbear:retroachievements-basefrom
sunlollyking:retroplayer-22alpha3-leaderboards

Conversation

@sunlollyking

@sunlollyking sunlollyking commented May 28, 2026

Copy link
Copy Markdown

Description

This PR delivers the complete RetroAchievements integration for RetroPlayer. It is split into two layers:1. Core RetroAchievements functionality (the engine)This PR is what actually makes RetroAchievements work in Kodi. Without it, the rcheevos library is present but dormant. This PR wires it up end-to-end:

  • Authentication — logs in to RetroAchievements using credentials stored in Kodi settings, obtains a session token and fetches game patch data on game load
  • Achievement unlock notifications — receives unlock callbacks from rcheevos and displays CGUIDialogKaiToast popup notifications with the achievement title, badge image and points
  • Mastery notification — detects when all achievements are earned and displays a mastery notification
  • Rich presence — implements the periodic session ping to RetroAchievements (r=ping) carrying the current rich presence string, keeping the user's profile page live during gameplay
  • Offline award queue — achievements earned while offline are queued and submitted when connectivity is restored
  • Background image downloads — badge images downloaded on background threads to avoid blocking the UI
  • Thread safety — all RA network operations run on background threads with proper shutdown/join on game exit; fetch threads are cancelled cleanly when dialogs close
  • 2 In-game OSD dialogs (the UI)Two new dialogs accessible from the Game OSD during gameplay:Achievements dialog (window 10833)

Full achievement list with badge icons, points, rarity percentages and unlock dates
Sorted earned-first, with rarity categories (Common / Uncommon / Rare / Ultra Rare)
Weighted point-based progress percentage
Logged-in gate with toast if unauthenticated
Leaderboards dialogs (windows 10834/10835)

Leaderboard list with top score per board fetched progressively in background
Entries dialog paginates the RA API at 10 per request (up to 100 total) — first 10 appear immediately, more load as the user scrolls
Player's own row always pinned at bottom showing rank or "Not ranked"
Avatar images, score formatting for all RA types (TIME, TIMESECS, FRAMES, SCORE, VALUE, FIXED1/2/3)

InfoLabels added

RetroPlayer.Achievements.GameTitle String Game title from RA
RetroPlayer.Achievements.Total String Total achievement count
RetroPlayer.Achievements.Unlocked String Unlocked count
RetroPlayer.Achievements.RichPresence String Current rich presence message
RetroPlayer.Achievements.Loaded Bool RA data loaded for current game
RetroPlayer.Achievements.LoggedIn Bool User authenticated with RA
RetroPlayer.Achievements.Status String "X / Y" or "N/A" summary
RetroPlayer.Leaderboards.Status String "X boards" count

Skin (Estuary)

  • GameOSD.xml — Achievements and Leaderboards buttons with live status labels; OSD height adjusted to show all items without scrolling
  • Includes_Games.xml — three new dialog includes following the DialogGameControllers.xml pattern (list controls ID 3, scrollbars ID 62); leaderboard entries use gold/silver/bronze podium for top 3, progressive row loading, pinned player row
  • DialogGameControllers.xml — visibility conditions for all three new dialogs

Motivation and context

RetroAchievements is one of the most-requested features for RetroPlayer. The rcheevos library was already integrated but the connection to Kodi's UI layer — notifications, session management, rich presence and browsing — was missing. This PR completes that connection, making RetroAchievements fully functional for the first time in Kodi.

How has this been tested?

Tested manually on WSL2 Ubuntu with Super Mario Bros (NES) using a RetroAchievements test account (itsmechrissyd):

Authentication: login flow verified with valid and invalid credentials; toast notifications fire correctly on both outcomes
Achievement unlocks: achievements triggered in-game produce popup notifications with correct title, badge and points
Rich presence: verified via RetroAchievements profile page updating during gameplay
OSD menu: all items (Pause, Save, Disc, Players, Reset, Exit, Leaderboards, Achievements, Settings) visible without scrolling
Achievements dialog: opens correctly, lists all 77 achievements for SMB with correct earned/unearned sorting, rarity and progress
Leaderboards list: all 36 boards populate progressively with top scores and correct time formatting
Leaderboard entries: first 10 entries appear immediately, subsequent pages load on scroll, player row always visible at bottom
Back navigation: all dialogs return cleanly to the previous screen
Focus warnings: resolved for windows 10833, 10834 and 10835 — no focus errors in log
Unit tests: TestGamesGUIInfo passes covering all new InfoLabel translations

Build environment: WSL2 Ubuntu 24, GCC, x86_64, software rendering (LIBGL_ALWAYS_SOFTWARE=1)

What is the effect on users?

Users with a RetroAchievements account can now:

Earn achievements while playing retro games in Kodi and receive real-time popup notifications
See their achievement progress and browse the full achievement list from the in-game menu
Browse leaderboards and see where they rank against other players worldwide
Have their RetroAchievements profile page updated with rich presence during gameplay

Users without a RetroAchievements account see no change — all dialogs gate on authentication status.

Screenshots (if appropriate):

image image image image image

Types of change

  • [X ] Improvement (non-breaking change which improves existing functionality)
  • [X ] New feature (non-breaking change which adds functionality)

Checklist:

  • My code follows the Code Guidelines of this project
  • My change requires a change to the documentation, either Doxygen or wiki
  • I have updated the documentation accordingly
  • I have read the Contributing document
  • I have added tests to cover my change
  • All new and existing tests passed

@sunlollyking
sunlollyking requested a review from garbear as a code owner May 28, 2026 08:50
@sunlollyking

Copy link
Copy Markdown
Author

Ok this is good to go - fully rebased on Beta 1 now for test builds. Lets get some feedback and see how it all runs!
Thank you!

@sunlollyking sunlollyking changed the title RetroAchievements: Full integration — authentication, unlock notifications, rich presence, and in-game OSD dialogs for achievements and leaderboards RetroAchievements: Full integration and in-game OSD dialogs for achievements and leaderboards May 28, 2026
@garbear

garbear commented May 28, 2026

Copy link
Copy Markdown
Owner

Looks like some gunk got into the PR, the top 9 commits should be rebased out:

git rebase -i fbcc9f3610379dc6cc732d1f2bb9927b87df0ff4

Then delete the top 9 lines. There might be a git conflict, and I like to use TortoiseGit on windows as it has a nice UI for resolving conflicts.

@sunlollyking
sunlollyking force-pushed the retroplayer-22alpha3-leaderboards branch from 893644b to 9bd5ecc Compare May 28, 2026 18:51
@sunlollyking

Copy link
Copy Markdown
Author

Looks like some gunk got into the PR, the top 9 commits should be rebased out:

git rebase -i fbcc9f3610379dc6cc732d1f2bb9927b87df0ff4

Then delete the top 9 lines. There might be a git conflict, and I like to use TortoiseGit on windows as it has a nice UI for resolving conflicts.

Cool think i've fixed it - crikey that was tough

@garbear

garbear commented May 28, 2026

Copy link
Copy Markdown
Owner

I tried the code, (reverted .gitignore and changes to xbmc/network), and then, logging in and showing achievements works! Good job on the UI, looks like just some dimension tweaks needed.

I don't have much time for testing, but I can certainly do test builds. It would be nice if the commit history was clean, not to the level as our upstream PR but not more than a few (or even just one) commits. It would be easier to move this feature between branches.

If you don't wanna do git-fu all day, I can ship the history you have here.

@sunlollyking

Copy link
Copy Markdown
Author

I mean I'd be happy with you squashing it all however you think Is best. I'm not going to be able to tinker on this until Sunday so keen to get a test build out there and get some feedback.

100% the cosmetic aspect needs tightening. Felt like nailing jelly to a wall getting to where it is now. Appreciate the help !

@garbear

garbear commented May 28, 2026

Copy link
Copy Markdown
Owner

OK, I'll do the squashing when I get a chance. After that I'll do builds. No ETA but I should have some free time soon.

@sunlollyking
sunlollyking force-pushed the retroplayer-22alpha3-leaderboards branch from 9bd5ecc to bc69efd Compare May 29, 2026 08:02
@sunlollyking

Copy link
Copy Markdown
Author

@garbear i had a bit of time this morning - gone ahead and just squashed them into 4 logical ones. Hopefully that frees up a bit more time for you on the build front.

@garbear

garbear commented May 29, 2026

Copy link
Copy Markdown
Owner

Hm, it looks like the squashing didn't go as planned.

Ultimately, when you have good history, each commit is mostly green, certainly no red on a green line of a previous commit (e.g. when one commit adds code, other's usually shouldn't remove it). And Kodi always builds between every commit (verify this, also motivation for less commits).

Individual commits are fine, but most reviewers will review using the "Files Changed" in GH, which just shows the diff of the full PR. So a lot of times, for really big PRs (like this one), I'll just send a single commit, as that's what a reviewer may prefer.

It looks like the PR here got messed up, so maybe we use the state I squashed it to: https://github.com/garbear/xbmc/commits/retroachievements . I also fixed a bunch of skinning issues and formatting stuff, so unless you snuck in new code missing from that, it would be best.

Note: my commit has 3k lines added, 200 removed. That's not a bad ratio (see how this PR has 900 lines removed). Above all else, PRs should aim to minimize lines removed (I call it "aim for zero red" in the diff). If you send a PR with 3k lines added, 3 lines removed, it will slide into the codebase with almost no friction. I did some git fu magic to remove about 700 red lines from the diff, as you can see in my commit.

You can see how I'm planning the PR: https://github.com/garbear/xbmc/commits/retroachievements. Just Shardul's work, then yours. This lets each author keep credit.

I could squash both commits into one for EVEN less red: https://github.com/garbear/xbmc/compare/retroachievements~2..retroachievements . The red count goes down because your second commit touched code added in the first. That means it's more work for reviewers to review commit-by-commit, and they'll prefer the "Files changed" view. So we might as well aim to squash all the work you do in order to minimize red line count.

@garbear

garbear commented May 29, 2026

Copy link
Copy Markdown
Owner

I'm getting closer to finishing the builds. Jenkins mostly passes: https://jenkins.kodi.tv/view/Automation/job/BuildMulti-All/3268/ . LE fails to build (breaks compiling kodi due to missing mutex.h includes). I'll keep going til I have builds.

@sunlollyking

Copy link
Copy Markdown
Author

Cheevos.cpp uses std::mutex but doesn't explicitly include . It compiles fine on standard GCC because it gets pulled in transitively, but LE's stricter toolchain won't have it. Maybe that's the issue ?

@garbear
garbear force-pushed the retroplayer-22beta1 branch from fbcc9f3 to 69efd20 Compare May 29, 2026 21:15
@garbear

garbear commented May 29, 2026

Copy link
Copy Markdown
Owner

Yup, that fixed it. There should be a "allow contributions from other developers" option that's checked for this PR. I'll force-push it to the squashed state.

@garbear
garbear changed the base branch from retroplayer-22beta1 to retroachievements-base May 29, 2026 23:15
@garbear
garbear force-pushed the retroplayer-22alpha3-leaderboards branch from bc69efd to e863d84 Compare May 29, 2026 23:17
@garbear

garbear commented May 29, 2026

Copy link
Copy Markdown
Owner

Builds are uploading to my releases page, and this PR is down to 171 lines removed. I'll post news of the builds in the forum.

https://github.com/garbear/xbmc/releases/tag/retroplayer-22beta1-20260529

@garbear
garbear force-pushed the retroplayer-22alpha3-leaderboards branch from e863d84 to c346f50 Compare May 29, 2026 23:19
@garbear

garbear commented May 29, 2026

Copy link
Copy Markdown
Owner

Oops, builds were broke. I'm uploading two versions, one with controller add-ons, and one without. Try the one with controller add-ons first and LMK if it boots.

ETA: 2 hrs

@sunlollyking

Copy link
Copy Markdown
Author

This is really exciting. Once there's a working LE build up in install and test. Currently cant see any and I know we've had problems with some of the sizes before

@garbear

garbear commented May 30, 2026

Copy link
Copy Markdown
Owner

@garbear garbear mentioned this pull request May 31, 2026
9 tasks
@sunlollyking

Copy link
Copy Markdown
Author

Commits being added in the next few hours that change:

Session stability: Users will no longer be unexpectedly logged out due to transient network failures when loading games. The token is now only cleared on an explicit authentication error from the RA server.

Notification images: Game icons and achievement badge images now always appear in notifications, including on first load (previously only showed after a second load once the image was cached).

Leaderboard UX: Logged-out users no longer see a brief empty dialog flash before being shown the login prompt. Page up/down scrolling now works in the leaderboard entries list.

Icon consistency: All RetroAchievements warning notifications now use the warning icon consistently.

InfoLabel rename: RetroPlayer.AchievementsLoggedIn renamed to RetroPlayer.RetroAchievementsLoggedIn for clarity and consistency with the platform name.

@garbear

garbear commented May 31, 2026

Copy link
Copy Markdown
Owner

@sunlollyking I pushed a commit. My agent has big trouble with XML indentation. You might have to tweak some XML by hand before pushing.

Regarding the commit, either rebase on it, or just force-push over it.

void FetchEntriesAsync();
void RefreshList();

// Utility function

Copy link
Copy Markdown
Owner

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Your agent is removing good comments.

Comment thread addons/skin.estuary/xml/GameOSD.xml Outdated
Comment thread xbmc/GUIInfoManager.cpp Outdated
Comment thread xbmc/cores/RetroPlayer/cheevos/Cheevos.cpp Outdated
@sunlollyking

Copy link
Copy Markdown
Author

I'm not 100% sure what issues the fixes resolved, and I haven't tested since last week, so nothing unresolved from my end. I see unreleased stuff here tho, so I'll do a round of builds with it included. While in progress, can you do a sanity check from the latest commit here?

Since the last round of test builds we've fixed:

Bug fixes (individual commits on PR #147):

Missing and includes in Cheevos.cpp — caused LE build failures on strict toolchains
Session expiry on transient network failure — any brief connectivity hiccup was incorrectly clearing the login token and logging users out
Game icon not showing in load notification — race condition meant the default Kodi icon showed instead of the game image on first load
Achievement badge not showing on first unlock — same race condition for achievement unlock notifications
Notification icon inconsistency — achievements used DefaultIconInfo, leaderboards used DefaultIconWarning; now consistent
Leaderboard dialog flash when not logged in — dialog briefly opened then closed; now checks login state first
Redundant "RetroAchievements" text in achievements dialog header removed
RetroPlayer.AchievementsLoggedIn renamed to RetroPlayer.RetroAchievementsLoggedIn for clarity
Page up/down scrolling not working in leaderboard entries dialog
RA metadata (title, publisher, developer, genre) now populates standard game info tag fields instead of achievements-prefixed InfoLabel

Comment thread xbmc/GUIInfoManager.cpp
@garbear

garbear commented Jun 10, 2026

Copy link
Copy Markdown
Owner

The update mostly looks good, but check out the diff for Includes_Games.xml. I fixed the tab indentations; if you push XML with good indentation, you won't get ugly red like that whole file. Also it looks like some dialogs were dropped?

@sunlollyking

Copy link
Copy Markdown
Author

The update mostly looks good, but check out the diff for Includes_Games.xml. I fixed the tab indentations; if you push XML with good indentation, you won't get ugly red like that whole file. Also it looks like some dialogs were dropped?

Cool i'll make sure to get the formatting correct next time I see what you mean. I'm away from my PC at the moment - all dialogs should be there ? Maybe something got pulled out during the rebase.

@sunlollyking

Copy link
Copy Markdown
Author

Ok thats all the dialogs back in - Weird they must have dropped during a rebase - Tried to make sure formatting was ok too.

Let me know if there's anything else needed.

@garbear

garbear commented Jun 10, 2026

Copy link
Copy Markdown
Owner

Sorry, but the XML file is still way messed up. I squashed your top two commits and look at how the diff is messed up: achievements (expand Includes_Games.xml‎)

Note that my agent had trouble with indentation of Kodi skins. You may need a XML formatting tool or to do it by hand.

When you're ready do an interactive rebase against 41a568e and squash everything into one commit. Then do git show HEAD to see the skin diff. It shouldn't be ugly like in the commit I linked.

@sunlollyking
sunlollyking force-pushed the retroplayer-22alpha3-leaderboards branch 2 times, most recently from 8d1ab8b to 088e713 Compare June 10, 2026 20:02
@sunlollyking

Copy link
Copy Markdown
Author

@garbear ok did that sort it ?

@garbear

garbear commented Jun 10, 2026

Copy link
Copy Markdown
Owner

Nice, that basically got it. There's two stray newlines that got added, which don't improve readability, so those can get removed. But otherwise I'll do a build with this branch.

@sunlollyking
sunlollyking force-pushed the retroplayer-22alpha3-leaderboards branch from 088e713 to 72084a2 Compare June 10, 2026 20:37
@sunlollyking

Copy link
Copy Markdown
Author

Fixed achievements never triggering during gameplay.
CheckTriggeredAchievement() was only being called once at startup and never again. Fixed by hooking it into FrameEvent() so achievement conditions are evaluated every frame. Also fixed a secondary build error caused by a missing KODI::GAME namespace declaration in Cheevos.cpp.

@garbear

garbear commented Jun 22, 2026

Copy link
Copy Markdown
Owner

OK, I grabbed your latest fixes. I'm doing a round of test builds based on Beta 1 final, so I'll include the stuff here.

@garbear

garbear commented Jun 24, 2026

Copy link
Copy Markdown
Owner

Done: https://github.com/garbear/xbmc/releases/tag/retroplayer-22beta1-20260622

If we want to land this in master, it's best t chop up into small parts. For example, I got the binary API change in. Can you fix RA login in master? That would reduce the size and complexity of our patch here. Then we keep whittling it down until it's all in.

@sunlollyking

Copy link
Copy Markdown
Author

Cool yep I should be able to do that. I'll split out the code and open up a PR against Kodi master?

Ill be able to test this build later today but commited to getting this in for Q*

@sunlollyking
sunlollyking force-pushed the retroplayer-22alpha3-leaderboards branch from 344f5f2 to 6a4271c Compare June 24, 2026 21:12
@garbear

garbear commented Jun 25, 2026

Copy link
Copy Markdown
Owner

Agreed, lets get the RA fix into v22 (that way captions work!) and the rest in Q*.

@garbear
garbear force-pushed the retroachievements-base branch from 7018477 to 6a11381 Compare June 26, 2026 21:06
@garbear
garbear force-pushed the retroplayer-22alpha3-leaderboards branch from 0a7f54e to 1aab99a Compare June 26, 2026 21:08
Shardul555 and others added 3 commits June 26, 2026 14:10
Implements a complete RetroAchievements (RA) integration for RetroPlayer.
Users with a RetroAchievements account can log in via Settings, earn
achievements during gameplay and receive real-time popup notifications.

Changes:
- CCheevos: login via RA Connect API (r=login2, HTTPS), session token
  persisted to settings so subsequent launches do not require re-entry
- CCheevos: achievement unlock notifications with badge artwork downloaded
  in background before the toast is shown, avoiding blank-icon flicker
- CCheevos: mastery notification on 100% game completion
- CCheevos: offline award queue — unlocks earned while offline are
  submitted when connectivity is restored
- CCheevos: rich presence string evaluated every 2 minutes and posted
  to RA so the user's profile page reflects current game state
- CCheevos: thread safety throughout — mutex-guarded state, atomic
  rich presence flag, persistent m_cheevoCallback member to prevent
  dangling pointer in achievement callback registration
- CCheevos: populated CGameInfoTag (Title, Publisher, Developer, Genres)
  from RA patch data so standard RetroPlayer InfoLabels reflect RA metadata
- CGameSettings: startup token validation resets stale logged-in flag;
  login2 fix; HTTPS; VERIFY_ACCOUNT endpoint replaces broken g=0 patch
  request; password no longer cleared on failed login attempt
- CGamesGUIInfo: RetroPlayer.RetroAchievementsLoggedIn boolean condition
  and RetroPlayer.AchievementsRichPresence string InfoLabel
- .gitignore: exclude ROM files, Zone.Identifier and build artefacts

Cheevos: Skip unlock notification for already-earned achievements

fceumm fires the achievement callback for achievements whose conditions
are met in-game, regardless of whether they were earned in a previous
session. This caused a spurious unlock notification to appear for
achievements the user had already earned.

Fix: before showing the unlock notification in CallbackUrlId, check the
loaded AchievementState to see if the achievement is already marked as
earned. If so, skip the notification silently — RA handles duplicate
award submissions gracefully so the HTTP award call is not needed either.

Cheevos: Apply clang-format to all modified C++ files
@garbear
garbear force-pushed the retroplayer-22alpha3-leaderboards branch from 1aab99a to 90eb216 Compare June 26, 2026 21:11
@garbear

garbear commented Jun 26, 2026

Copy link
Copy Markdown
Owner

@sunlollyking I have a treat for you. I fully squashed and rebased this PR on top of xbmc#28496. I'll do a round of test builds and we can test both xbmc#28496 and the work here.

EDIT: As a side effect, you can check the final commit, and see if any of it is missing from the upstream PR.

@sunlollyking

Copy link
Copy Markdown
Author

@garbear
I rebuilt this from source on a separate Ubuntu 26.04 machine (native x86_64, fceumm built via the same cmake addon flow) to see if the crash reproduces outside LibreELEC. It doesn't — I tested Kung Fu and Felix the Cat, both unlocked achievements cleanly with no crash. AwardAchievement and DeactivateTriggeredAchievement both completed without issue.
So this looks like it's specific to the game.libretro.so binary shipped in the LibreELEC build rather than a bug in the achievements code itself — same Cheevos.cpp logic, same branch, different platform/binary, and the crash only shows up on one of them. Possibilities I'd flag:

LibreELEC's game.libretro.so may be built from a different commit than what's in the source tree, or cross-compiled with different flags
Could be an ABI/alignment issue specific to whatever architecture the LibreELEC image targets
Could be a timing/race condition that's more likely to surface under LibreELEC's tighter resource constraints than on a desktop machine

Given it's isolated to game.libretro.so rather than our Cheevos.cpp code, might be worth checking what commit/build LibreELEC's game.libretro is actually running versus the source tree, in case there's a mismatch.
Happy to provide my full build steps if useful for comparison.

Unsure if this is also affecting xbmc#28496 - But confirming this works on Ubuntu.

@garbear

garbear commented Jun 30, 2026

Copy link
Copy Markdown
Owner

Hm, weird that it is only reproducible on LE. It's likely not an LE issue but a problem in the game.libretro code introduced in kodi-game/game.libretro#158. Keep in mind, it's originally student code (no knock on students but they're still learning patterns to avoid crashes like this).

I also got a crash in game.libretro in an achievements function playing an N64 game on my macbook. So it's likely there's even more than one issue in the code.

This reminds me of when I was bright-eyed and new to embedded, doing contract work for Valve to get Kodi on the Steam Link, and Kodi kept crashing. Couldn't reproduce locally. And it's like, well you gotta go in with gdb and find the problem. It took me two weeks. But the only other option was failure, so I had to keep learning and keep digging. Of course, the solution was a single character in a single line - I had a change a 6 to a 7, and instant success.

It looks like we're down to the GDB stage. Here's some gdb resources from my Steam Link job:

I got creative and probably saved a few days by doing visual debugging in Eclipse instead of learning gdb's command line interface. But that comes with its own challenges.

Fortunately, LE has some great devs who can offer help and resources. Keep chasing the problem, and if you have no luck, we'll reconvene and figure out another approach.

@sunlollyking

Copy link
Copy Markdown
Author

Going to close this PR now as it's been superceeded by #149

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.

3 participants