@@ -168,6 +168,12 @@ + (void)enumerateAllPlaylistEntries:(PlaylistEntryBlock _Nonnull)block
168168 game.title = [NSString stringWithUTF8String: entry->label];
169169 game.fullPath = [NSString stringWithUTF8String: entry->path];
170170
171+ /* System/playlist display name (strip trailing ".lpl") */
172+ if ([playlistName.pathExtension.lowercaseString isEqualToString: @" lpl" ])
173+ game.system = playlistName.stringByDeletingPathExtension ;
174+ else
175+ game.system = playlistName;
176+
171177 /* Extract filename from path */
172178 const char *filename = path_basename (entry->path );
173179 game.filename = [NSString stringWithUTF8String: filename];
@@ -211,6 +217,59 @@ + (nullable RetroArchPlaylistGame *)findGameByFilename:(NSString * _Nonnull)file
211217 return nil ;
212218}
213219
220+ + (nullable NSData *)exportAllGamesAsJSONData
221+ {
222+ NSArray <RetroArchPlaylistGame *> *allGames = [self getAllGames ];
223+ NSMutableArray <NSDictionary *> *serialized =
224+ [[NSMutableArray alloc ] initWithCapacity: allGames.count];
225+
226+ for (RetroArchPlaylistGame *game in allGames) {
227+ NSMutableDictionary *dict = [[NSMutableDictionary alloc ] init ];
228+
229+ // "titleId" is the same <filename> used in the retroarch://game/<filename> launch scheme
230+ dict[@" titleId" ] = game.filename ?: @" " ;
231+ dict[@" titleName" ] = game.title ?: @" " ;
232+ dict[@" filename" ] = game.filename ?: @" " ;
233+ dict[@" gameId" ] = game.gameId ?: @" " ;
234+ dict[@" developer" ] = @" " ;
235+ dict[@" version" ] = @" " ;
236+ if (game.system )
237+ dict[@" system" ] = game.system ;
238+ if (game.coreName )
239+ dict[@" coreName" ] = game.coreName ;
240+
241+ [serialized addObject: dict];
242+ }
243+
244+ NSError *error = nil ;
245+ NSData *json = [NSJSONSerialization dataWithJSONObject: serialized
246+ options: 0
247+ error: &error];
248+ if (!json) {
249+ RARCH_WARN (" Failed to serialize game library: %s \n " ,
250+ [[error localizedDescription ] UTF8String ]);
251+ return nil ;
252+ }
253+
254+ return json;
255+ }
256+
257+ + (nullable NSString *)exportAllGamesAsBase64URLString
258+ {
259+ NSData *json = [self exportAllGamesAsJSONData ];
260+ if (!json)
261+ return nil ;
262+
263+ /* URL-safe base64 (base64url) without padding, matching the encoding other
264+ * front-ends use for their library callbacks. */
265+ NSString *encoded = [json base64EncodedStringWithOptions: 0 ];
266+ encoded = [encoded stringByReplacingOccurrencesOfString: @" +" withString: @" -" ];
267+ encoded = [encoded stringByReplacingOccurrencesOfString: @" /" withString: @" _" ];
268+ encoded = [encoded stringByReplacingOccurrencesOfString: @" =" withString: @" " ];
269+
270+ return encoded;
271+ }
272+
214273// Private helper method to extract games from a playlist
215274+ (NSArray <RetroArchPlaylistGame *> *)getGamesFromPlaylist : (playlist_t *)playlist
216275 withIdPrefix : (NSString *)idPrefix
0 commit comments