Skip to content

RetroPlayer: Add RetroAchievements Game API callbacks - #150

Open
sunlollyking wants to merge 4 commits into
garbear:masterfrom
sunlollyking:retroplayer-achievements-api
Open

RetroPlayer: Add RetroAchievements Game API callbacks#150
sunlollyking wants to merge 4 commits into
garbear:masterfrom
sunlollyking:retroplayer-achievements-api

Conversation

@sunlollyking

@sunlollyking sunlollyking commented Jul 12, 2026

Copy link
Copy Markdown

Description

Extends the Game add-on API with add-on-to-Kodi callbacks for RetroAchievements events, keeping rcheevos as a binary add-on dependency (in game.libretro) rather than compiled into Kodi. This is the Kodi-side counterpart to the game.libretro rc-client-integration PR.

Per garbear's architectural guidance, rcheevos stays in game.libretro. Kodi receives events and handles display only — it performs no RetroAchievements network I/O and holds no knowledge of the achievement runtime. No rcheevos source is compiled into Kodi.

Flow:
game.libretro (owns rc_client) → Game API callbacks → CGameClientCheevos → CAchievementRuntime → OSD dialog

Game API additions (kodi-dev-kit), 6.0.0 → 6.1.0:

  • New C structs: game_rc_achievement, game_rc_game_loaded, game_rc_achievement_triggered, game_rc_login_result, plus GAME_RC_UNLOCK_STATE
  • New callbacks in AddonToKodiFuncTable_Game: RCOnGameLoaded, RCOnAchievementTriggered, RCOnGameCompleted, RCOnRichPresenceUpdated, RCOnLoginResult
  • C++ wrappers in Game.h for add-on-side use
  • The change is purely additive: members are appended to the end of AddonToKodiFuncTable_Game so the offsets used by add-ons built against 6.0.0 stay valid, and KodiToAddonFuncTable_Game is untouched. ADDON_INSTANCE_VERSION_GAME_MIN therefore stays at 6.0.0 and existing add-ons keep working.

Kodi-side implementation:

  • GameClient.cpp: static callback functions wired in Initialize(), forwarding to CGameClientCheevos
  • GameClientCheevos.cpp: event receivers that validate every pointer and count from the add-on, cap what they copy, publish to the achievement runtime and post localized notifications. Badge, icon and avatar URLs are handed to Kodi's texture cache rather than downloaded, so no background threads are involved.
  • AchievementRuntime.h/cpp: extends garbear's existing runtime with targeted accessors for the two fields the info label reads, since GetState() copies the whole achievement list and skins query info labels once per frame per control
  • GamesGUIInfo.cpp: handler for RetroPlayer.AchievementsProgress
  • GameSettings.cpp: SetAchievementsLoggedIn() so a rejected token can't leave the UI claiming the player is signed in

OSD dialog:

  • DialogGameAchievements: achievement list with badges, points, rarity and unlock dates, refreshed live when one is earned. Reuses DialogGameControllers.xml as its window file, as that file documents, so skins without the new layout still work.

Skin (Estuary):

  • GameOSD.xml: an achievements button, shown unconditionally so the dialog can explain whether the player needs to sign in or the game has no achievement set. The menu grows by one row to fit it.
  • Includes_Games.xml: the dialog layout, with the focused row scrolling its title and criteria since achievement criteria are frequently longer than the column

Bugs fixed along the way:

  • CDateTime::GetAsLocalizedDate() was called with a string literal, which binds to the GetAsLocalizedDate(bool) overload as true — the format was silently discarded and the long date used
  • The in-game menu's list extended 80px past its dialog background, letting the bottom row render outside the shaded area
  • GAME_ERROR_NOT_IMPLEMENTED was logged at ERROR. Declining an optional part of the API is not a failure, so it now logs at DEBUG and ERROR is reserved for genuine ones
  • The two hardcoded English strings in CGameSettings::LoginToRA() are now localized, closing a review comment deferred from RetroPlayer: Add RetroAchievements integration xbmc/xbmc#28496

Motivation and context

RetroAchievements integration for Kodi RetroPlayer. Previously rcheevos was vendored directly into the Kodi source tree, which garbear identified as architecturally wrong — third-party libraries used by binary add-ons should stay in the add-on, not in Kodi core. This PR restructures the integration so Kodi only receives and displays events, while game.libretro owns all rcheevos logic.

Addresses garbear's review feedback on #149, and builds on the achievement runtime introduced by #28496.

How has this been tested?

Built and tested on Ubuntu 26.04 x86_64, against the companion game.libretro branch.

Verified end to end: signed in, loaded Sonic the Hedgehog 2 (Mega Drive), earned Hold Your Breath in play, and confirmed via the log that the event reached Kodi, the toast appeared with its badge, the award was submitted to RetroAchievements and the score updated. Also verified on Super Mario Bros. (NES) that the achievement list, counts and progress label populate correctly.

  • Unit tests: 8 in TestGamesGUIInfo, covering the info label, the empty case, and CAchievementRuntime::MarkEarned() not double-counting a re-reported unlock
  • Full suite passes (3513 tests), clang-format clean
  • Verified the guard paths: not signed in, and a game with no achievement set, each show their toast and close without a frame of render
  • Verified the OSD menu fits without scrolling in both the disc and non-disc variants
  • Verified the sign-in notification carries the player's avatar

Platforms tested: Ubuntu 26.04 (development), LibreELEC Generic x86_64 (previous branch iterations)

Requires the companion game.libretro#162 for the events to arrive; without it Kodi simply shows no achievement data.

What is the effect on users?

Adds RetroAchievements support to Kodi RetroPlayer. Users with a RetroAchievements account can:

  • See achievement unlock notifications with badge images while playing retro games
  • Browse a game's achievement list with descriptions, point values, rarity and unlock status
  • See rich presence updates showing current in-game status
  • See a mastery notification when all achievements are unlocked

No impact on users who don't use RetroAchievements. The achievements button is always present in the game OSD, and tells the player they need to sign in rather than silently hiding — the same reasoning as offering port 2 on a one-player game.

Leaderboards are deliberately out of scope. They are redundant until hardcore mode lands and are better reviewed alongside it.

Screenshots (if appropriate):

Types of change

  • 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

Copy link
Copy Markdown
Author

@garbear I know you're very busy with Beta 2 - I'd be keen when you're doing the next round of Retroplayer builds based on the release to see if we could include this and kodi-game/game.libretro#162 so we're properly able to test unlocking across all platforms. If working then we can start hacking out features into V23 :)

@garbear

garbear commented Aug 3, 2026

Copy link
Copy Markdown
Owner

Indeed, busy with Beta 2, I'll report back here after release (tho realistically prolly before) with a build that includes the open PRs. Just get any PRs open and fully updated and when I can do a build it'll include them all.

I'm still doing my own local testing against retroplayer-xxx builds.

@sunlollyking
sunlollyking force-pushed the retroplayer-achievements-api branch from 17aa36d to bf78933 Compare August 4, 2026 12:46
@sunlollyking
sunlollyking changed the base branch from master to retroplayer-22beta2 August 4, 2026 12:52
@sunlollyking
sunlollyking force-pushed the retroplayer-achievements-api branch 7 times, most recently from 06ee351 to 5c15304 Compare August 5, 2026 15:29
@garbear
garbear force-pushed the retroplayer-22beta2 branch 2 times, most recently from e893bf7 to c5bf624 Compare August 5, 2026 23:23
@garbear garbear self-assigned this Aug 6, 2026
@garbear

garbear commented Aug 6, 2026

Copy link
Copy Markdown
Owner

Failed test cases, needed:

--- a/xbmc/guilib/test/TestGamesGUIInfo.cpp
+++ b/xbmc/guilib/test/TestGamesGUIInfo.cpp
@@ -123,18 +123,20 @@ TEST_F(TestGamesGUIInfo, MarkEarnedOnlyCountsTheFirstUnlock)
   achievementRuntime.SetState(MakeAchievementState());
 
   bool newlyEarned = false;
-  AchievementState state = achievementRuntime.MarkEarned(2, newlyEarned);
+  AchievementState state = achievementRuntime.MarkEarned(2, "2026-08-05 19:20", newlyEarned);
   EXPECT_TRUE(newlyEarned);
   EXPECT_EQ(state.unlockedAchievements, 2U);
+  EXPECT_EQ(state.achievements[1].unlockedDate, "2026-08-05 19:20");
 
   // The achievement runtime re-reports achievements earned in an earlier
-  // session, which must not inflate the count
-  state = achievementRuntime.MarkEarned(2, newlyEarned);
+  // session, which must not inflate the count or replace the unlock date
+  state = achievementRuntime.MarkEarned(2, "2026-08-06 08:15", newlyEarned);
   EXPECT_FALSE(newlyEarned);
   EXPECT_EQ(state.unlockedAchievements, 2U);
+  EXPECT_EQ(state.achievements[1].unlockedDate, "2026-08-05 19:20");
 
   // An unknown ID must not change anything
-  state = achievementRuntime.MarkEarned(99, newlyEarned);
+  state = achievementRuntime.MarkEarned(99, "2026-08-07 12:00", newlyEarned);
   EXPECT_FALSE(newlyEarned);
   EXPECT_EQ(state.unlockedAchievements, 2U);
 }

I'm starting the process of making new RP builds. Still working through build/test failures: https://jenkins.kodi.tv/view/Automation/job/BuildMulti-All/3343/

@garbear

garbear commented Aug 6, 2026

Copy link
Copy Markdown
Owner

Probably retarget my master? Then I can control what the retroplayer-22beta2 branch does on top of this.

@sunlollyking
sunlollyking force-pushed the retroplayer-achievements-api branch from 5c15304 to 3fad5fa Compare August 6, 2026 07:12
@sunlollyking
sunlollyking changed the base branch from retroplayer-22beta2 to master August 6, 2026 07:13
@sunlollyking

sunlollyking commented Aug 6, 2026

Copy link
Copy Markdown
Author

Thanks @garbear — both points addressed, and the branch is updated.

Testing: I've had a LibreELEC Generic x86_64 build running with all of this and it works well — achievements unlock and submit across Genesis and NES titles, progress bars track measured achievements, and unlock notifications carry the right badge.

@garbear

garbear commented Aug 19, 2026

Copy link
Copy Markdown
Owner

Fixed the two baby rebase conflicts. I'll include this in my test builds today.

@garbear

garbear commented Aug 20, 2026

Copy link
Copy Markdown
Owner

Test builds are up! https://github.com/garbear/xbmc/releases/tag/retroplayer-22beta2-20260819

Included everything so far, all work, except for HW rendering.

The new dialog works great. Next I'm working on an achievement to test unlocking.

We should get this work against master soon. I'll do a review here first then we can upstream.

@sunlollyking

Copy link
Copy Markdown
Author

Amazing. Yep I've been using it for some time now and really keen on building on it I've just been waiting for the master merge. It feels rock solid though it's more just making sure your using the rom version that aligns with what's in the RA dB. Open to more feature suggestions and tightening

///
/// @note Added in Game API 7.1.0
///
void KodiRCOnGameLoaded(const game_rc_game_loaded& data)

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.

Please remove branding (the Kodi word) from API calls.

Copy link
Copy Markdown
Author

Choose a reason for hiding this comment

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

Done in 438c224. The C table already named these RCOnGameLoaded and friends — only the C++ wrapper carried the prefix, so the two halves now agree, and it matches what 7.1.1 did to GetPlaybackSpeed.

Left KodiInputEvent alone: it predates this PR.

One knock-on worth flagging — kodi-game/game.libretro#162 calls these by the old names, so it needs the same rename before the pair will build together. I'll push that once you're happy with the naming here.

Comment thread addons/skin.estuary/xml/Variables.xml Outdated
<value condition="!RetroPlayer.DiscEjected">60FFFFFF</value>
<value>FFFFFFFF</value>
</variable>
<variable name="GameAchievementBadgeTintVar">

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.

I think this can go right above <include name="GameAchievementItem">. That would be a better place for it than the generic Variables.xml.

Copy link
Copy Markdown
Author

Choose a reason for hiding this comment

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

Moved in 438c224 — it now sits directly above <include name="GameAchievementItem"> in Includes_Games.xml, which is the only thing that references it. Both files still parse.

Comment on lines +1415 to +1421
/*
* RetroAchievements events, added in Game API 7.1.0.
*
* New members must be appended here so that the offsets of the members
* above stay valid for add-ons built against an older version of this
* header.
*/

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.

Please remove this comment. AI gets too verbose with comments, so do a review pass after generation and strip out what isn't needed.

Copy link
Copy Markdown
Author

Choose a reason for hiding this comment

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

Removed in 438c224. Fair — it restated what the struct layout already implies.

@garbear

garbear commented Aug 20, 2026

Copy link
Copy Markdown
Owner

Looks like the % calculation is broken.

Screenshot 2026-08-20 at 4 51 36 PM

Comment thread xbmc/cores/RetroPlayer/playback/ReversiblePlayback.cpp Outdated
Add(new GAME::CDialogInGameSaves);
Add(new GAME::CGUIAgentWindow);
Add(new GAME::CDialogGameDiscManager);
Add(new GAME::CDialogGameAchievements);

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.

Missing delete call (deletes via WINDOW_DIALOG_GAME_ACHIEVEMENTS constant)

Copy link
Copy Markdown
Author

Choose a reason for hiding this comment

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

Good catch, fixed in 438c224. It was added in CreateWindows() and never torn down, so it outlived DestroyWindows() while every other game dialog was destroyed. DestroyWindow(WINDOW_DIALOG_GAME_ACHIEVEMENTS) now sits with the rest.

@sunlollyking

Copy link
Copy Markdown
Author

Looks like the % calculation is broken.

Screenshot 2026-08-20 at 4 51 36 PM

With this it'll genuinely be because there are so many achievements in that game and the weighting of the ones you've unlocked haven't triggered it over 0% because diff achievements have different points attached. I can look Into it further but it does work

sunlollyking added a commit to sunlollyking/xbmc that referenced this pull request Aug 21, 2026
Four things from review on garbear#150.

Drop the Kodi prefix from the eight RetroAchievements callbacks in the C++
wrapper. The C table already named them RCOnGameLoaded and so on; only the
wrapper carried the branding, so this makes the two halves agree and follows
what Game API 7.1.1 did for GetPlaybackSpeed. KodiInputEvent is left alone,
being none of this PR's business.

Destroy the achievements dialog. It was added in CreateWindows() and never
torn down, so it outlived DestroyWindows() while every other game dialog did
not.

Move GameAchievementBadgeTintVar out of the generic Variables.xml and put it
directly above GameAchievementItem in Includes_Games.xml, beside the only
thing that uses it.

Drop the comment about appending to the callback table. It restated what the
struct layout already implies.
sunlollyking pushed a commit to sunlollyking/game.libretro that referenced this pull request Aug 21, 2026
Review on garbear/xbmc#150 asked for the Kodi prefix to come off the
RetroAchievements callbacks, so the C++ wrapper now matches the C table that
already named them RCOnGameLoaded and friends. Follow that here.

Eleven call sites, no behaviour change. This has to land with the Kodi side
rather than before it -- the old names no longer exist.
@garbear

garbear commented Aug 21, 2026

Copy link
Copy Markdown
Owner

Let's do version 8.0.0, what do you think? versions.h needs a rebase conflict fixed after game api v7.2.0.

Do the other RC functions need to be dropped?

Chris and others added 2 commits August 21, 2026 09:20
RetroAchievements support currently lives in Kodi, which means Kodi drives the
legacy dorequest.php API directly and every game client inherits whatever it
implements. Move the runtime into the game add-on and give it a way to report
back, so the add-on owns identification, memory access and unlocking, and Kodi
owns presentation.

Game API 6.1.0 appends eight callbacks to AddonToKodiFuncTable_Game:

 - RCOnGameLoaded, once the add-on has identified the game and resolved its
   achievement set
 - RCOnAchievementTriggered, when an achievement is earned
 - RCOnGameCompleted, when the whole set is earned
 - RCOnRichPresenceUpdated, for what the player is currently doing
 - RCOnLoginResult, for the outcome of a login attempt
 - RCOnAchievementProgress, for achievements that count something
 - RCOnServerError, for an API failure that will not be retried
 - RCOnConnectionChanged, for the transition in and out of offline play

Members are appended rather than inserted, and the existing structs are left
alone, so add-ons built against 6.0.0 keep working. MIN stays at 6.0.0.

CAchievementRuntime holds the resulting state for the current game. Its
mutating accessors are targeted rather than read-modify-write so that updates
from the game thread and the GUI thread cannot clobber each other, and the
info-label providers read single fields rather than copying the achievement
list on every rendered frame.

The achievements dialog lists the set with badges, points, rarity and unlock
dates, and draws a progress bar for achievements that count something and
haven't been earned. Progress is a snapshot taken when the dialog opens.
Achievements whose trigger is a plain threshold have no counter and report
nothing, which is why only some sets show a bar.

Notifications cover unlocking, completion, login, server errors, and going
offline and back. Only the unlock notification plays a sound, through the same
path as every other Kodi notification. Badges are pre-cached when the game
loads so an unlock draws its own badge immediately rather than briefly showing
the game icon left over from the load notification.

When RetroAchievements doesn't recognise a ROM's hash it still resolves it, to
a placeholder game titled "Unsupported Game Version" holding a single
always-true achievement. That would otherwise fire immediately and read as an
unlock, then as having mastered a one-achievement game; it is now treated as a
game without achievements.

The achievements button in the game OSD is always shown. A game being
unsupported, or the player not being signed in, is explained by a notification
rather than by the button quietly disappearing.

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
Four things from review on garbear#150.

Drop the Kodi prefix from the eight RetroAchievements callbacks in the C++
wrapper. The C table already named them RCOnGameLoaded and so on; only the
wrapper carried the branding, so this makes the two halves agree and follows
what Game API 7.1.1 did for GetPlaybackSpeed. KodiInputEvent is left alone,
being none of this PR's business.

Destroy the achievements dialog. It was added in CreateWindows() and never
torn down, so it outlived DestroyWindows() while every other game dialog did
not.

Move GameAchievementBadgeTintVar out of the generic Variables.xml and put it
directly above GameAchievementItem in Includes_Games.xml, beside the only
thing that uses it.

Drop the comment about appending to the callback table. It restated what the
struct layout already implies.
@sunlollyking
sunlollyking force-pushed the retroplayer-achievements-api branch from 438c224 to 9dfd4bc Compare August 21, 2026 08:20
@sunlollyking

Copy link
Copy Markdown
Author

Rebased onto master — the versions.h conflict is fixed and it's 0 behind. The branch already declared 8.0.0, so we agree; nothing to change there.

Worth recording why 8.0.0 is right rather than 7.3.0, because I checked while resolving: master's 7.2.0 is your "Allow setting game FPS/samplerate" (25a2bf39dd). That's additive. This PR is not — see below.

Yes, the other RC functions should be dropped

They are already dead, which I had not appreciated until you asked. Seven legacy entry points survive in KodiToAddonFuncTable_Game:

RCGenerateHashFromFile  RCGetGameIDUrl  RCGetPatchFileUrl  RCPostRichPresenceUrl
RCEnableRichPresence    RCGetRichPresenceEvaluation        RCResetRuntime

Kodi still calls all seven, from the old CCheevos that RetroPlayer.cpp:197 still constructs. But on the add-on side, kodi-game/game.libretro#162 stubs every one of them:

GAME_ERROR CGameLibRetro::RCEnableRichPresence(const std::string& script)
{
  return GAME_ERROR_NOT_IMPLEMENTED;
}

So with both PRs in, Kodi runs a second, older achievements implementation that drives an API the add-on has deliberately stopped answering. Two implementations, one of them talking to a wall. That is the strongest argument for the major bump: removing those seven changes the table layout, so nothing built against 7.x can be loaded against it, which is exactly what _MIN 8.0.0 says.

But it is bigger than deleting seven pointers

The functions are the small part. Behind them sits Kodi's own achievements implementation:

lines
xbmc/cores/RetroPlayer/cheevos/ (Cheevos, AwardQueue, ImageCache, RConsoleIDs) 1643
xbmc/games/addons/cheevos/ (the add-on-facing wrapper) 637

The new RCOn* path does not depend on any of it — it is wired straight onto the client in GameClient.cpp:186 — so the old path can go without disturbing the new one. But that is ~2,280 lines of deletion, and it changes this PR from "add an API" to "add an API and remove its predecessor".

How would you like it split? Three options as I see them:

  1. All in here. One PR that adds the new callbacks and removes the old implementation, landing as 8.0.0. Honest, self-contained, and the reviewer sees the whole trade — but it is a big diff.
  2. This PR adds, a follow-up removes. Keeps this one reviewable; costs a release where both paths exist and the old one silently does nothing.
  3. This PR drops the seven functions and the wrapper, a follow-up removes cores/RetroPlayer/cheevos/. Splits it at the API boundary, which is the line the version number is actually about.

My preference is 3 — the version bump and the ABI change land together, which is the bit that has to be atomic, and the 1,643 lines of dead implementation follow separately without an ABI consequence. Say which you want and I will do it.

One sequencing note

#151 currently also claims 7.2.0, for the hardware framebuffer size — a different layout under the same number as your FPS/samplerate change. I am moving that one to 7.3.0 as you asked. If this PR lands first at 8.0.0, I will re-target it to 8.1.0 instead; either order works as long as they do not both sit on 7.2.0.

@garbear

garbear commented Aug 21, 2026

Copy link
Copy Markdown
Owner

Rip out as much as you can!

The add-on owns rc_client now, so Kodi's own achievements implementation is
dead weight: game.libretro answers every one of the legacy entry points with
GAME_ERROR_NOT_IMPLEMENTED, while Kodi carried on calling them. Two
implementations, one of them talking to a wall.

Gone from the Game API: RCGenerateHashFromFile, RCGetGameIDUrl,
RCGetPatchFileUrl, RCPostRichPresenceUrl, RCEnableRichPresence,
RCGetRichPresenceEvaluation and RCResetRuntime, with their C++ wrappers and
thunks. That is what makes this 8.0.0 rather than an additive bump -- the
offsets of everything after them move.

Gone with them: cores/RetroPlayer/cheevos entirely, and the legacy half of
CGameClientCheevos. What remains there are the eight On* handlers the new
callbacks deliver into, which never depended on any of it.

Rich presence still reaches savestate captions. It arrives through
RCOnRichPresenceUpdated and is kept in CAchievementRuntime, so
ReversiblePlayback reads it from there rather than asking the client for an
evaluation it no longer computes.
@sunlollyking

Copy link
Copy Markdown
Author

Ripped out. 8812d6378e2,211 lines gone, 3 added, builds clean, 0 behind master.

What went:

  • The seven legacy entry points from the Game API — RCGenerateHashFromFile, RCGetGameIDUrl, RCGetPatchFileUrl, RCPostRichPresenceUrl, RCEnableRichPresence, RCGetRichPresenceEvaluation, RCResetRuntime — along with their C++ virtuals, their ADDON_* thunks and the assignments wiring them up. 21 removals across the two headers. That is what earns the 8.0.0.
  • cores/RetroPlayer/cheevos/ entirely: CCheevos, CheevosAwardQueue, CheevosImageCache, RConsoleIDs.
  • The legacy half of CGameClientCheevos — ten method bodies and their declarations.
  • CCheevos threading out of CRetroPlayer and the cheevos parameter out of CReversiblePlayback.

What stayed, and why it had to: CGameClientCheevos also hosts the eight On* handlers the new callbacks deliver into. They never touched the legacy code, so the file loses its old half and keeps its new one.

One thing needed re-plumbing rather than deleting. Savestate captions were taking their text from m_cheevos->GetRichPresenceEvaluation(). Rich presence still arrives — through RCOnRichPresenceUpdated, which stores it in CAchievementRuntime — so CReversiblePlayback now reads it from there. Same caption, sourced from the path that is actually live.

I checked CheevosImageCache and RConsoleID had no users outside the code being deleted before removing them, and that the achievements dialogs do not reach into any of it.

Comment thread xbmc/games/addons/GameClient.cpp Outdated
Comment thread xbmc/addons/kodi-dev-kit/include/kodi/c-api/addon-instance/game.h Outdated
sunlollyking pushed a commit to sunlollyking/game.libretro that referenced this pull request Aug 21, 2026
Review on garbear/xbmc#150 asked for the Kodi prefix to come off the
RetroAchievements callbacks, so the C++ wrapper now matches the C table that
already named them RCOnGameLoaded and friends. Follow that here.

Eleven call sites, no behaviour change. This has to land with the Kodi side
rather than before it -- the old names no longer exist.
sunlollyking pushed a commit to sunlollyking/game.libretro that referenced this pull request Aug 21, 2026
Two things, both following from review elsewhere.

garbear/xbmc#150 removes the seven legacy RetroAchievements entry points from
the Game API now that rc_client lives here, so the stubs that answered them
with GAME_ERROR_NOT_IMPLEMENTED override nothing any more. Gone, along with
their declarations.

The login guard was one-way. m_loginStarted is set when a login begins and was
only cleared in Deinitialize(), so a rejected token left it set and corrected
credentials could not start another attempt until the game was unloaded. It
exists to stop a second login racing one already in flight, not to make failure
permanent, so the failure path clears it. SetCredentials() already calls
BeginLogin(), so a corrected username or token now retries on the spot.
Comment thread xbmc/addons/kodi-dev-kit/include/kodi/c-api/addon-instance/game.h Outdated
Comment thread xbmc/cores/RetroPlayer/playback/ReversiblePlayback.cpp Outdated
Comment thread xbmc/games/addons/cheevos/GameClientCheevos.cpp Outdated
Comment thread xbmc/games/addons/cheevos/GameClientCheevos.cpp
Comment thread xbmc/games/GameSettings.cpp Outdated
Comment thread xbmc/games/AchievementRuntime.cpp Outdated
Comment thread xbmc/games/AchievementRuntime.h Outdated
Comment thread xbmc/games/AchievementRuntime.h
Carry the unlock as a CDateTime rather than preformatted text. The source is a
Unix timestamp from rc_client, not a string, and the only consumer is the
achievements dialog, so formatting it at the edge meant the runtime held
locale-dependent text nothing else could reason about. The date now travels as
a date and is localized where it is shown.

The rewind buffer comment was wrong. It does not hold a serialized state per
frame -- CDeltaPairMemoryStream stores xor deltas, and only the words that
changed -- so the logged figure is a ceiling rather than a cost. Says so now.

Comment tidying from review: the second sentence about add-ons declining
optional entry points is gone, the stdint include no longer names the types it
provides, the two localized-string references are a line each, and the removals
in the last commit left eleven consecutive blank lines behind.
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.

2 participants