Skip to content

feat: Add RetroAchievements integration and in-game notifications#633

Open
clintonium-119 wants to merge 27 commits intoLoveRetro:mainfrom
clintonium-119:feature/retroachievements-notifications
Open

feat: Add RetroAchievements integration and in-game notifications#633
clintonium-119 wants to merge 27 commits intoLoveRetro:mainfrom
clintonium-119:feature/retroachievements-notifications

Conversation

@clintonium-119
Copy link

Adds full RetroAchievements support for tg5040/tg5050 platforms with in-game toast notifications for achievements, save states, screenshots, and more.

RetroAchievements Features:

  • Login via Settings menu with on-screen keyboard
  • Achievement unlock notifications with badge images
  • Progress tracking and leaderboard support
  • Hardcore mode toggle (disables save states/cheats)
  • Game hash identification with CHD disc image support
  • Automatic badge caching and async downloading
  • Rich presence support

In-Game Notification System:

  • Toast notifications for save/load state operations
  • Screenshot confirmation notifications
  • Volume/brightness change indicators
  • Achievement unlock popups with game badges
  • Non-blocking async design

Technical:

  • Integrates rcheevos library (cloned at build time)
  • Uses libchdr for CD-ROM/CHD image hashing
  • Async HTTP client for RA API communication
  • Thread-safe badge cache with memory management
  • Platform-conditional compilation (tg5040/tg5050 only)

New files:

  • common/notification.{c,h} - Toast notification system
  • common/http.{c,h} - Async HTTP client wrapper
  • common/ra_auth.{c,h} - RA authentication handling
  • common/ra_badges.{c,h} - Badge download/caching
  • minarch/ra_integration.{c,h} - Core RA integration
  • minarch/chd_reader.{c,h} - CHD image support
  • rcheevos/makefile - rcheevos library build

@clintonium-119 clintonium-119 force-pushed the feature/retroachievements-notifications branch 4 times, most recently from 9d1d680 to 89784c0 Compare February 3, 2026 22:58
Adds full RetroAchievements support for tg5040/tg5050 platforms with in-game
toast notifications for achievements, save states, screenshots, and more.
RetroAchievements Features:
- Login via Settings menu with on-screen keyboard
- Achievement unlock notifications with badge images
- Progress tracking and leaderboard support
- Hardcore mode toggle (disables save states/cheats)
- Game hash identification with CHD disc image support
- Automatic badge caching and async downloading
- Rich presence support
In-Game Notification System:
- Toast notifications for save/load state operations
- Screenshot confirmation notifications
- Volume/brightness change indicators
- Achievement unlock popups with game badges
- Non-blocking async design
Technical:
- Integrates rcheevos library (cloned at build time)
- Uses libchdr for CD-ROM/CHD image hashing
- Async HTTP client for RA API communication
- Thread-safe badge cache with memory management
- Platform-conditional compilation (tg5040/tg5050 only)
New files:
- common/notification.{c,h} - Toast notification system
- common/http.{c,h} - Async HTTP client wrapper
- common/ra_auth.{c,h} - RA authentication handling
- common/ra_badges.{c,h} - Badge download/caching
- minarch/ra_integration.{c,h} - Core RA integration
- minarch/chd_reader.{c,h} - CHD image support
- rcheevos/makefile - rcheevos library build
@clintonium-119 clintonium-119 force-pushed the feature/retroachievements-notifications branch from 89784c0 to 3dc835d Compare February 3, 2026 23:03
@frysee
Copy link
Member

frysee commented Feb 4, 2026

Not necessarily caused by your changes, but I just noticed that the framebuffer is not properly cleared after a notification pill was shown:
IMG_9169

@frysee
Copy link
Member

frysee commented Feb 4, 2026

When RA is turned off in settings, the ingame "Achievements" menu shows a "No game loaded for achievements" message. I think I would prefer either a more fitting message based on CFG_getRAEnable(), or the menu entry being hidden entirely in that case.

@frysee
Copy link
Member

frysee commented Feb 4, 2026

On initial launch of a game where nothing has been cached yet, I can see major slowdown while the badges are pulled down (my assumption). Maybe a toast should stick around until that background process completes?

Co-authored-by: frysee <frysee@googlemail.com>
@clintonium-119
Copy link
Author

When RA is turned off in settings, the ingame "Achievements" menu shows a "No game loaded for achievements" message. I think I would prefer either a more fitting message based on CFG_getRAEnable(), or the menu entry being hidden entirely in that case.

Good catch. I think I should hide it completely in that case.

@clintonium-119
Copy link
Author

On initial launch of a game where nothing has been cached yet, I can see major slowdown while the badges are pulled down (my assumption). Maybe a toast should stick around until that background process completes?

Yeah, that's a good idea. I can implement that.

When notifications end, trigger 3 frames of glClear() to fully clear
the framebuffer including areas outside the game's viewport.
GFX API refinements:
- Remove center_x param from GFX_blitWrappedText (calculates internally)
- Rename screen to surface for clarity
- Add IndicatorType enum (BRIGHTNESS, VOLUME, COLORTEMP)
- Use GFX_blitPillLight instead of GFX_blitPillColor
- Use SDL_SWSURFACE instead of 0 in GFX_createScreenFormatSurface
RetroAchievements cleanup:
- Refactor ra_consoles.h to use lookup table instead of if/strcmp chain
- Replace RA_LOG with leveled macros (DEBUG, INFO, WARN, ERROR)
  mapping to NextUI's native LOG_* functions
Video/Desktop fixes:
- Add framebuffer clearing for 3 frames when notifications end
- Simplify desktop msettings.c with hardcoded defaults
Store RetroAchievements data (muted achievements, badge cache) in
SHARED_USERDATA_PATH/.ra instead of per-platform USERDATA_PATH/ra.
Dynamically adjust options menu based on CFG_getRAEnable() state.
When RA is disabled, the Achievements item is hidden and Save Changes
moves up to fill the gap.
- Add download queue with max 8 concurrent requests to prevent
  network/disk thrashing that caused gameplay stuttering
- Lazy load badge images on-demand instead of during prefetch
  (only save PNG to disk during prefetch, decode when displayed)
- Show persistent "Loading achievement badges..." indicator
  during download that auto-hides when complete
- Fix progress indicator to omit colon when progress string is empty
- Remove unused RA_Badges_hasPendingDownloads()
@clintonium-119
Copy link
Author

@frysee

Ready for re-review! Here's a summary of the changes since last feedback:

Badge prefetching optimization - The biggest change. Badge downloads now use a rate-limited queue (max 8 concurrent) with lazy loading. During prefetch, we only save PNGs to disk without decoding; images are loaded on-demand when actually displayed. This seems to completely eliminate the gameplay stuttering that occurred when loading games with 100+ achievements. A persistent "Loading achievement badges..." indicator shows while it's progressing.

Framebuffer clearing

  • Added 3-frame glClear() when notifications end to address the artifact issue you reported. I wasn't able to reproduce the original issue on my end, so I'd be curious if this fixes it for you.

Other changes:

  • RA data now stored in shared userdata (SHARED_USERDATA_PATH/.ra) instead of per-platform
  • Achievements menu hidden when RA is disabled
  • All your API feedback implemented (GFX refinements, IndicatorType enum, leveled logging, ra_consoles lookup table)

@frysee
Copy link
Member

frysee commented Feb 5, 2026

@frysee

Ready for re-review! Here's a summary of the changes since last feedback:

Badge prefetching optimization - The biggest change. Badge downloads now use a rate-limited queue (max 8 concurrent) with lazy loading. During prefetch, we only save PNGs to disk without decoding; images are loaded on-demand when actually displayed. This seems to completely eliminate the gameplay stuttering that occurred when loading games with 100+ achievements. A persistent "Loading achievement badges..." indicator shows while it's progressing.

Framebuffer clearing

  • Added 3-frame glClear() when notifications end to address the artifact issue you reported. I wasn't able to reproduce the original issue on my end, so I'd be curious if this fixes it for you.

Other changes:

  • RA data now stored in shared userdata (SHARED_USERDATA_PATH/.ra) instead of per-platform
  • Achievements menu hidden when RA is disabled
  • All your API feedback implemented (GFX refinements, IndicatorType enum, leveled logging, ra_consoles lookup table)

You're quick! I'll check it out in a bit, thanks!

@clintonium-119 clintonium-119 requested a review from frysee February 5, 2026 20:08
@frysee
Copy link
Member

frysee commented Feb 5, 2026

Looks like a few of the review items are still open above. Let me know if you want me to take over some of them!

@clintonium-119
Copy link
Author

Looks like a few of the review items are still open above. Let me know if you want me to take over some of them!

Ah, yes, they were folded behind the 'X conversationsn hidden' button - I didn't even see them.

I'll get on these.

clintonium-119 and others added 15 commits February 5, 2026 15:28
Co-authored-by: frysee <frysee@googlemail.com>
Co-authored-by: frysee <frysee@googlemail.com>
Co-authored-by: frysee <frysee@googlemail.com>
- Group related static variables into structs:
  - ra_integration.c: RAPendingLoad and RALoginRetry structs
  - notification.c: ProgressIndicatorState struct (renamed to
progress_state)
  - ra_badges.c: DownloadQueueState struct
- Extract PLAT_initNotificationTexture() from PLAT_initShaders()
- Add rcheevos integration guide references to header files:
  - ra_integration.h, ra_auth.h, ra_badges.h
- Simplify/clarify comments in http.c and ra_auth.c
Pull layout values (padding, margins, gaps) to #defines at top of file
for better readability and maintainability.
…clintonium-119/NextUI into feature/retroachievements-notifications
Extract rendering logic into focused helper functions:
- render_system_indicator() for hardware indicator (top-right)
- render_progress_indicator() for progress pill (top-left)
- render_notification_pill() for individual notification rendering
- render_notification_stack() for stacked notifications (bottom-left)
Use ifneq filter pattern to combine identical rcheevos/libchdr linking
for all RA-enabled platforms, with nested conditional for desktop rpath.
Per PR feedback, HTTP client is only used by minarch (RA integration).
Update include paths in ra_auth.c and ra_badges.c accordingly.
Remove duplicate toolchain file generation for tg5040/tg5050.
The build container already provides CMAKE_TOOLCHAIN_FILE.
Keep underlying code intact for future use, but hide menu item
until feature is ready. Default remains OFF.
Group 7 related notification state variables into NotificationOverlay
struct for improved readability per PR feedback.
- Rename PLAT_findFileInDir to findFileInDir (now in utils)
- Remove duplicate static version from minarch.c (uses utils version
with improved best-match logic)
- Change LOG_info to LOG_debug for match logging (debugging info, not
user-facing)
- Update api.h, utils.h declarations
- Move gl_notification_surface to top with other static variables
- Add comment explaining why draw_rounded_rect is separate from
GFX_blitPill* functions
  (different rendering context: RGBA for GL overlay vs theme assets for
screen format)
@clintonium-119 clintonium-119 requested a review from frysee February 5, 2026 23:21
@clintonium-119
Copy link
Author

@frysee I'm sure I've missed (or misunderstood) something, but I've addressed what I could. Let me know if there's anything else you'd like to see,

And thanks for the thorough review and feedback. It's a good learning experience for me.

@frysee
Copy link
Member

frysee commented Feb 5, 2026

@frysee I'm sure I've missed (or misunderstood) something, but I've addressed what I could. Let me know if there's anything else you'd like to see,

And thanks for the thorough review and feedback. It's a good learning experience for me.

Thanks for taking your time and implementing changes! A lot of the things were stylistic choices, so no big deal in the first place.

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