gemba 0.1.1 → 0.2.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (285) hide show
  1. checksums.yaml +4 -4
  2. data/THIRD_PARTY_NOTICES +37 -2
  3. data/assets/placeholder_boxart.png +0 -0
  4. data/bin/gemba +2 -2
  5. data/ext/gemba/extconf.rb +23 -1
  6. data/ext/gemba/gemba_ext.c +436 -2
  7. data/ext/gemba/gemba_ext.h +2 -0
  8. data/gemba.gemspec +5 -3
  9. data/lib/gemba/achievements/achievement.rb +23 -0
  10. data/lib/gemba/achievements/backend.rb +186 -0
  11. data/lib/gemba/achievements/cache.rb +70 -0
  12. data/lib/gemba/achievements/credentials_presenter.rb +142 -0
  13. data/lib/gemba/achievements/fake_backend.rb +205 -0
  14. data/lib/gemba/achievements/null_backend.rb +11 -0
  15. data/lib/gemba/achievements/offline_backend.rb +168 -0
  16. data/lib/gemba/achievements/retro_achievements/backend.rb +453 -0
  17. data/lib/gemba/achievements/retro_achievements/cli_sync_requester.rb +64 -0
  18. data/lib/gemba/achievements/retro_achievements/ping_worker.rb +27 -0
  19. data/lib/gemba/achievements.rb +19 -0
  20. data/lib/gemba/achievements_window.rb +556 -0
  21. data/lib/gemba/app_controller.rb +1015 -0
  22. data/lib/gemba/bios.rb +54 -0
  23. data/lib/gemba/boxart_fetcher/libretro_backend.rb +39 -0
  24. data/lib/gemba/boxart_fetcher/null_backend.rb +12 -0
  25. data/lib/gemba/boxart_fetcher.rb +79 -0
  26. data/lib/gemba/bus_emitter.rb +13 -0
  27. data/lib/gemba/child_window.rb +24 -1
  28. data/lib/gemba/cli/commands/config_cmd.rb +83 -0
  29. data/lib/gemba/cli/commands/decode.rb +154 -0
  30. data/lib/gemba/cli/commands/patch.rb +78 -0
  31. data/lib/gemba/cli/commands/play.rb +78 -0
  32. data/lib/gemba/cli/commands/record.rb +114 -0
  33. data/lib/gemba/cli/commands/replay.rb +161 -0
  34. data/lib/gemba/cli/commands/retro_achievements.rb +213 -0
  35. data/lib/gemba/cli/commands/version.rb +22 -0
  36. data/lib/gemba/cli.rb +52 -364
  37. data/lib/gemba/config.rb +134 -1
  38. data/lib/gemba/data/gb_games.json +1 -0
  39. data/lib/gemba/data/gb_md5.json +1 -0
  40. data/lib/gemba/data/gba_games.json +1 -0
  41. data/lib/gemba/data/gba_md5.json +1 -0
  42. data/lib/gemba/data/gbc_games.json +1 -0
  43. data/lib/gemba/data/gbc_md5.json +1 -0
  44. data/lib/gemba/emulator_frame.rb +1060 -0
  45. data/lib/gemba/event_bus.rb +48 -0
  46. data/lib/gemba/frame_stack.rb +60 -0
  47. data/lib/gemba/game_index.rb +84 -0
  48. data/lib/gemba/game_picker_frame.rb +268 -0
  49. data/lib/gemba/gamepad_map.rb +103 -0
  50. data/lib/gemba/headless.rb +6 -5
  51. data/lib/gemba/headless_player.rb +33 -3
  52. data/lib/gemba/help_window.rb +61 -0
  53. data/lib/gemba/hotkey_map.rb +3 -1
  54. data/lib/gemba/input_recorder.rb +107 -0
  55. data/lib/gemba/input_replayer.rb +119 -0
  56. data/lib/gemba/keyboard_map.rb +90 -0
  57. data/lib/gemba/locales/en.yml +97 -5
  58. data/lib/gemba/locales/ja.yml +97 -5
  59. data/lib/gemba/main_window.rb +56 -0
  60. data/lib/gemba/modal_stack.rb +81 -0
  61. data/lib/gemba/patcher_window.rb +223 -0
  62. data/lib/gemba/platform/gb.rb +21 -0
  63. data/lib/gemba/platform/gba.rb +21 -0
  64. data/lib/gemba/platform/gbc.rb +23 -0
  65. data/lib/gemba/platform.rb +20 -0
  66. data/lib/gemba/platform_open.rb +19 -0
  67. data/lib/gemba/recorder.rb +4 -3
  68. data/lib/gemba/replay_player.rb +691 -0
  69. data/lib/gemba/rom_info.rb +57 -0
  70. data/lib/gemba/rom_info_window.rb +16 -3
  71. data/lib/gemba/rom_library.rb +106 -0
  72. data/lib/gemba/rom_overrides.rb +47 -0
  73. data/lib/gemba/rom_patcher/bps.rb +161 -0
  74. data/lib/gemba/rom_patcher/ips.rb +101 -0
  75. data/lib/gemba/rom_patcher/ups.rb +118 -0
  76. data/lib/gemba/rom_patcher.rb +109 -0
  77. data/lib/gemba/{rom_loader.rb → rom_resolver.rb} +7 -6
  78. data/lib/gemba/runtime.rb +59 -26
  79. data/lib/gemba/save_state_manager.rb +4 -7
  80. data/lib/gemba/save_state_picker.rb +17 -4
  81. data/lib/gemba/session_logger.rb +64 -0
  82. data/lib/gemba/settings/audio_tab.rb +77 -0
  83. data/lib/gemba/settings/gamepad_tab.rb +351 -0
  84. data/lib/gemba/settings/hotkeys_tab.rb +259 -0
  85. data/lib/gemba/settings/paths.rb +11 -0
  86. data/lib/gemba/settings/recording_tab.rb +83 -0
  87. data/lib/gemba/settings/save_states_tab.rb +91 -0
  88. data/lib/gemba/settings/system_tab.rb +362 -0
  89. data/lib/gemba/settings/video_tab.rb +318 -0
  90. data/lib/gemba/settings_window.rb +162 -1036
  91. data/lib/gemba/version.rb +1 -1
  92. data/lib/gemba/virtual_keyboard.rb +19 -0
  93. data/lib/gemba.rb +2 -12
  94. data/test/achievements_window/test_bulk_sync.rb +218 -0
  95. data/test/achievements_window/test_bus_events.rb +125 -0
  96. data/test/achievements_window/test_close_confirmation.rb +201 -0
  97. data/test/achievements_window/test_initial_state.rb +164 -0
  98. data/test/achievements_window/test_sorting.rb +227 -0
  99. data/test/achievements_window/test_tree_rendering.rb +133 -0
  100. data/test/fixtures/fake_bios.bin +0 -0
  101. data/test/fixtures/pong.gba +0 -0
  102. data/test/fixtures/test.gb +0 -0
  103. data/test/fixtures/test.gbc +0 -0
  104. data/test/fixtures/test_quicksave.ss +0 -0
  105. data/test/screenshots/no_focus.png +0 -0
  106. data/test/shared/teek_test_worker.rb +17 -1
  107. data/test/shared/tk_test_helper.rb +91 -4
  108. data/test/support/achievements_window_helpers.rb +18 -0
  109. data/test/support/fake_core.rb +25 -0
  110. data/test/support/fake_ra_runtime.rb +74 -0
  111. data/test/support/fake_requester.rb +68 -0
  112. data/test/support/player_helpers.rb +20 -5
  113. data/test/test_achievement.rb +32 -0
  114. data/test/{test_player.rb → test_app_controller.rb} +353 -85
  115. data/test/test_bios.rb +123 -0
  116. data/test/test_boxart_fetcher.rb +150 -0
  117. data/test/test_cli.rb +17 -265
  118. data/test/test_cli_config.rb +64 -0
  119. data/test/test_cli_decode.rb +97 -0
  120. data/test/test_cli_patch.rb +58 -0
  121. data/test/test_cli_play.rb +213 -0
  122. data/test/test_cli_ra.rb +175 -0
  123. data/test/test_cli_record.rb +69 -0
  124. data/test/test_cli_replay.rb +72 -0
  125. data/test/test_cli_sync_requester.rb +152 -0
  126. data/test/test_cli_version.rb +27 -0
  127. data/test/test_config.rb +2 -3
  128. data/test/test_config_ra.rb +69 -0
  129. data/test/test_core.rb +62 -1
  130. data/test/test_credentials_presenter.rb +192 -0
  131. data/test/test_event_bus.rb +100 -0
  132. data/test/test_fake_backend_achievements.rb +130 -0
  133. data/test/test_fake_backend_auth.rb +68 -0
  134. data/test/test_game_index.rb +77 -0
  135. data/test/test_game_picker_frame.rb +310 -0
  136. data/test/test_gamepad_map.rb +1 -3
  137. data/test/test_headless_player.rb +17 -3
  138. data/test/test_help_window.rb +82 -0
  139. data/test/test_hotkey_map.rb +22 -1
  140. data/test/test_input_recorder.rb +179 -0
  141. data/test/test_input_replay_determinism.rb +113 -0
  142. data/test/test_input_replayer.rb +162 -0
  143. data/test/test_keyboard_map.rb +1 -3
  144. data/test/test_libretro_backend.rb +41 -0
  145. data/test/test_locale.rb +1 -1
  146. data/test/test_logging.rb +123 -0
  147. data/test/test_null_backend.rb +42 -0
  148. data/test/test_offline_backend.rb +116 -0
  149. data/test/test_overlay_renderer.rb +1 -1
  150. data/test/test_platform.rb +149 -0
  151. data/test/test_ra_backend.rb +313 -0
  152. data/test/test_ra_backend_unlock_gate.rb +56 -0
  153. data/test/test_recorder.rb +0 -3
  154. data/test/test_replay_player.rb +316 -0
  155. data/test/test_rom_info.rb +149 -0
  156. data/test/test_rom_overrides.rb +86 -0
  157. data/test/test_rom_patcher.rb +382 -0
  158. data/test/{test_rom_loader.rb → test_rom_resolver.rb} +25 -26
  159. data/test/test_save_state_manager.rb +2 -4
  160. data/test/test_settings_audio.rb +107 -0
  161. data/test/test_settings_hotkeys.rb +83 -66
  162. data/test/test_settings_recording.rb +49 -0
  163. data/test/test_settings_save_states.rb +97 -0
  164. data/test/test_settings_system.rb +133 -0
  165. data/test/test_settings_video.rb +450 -0
  166. data/test/test_settings_window.rb +76 -507
  167. data/test/test_tip_service.rb +6 -6
  168. data/test/test_toast_overlay.rb +1 -1
  169. data/test/test_virtual_events.rb +156 -0
  170. data/test/test_virtual_keyboard.rb +1 -1
  171. data/vendor/rcheevos/CHANGELOG.md +495 -0
  172. data/vendor/rcheevos/LICENSE +21 -0
  173. data/vendor/rcheevos/Package.swift +33 -0
  174. data/vendor/rcheevos/README.md +67 -0
  175. data/vendor/rcheevos/include/module.modulemap +70 -0
  176. data/vendor/rcheevos/include/rc_api_editor.h +296 -0
  177. data/vendor/rcheevos/include/rc_api_info.h +280 -0
  178. data/vendor/rcheevos/include/rc_api_request.h +77 -0
  179. data/vendor/rcheevos/include/rc_api_runtime.h +417 -0
  180. data/vendor/rcheevos/include/rc_api_user.h +262 -0
  181. data/vendor/rcheevos/include/rc_client.h +877 -0
  182. data/vendor/rcheevos/include/rc_client_raintegration.h +101 -0
  183. data/vendor/rcheevos/include/rc_consoles.h +138 -0
  184. data/vendor/rcheevos/include/rc_error.h +59 -0
  185. data/vendor/rcheevos/include/rc_export.h +100 -0
  186. data/vendor/rcheevos/include/rc_hash.h +200 -0
  187. data/vendor/rcheevos/include/rc_runtime.h +148 -0
  188. data/vendor/rcheevos/include/rc_runtime_types.h +452 -0
  189. data/vendor/rcheevos/include/rc_util.h +51 -0
  190. data/vendor/rcheevos/include/rcheevos.h +8 -0
  191. data/vendor/rcheevos/src/rapi/rc_api_common.c +1379 -0
  192. data/vendor/rcheevos/src/rapi/rc_api_common.h +88 -0
  193. data/vendor/rcheevos/src/rapi/rc_api_editor.c +625 -0
  194. data/vendor/rcheevos/src/rapi/rc_api_info.c +587 -0
  195. data/vendor/rcheevos/src/rapi/rc_api_runtime.c +901 -0
  196. data/vendor/rcheevos/src/rapi/rc_api_user.c +483 -0
  197. data/vendor/rcheevos/src/rc_client.c +6941 -0
  198. data/vendor/rcheevos/src/rc_client_external.c +281 -0
  199. data/vendor/rcheevos/src/rc_client_external.h +177 -0
  200. data/vendor/rcheevos/src/rc_client_external_versions.h +171 -0
  201. data/vendor/rcheevos/src/rc_client_internal.h +409 -0
  202. data/vendor/rcheevos/src/rc_client_raintegration.c +566 -0
  203. data/vendor/rcheevos/src/rc_client_raintegration_internal.h +61 -0
  204. data/vendor/rcheevos/src/rc_client_types.natvis +396 -0
  205. data/vendor/rcheevos/src/rc_compat.c +251 -0
  206. data/vendor/rcheevos/src/rc_compat.h +121 -0
  207. data/vendor/rcheevos/src/rc_libretro.c +915 -0
  208. data/vendor/rcheevos/src/rc_libretro.h +98 -0
  209. data/vendor/rcheevos/src/rc_util.c +199 -0
  210. data/vendor/rcheevos/src/rc_version.c +11 -0
  211. data/vendor/rcheevos/src/rc_version.h +32 -0
  212. data/vendor/rcheevos/src/rcheevos/alloc.c +312 -0
  213. data/vendor/rcheevos/src/rcheevos/condition.c +754 -0
  214. data/vendor/rcheevos/src/rcheevos/condset.c +777 -0
  215. data/vendor/rcheevos/src/rcheevos/consoleinfo.c +1215 -0
  216. data/vendor/rcheevos/src/rcheevos/format.c +330 -0
  217. data/vendor/rcheevos/src/rcheevos/lboard.c +287 -0
  218. data/vendor/rcheevos/src/rcheevos/memref.c +805 -0
  219. data/vendor/rcheevos/src/rcheevos/operand.c +607 -0
  220. data/vendor/rcheevos/src/rcheevos/rc_internal.h +390 -0
  221. data/vendor/rcheevos/src/rcheevos/rc_runtime_types.natvis +541 -0
  222. data/vendor/rcheevos/src/rcheevos/rc_validate.c +1406 -0
  223. data/vendor/rcheevos/src/rcheevos/rc_validate.h +18 -0
  224. data/vendor/rcheevos/src/rcheevos/richpresence.c +922 -0
  225. data/vendor/rcheevos/src/rcheevos/runtime.c +852 -0
  226. data/vendor/rcheevos/src/rcheevos/runtime_progress.c +1073 -0
  227. data/vendor/rcheevos/src/rcheevos/trigger.c +344 -0
  228. data/vendor/rcheevos/src/rcheevos/value.c +935 -0
  229. data/vendor/rcheevos/src/rhash/aes.c +480 -0
  230. data/vendor/rcheevos/src/rhash/aes.h +49 -0
  231. data/vendor/rcheevos/src/rhash/cdreader.c +838 -0
  232. data/vendor/rcheevos/src/rhash/hash.c +1402 -0
  233. data/vendor/rcheevos/src/rhash/hash_disc.c +1340 -0
  234. data/vendor/rcheevos/src/rhash/hash_encrypted.c +566 -0
  235. data/vendor/rcheevos/src/rhash/hash_rom.c +426 -0
  236. data/vendor/rcheevos/src/rhash/hash_zip.c +460 -0
  237. data/vendor/rcheevos/src/rhash/md5.c +382 -0
  238. data/vendor/rcheevos/src/rhash/md5.h +91 -0
  239. data/vendor/rcheevos/src/rhash/rc_hash_internal.h +116 -0
  240. data/vendor/rcheevos/test/libretro.h +205 -0
  241. data/vendor/rcheevos/test/rapi/test_rc_api_common.c +941 -0
  242. data/vendor/rcheevos/test/rapi/test_rc_api_editor.c +931 -0
  243. data/vendor/rcheevos/test/rapi/test_rc_api_info.c +545 -0
  244. data/vendor/rcheevos/test/rapi/test_rc_api_runtime.c +2213 -0
  245. data/vendor/rcheevos/test/rapi/test_rc_api_user.c +998 -0
  246. data/vendor/rcheevos/test/rcheevos/mock_memory.h +32 -0
  247. data/vendor/rcheevos/test/rcheevos/test_condition.c +570 -0
  248. data/vendor/rcheevos/test/rcheevos/test_condset.c +5170 -0
  249. data/vendor/rcheevos/test/rcheevos/test_consoleinfo.c +203 -0
  250. data/vendor/rcheevos/test/rcheevos/test_format.c +112 -0
  251. data/vendor/rcheevos/test/rcheevos/test_lboard.c +746 -0
  252. data/vendor/rcheevos/test/rcheevos/test_memref.c +520 -0
  253. data/vendor/rcheevos/test/rcheevos/test_operand.c +692 -0
  254. data/vendor/rcheevos/test/rcheevos/test_rc_validate.c +502 -0
  255. data/vendor/rcheevos/test/rcheevos/test_richpresence.c +1564 -0
  256. data/vendor/rcheevos/test/rcheevos/test_runtime.c +1667 -0
  257. data/vendor/rcheevos/test/rcheevos/test_runtime_progress.c +1821 -0
  258. data/vendor/rcheevos/test/rcheevos/test_timing.c +166 -0
  259. data/vendor/rcheevos/test/rcheevos/test_trigger.c +2521 -0
  260. data/vendor/rcheevos/test/rcheevos/test_value.c +870 -0
  261. data/vendor/rcheevos/test/rcheevos-test.sln +46 -0
  262. data/vendor/rcheevos/test/rcheevos-test.vcxproj +239 -0
  263. data/vendor/rcheevos/test/rcheevos-test.vcxproj.filters +335 -0
  264. data/vendor/rcheevos/test/rhash/data.c +657 -0
  265. data/vendor/rcheevos/test/rhash/data.h +32 -0
  266. data/vendor/rcheevos/test/rhash/mock_filereader.c +236 -0
  267. data/vendor/rcheevos/test/rhash/mock_filereader.h +31 -0
  268. data/vendor/rcheevos/test/rhash/test_cdreader.c +920 -0
  269. data/vendor/rcheevos/test/rhash/test_hash.c +310 -0
  270. data/vendor/rcheevos/test/rhash/test_hash_disc.c +1450 -0
  271. data/vendor/rcheevos/test/rhash/test_hash_rom.c +899 -0
  272. data/vendor/rcheevos/test/rhash/test_hash_zip.c +551 -0
  273. data/vendor/rcheevos/test/test.c +113 -0
  274. data/vendor/rcheevos/test/test_framework.h +205 -0
  275. data/vendor/rcheevos/test/test_rc_client.c +10509 -0
  276. data/vendor/rcheevos/test/test_rc_client_external.c +2197 -0
  277. data/vendor/rcheevos/test/test_rc_client_raintegration.c +441 -0
  278. data/vendor/rcheevos/test/test_rc_libretro.c +952 -0
  279. data/vendor/rcheevos/test/test_types.natvis +9 -0
  280. data/vendor/rcheevos/validator/validator.c +658 -0
  281. data/vendor/rcheevos/validator/validator.vcxproj +152 -0
  282. data/vendor/rcheevos/validator/validator.vcxproj.filters +82 -0
  283. metadata +274 -11
  284. data/lib/gemba/input_mappings.rb +0 -214
  285. data/lib/gemba/player.rb +0 -1525
@@ -0,0 +1,396 @@
1
+ <?xml version="1.0" encoding="utf-8"?>
2
+ <AutoVisualizer xmlns="http://schemas.microsoft.com/vstudio/debugger/natvis/2010">
3
+ <!-- https://learn.microsoft.com/en-us/visualstudio/debugger/create-custom-views-of-native-objects?view=vs-2022 -->
4
+ <!-- https://learn.microsoft.com/en-us/visualstudio/debugger/format-specifiers-in-cpp?view=vs-2022 -->
5
+ <Type Name="rc_client_user_t">
6
+ <DisplayString>{{display_name={display_name,s} score={score}}}</DisplayString>
7
+ </Type>
8
+ <Type Name="rc_client_game_t">
9
+ <DisplayString>{{title={title,s} id={id}}}</DisplayString>
10
+ </Type>
11
+ <Type Name="rc_client_subset_t">
12
+ <DisplayString>{{title={title,s} id={id}}}</DisplayString>
13
+ </Type>
14
+ <Type Name="__rc_client_achievement_state_enum_t">
15
+ <DisplayString Condition="value==RC_CLIENT_ACHIEVEMENT_STATE_INACTIVE">{RC_CLIENT_ACHIEVEMENT_STATE_INACTIVE}</DisplayString>
16
+ <DisplayString Condition="value==RC_CLIENT_ACHIEVEMENT_STATE_ACTIVE">{RC_CLIENT_ACHIEVEMENT_STATE_ACTIVE}</DisplayString>
17
+ <DisplayString Condition="value==RC_CLIENT_ACHIEVEMENT_STATE_UNLOCKED">{RC_CLIENT_ACHIEVEMENT_STATE_UNLOCKED}</DisplayString>
18
+ <DisplayString Condition="value==RC_CLIENT_ACHIEVEMENT_STATE_DISABLED">{RC_CLIENT_ACHIEVEMENT_STATE_DISABLED}</DisplayString>
19
+ <DisplayString>unknown ({value})</DisplayString>
20
+ </Type>
21
+ <Type Name="__rc_client_achievement_category_enum_t">
22
+ <DisplayString Condition="value==RC_CLIENT_ACHIEVEMENT_CATEGORY_NONE">{RC_CLIENT_ACHIEVEMENT_CATEGORY_NONE}</DisplayString>
23
+ <DisplayString Condition="value==RC_CLIENT_ACHIEVEMENT_CATEGORY_CORE">{RC_CLIENT_ACHIEVEMENT_CATEGORY_CORE}</DisplayString>
24
+ <DisplayString Condition="value==RC_CLIENT_ACHIEVEMENT_CATEGORY_UNOFFICIAL">{RC_CLIENT_ACHIEVEMENT_CATEGORY_UNOFFICIAL}</DisplayString>
25
+ <DisplayString Condition="value==RC_CLIENT_ACHIEVEMENT_CATEGORY_CORE_AND_UNOFFICIAL">{RC_CLIENT_ACHIEVEMENT_CATEGORY_CORE_AND_UNOFFICIAL}</DisplayString>
26
+ <DisplayString>unknown ({value})</DisplayString>
27
+ </Type>
28
+ <Type Name="__rc_client_achievement_type_enum_t">
29
+ <DisplayString Condition="value==RC_CLIENT_ACHIEVEMENT_TYPE_STANDARD">{RC_CLIENT_ACHIEVEMENT_TYPE_STANDARD}</DisplayString>
30
+ <DisplayString Condition="value==RC_CLIENT_ACHIEVEMENT_TYPE_MISSABLE">{RC_CLIENT_ACHIEVEMENT_TYPE_MISSABLE}</DisplayString>
31
+ <DisplayString Condition="value==RC_CLIENT_ACHIEVEMENT_TYPE_PROGRESSION">{RC_CLIENT_ACHIEVEMENT_TYPE_PROGRESSION}</DisplayString>
32
+ <DisplayString Condition="value==RC_CLIENT_ACHIEVEMENT_TYPE_WIN">{RC_CLIENT_ACHIEVEMENT_TYPE_WIN}</DisplayString>
33
+ <DisplayString>unknown ({value})</DisplayString>
34
+ </Type>
35
+ <Type Name="__rc_client_achievement_bucket_enum_t">
36
+ <DisplayString Condition="value==RC_CLIENT_ACHIEVEMENT_BUCKET_UNKNOWN">{RC_CLIENT_ACHIEVEMENT_BUCKET_UNKNOWN}</DisplayString>
37
+ <DisplayString Condition="value==RC_CLIENT_ACHIEVEMENT_BUCKET_LOCKED">{RC_CLIENT_ACHIEVEMENT_BUCKET_LOCKED}</DisplayString>
38
+ <DisplayString Condition="value==RC_CLIENT_ACHIEVEMENT_BUCKET_UNLOCKED">{RC_CLIENT_ACHIEVEMENT_BUCKET_UNLOCKED}</DisplayString>
39
+ <DisplayString Condition="value==RC_CLIENT_ACHIEVEMENT_BUCKET_UNSUPPORTED">{RC_CLIENT_ACHIEVEMENT_BUCKET_UNSUPPORTED}</DisplayString>
40
+ <DisplayString Condition="value==RC_CLIENT_ACHIEVEMENT_BUCKET_UNOFFICIAL">{RC_CLIENT_ACHIEVEMENT_BUCKET_UNOFFICIAL}</DisplayString>
41
+ <DisplayString Condition="value==RC_CLIENT_ACHIEVEMENT_BUCKET_RECENTLY_UNLOCKED">{RC_CLIENT_ACHIEVEMENT_BUCKET_RECENTLY_UNLOCKED}</DisplayString>
42
+ <DisplayString Condition="value==RC_CLIENT_ACHIEVEMENT_BUCKET_ACTIVE_CHALLENGE">{RC_CLIENT_ACHIEVEMENT_BUCKET_ACTIVE_CHALLENGE}</DisplayString>
43
+ <DisplayString Condition="value==RC_CLIENT_ACHIEVEMENT_BUCKET_UNSUPPORTED">{RC_CLIENT_ACHIEVEMENT_BUCKET_ALMOST_THERE}</DisplayString>
44
+ <DisplayString Condition="value==RC_CLIENT_ACHIEVEMENT_BUCKET_UNSYNCED">{RC_CLIENT_ACHIEVEMENT_BUCKET_UNSYNCED}</DisplayString>
45
+ <DisplayString>unknown ({value})</DisplayString>
46
+ </Type>
47
+ <Type Name="__rc_client_achievement_unlocked_enum_t">
48
+ <DisplayString Condition="value==RC_CLIENT_ACHIEVEMENT_UNLOCKED_NONE">{RC_CLIENT_ACHIEVEMENT_UNLOCKED_NONE}</DisplayString>
49
+ <DisplayString Condition="value==RC_CLIENT_ACHIEVEMENT_UNLOCKED_SOFTCORE">{RC_CLIENT_ACHIEVEMENT_UNLOCKED_SOFTCORE}</DisplayString>
50
+ <DisplayString Condition="value==RC_CLIENT_ACHIEVEMENT_UNLOCKED_HARDCORE">{RC_CLIENT_ACHIEVEMENT_UNLOCKED_HARDCORE}</DisplayString>
51
+ <DisplayString Condition="value==RC_CLIENT_ACHIEVEMENT_UNLOCKED_BOTH">{RC_CLIENT_ACHIEVEMENT_UNLOCKED_BOTH}</DisplayString>
52
+ <DisplayString>unknown ({value})</DisplayString>
53
+ </Type>
54
+ <Type Name="rc_client_achievement_t">
55
+ <DisplayString>{{title={title,s} id={id}}}</DisplayString>
56
+ <Expand>
57
+ <Item Name="title">title</Item>
58
+ <Item Name="description">description</Item>
59
+ <Item Name="points">points</Item>
60
+ <Item Name="id">id</Item>
61
+ <Item Name="state">*((__rc_client_achievement_state_enum_t*)&amp;state)</Item>
62
+ <Item Name="type">*((__rc_client_achievement_type_enum_t*)&amp;state)</Item>
63
+ <Item Name="category">*((__rc_client_achievement_category_enum_t*)&amp;category)</Item>
64
+ <Item Name="bucket">*((__rc_client_achievement_state_enum_t*)&amp;bucket)</Item>
65
+ <Item Name="unlocked">*((__rc_client_achievement_unlocked_enum_t*)&amp;unlocked)</Item>
66
+ </Expand>
67
+ </Type>
68
+ <Type Name="rc_client_achievement_bucket_t">
69
+ <DisplayString>{{label={label,s} count={num_achievements}}}</DisplayString>
70
+ <Expand>
71
+ <IndexListItems>
72
+ <Size>num_achievements</Size>
73
+ <ValueNode>achievements[$i]</ValueNode>
74
+ </IndexListItems>
75
+ </Expand>
76
+ </Type>
77
+ <Type Name="rc_client_achievement_list_t">
78
+ <DisplayString>{{count={num_buckets}}}</DisplayString>
79
+ <Expand>
80
+ <IndexListItems>
81
+ <Size>num_buckets</Size>
82
+ <ValueNode>buckets[$i]</ValueNode>
83
+ </IndexListItems>
84
+ </Expand>
85
+ </Type>
86
+ <Type Name="__rc_client_leaderboard_state_enum_t">
87
+ <DisplayString Condition="value==RC_CLIENT_LEADERBOARD_STATE_INACTIVE">{RC_CLIENT_LEADERBOARD_STATE_INACTIVE}</DisplayString>
88
+ <DisplayString Condition="value==RC_CLIENT_LEADERBOARD_STATE_ACTIVE">{RC_CLIENT_LEADERBOARD_STATE_ACTIVE}</DisplayString>
89
+ <DisplayString Condition="value==RC_CLIENT_LEADERBOARD_STATE_TRACKING">{RC_CLIENT_LEADERBOARD_STATE_TRACKING}</DisplayString>
90
+ <DisplayString Condition="value==RC_CLIENT_LEADERBOARD_STATE_DISABLED">{RC_CLIENT_LEADERBOARD_STATE_DISABLED}</DisplayString>
91
+ <DisplayString>unknown ({value})</DisplayString>
92
+ </Type>
93
+ <Type Name="__rc_client_leaderboard_format_enum_t">
94
+ <DisplayString Condition="value==RC_CLIENT_LEADERBOARD_FORMAT_TIME">{RC_CLIENT_LEADERBOARD_FORMAT_TIME}</DisplayString>
95
+ <DisplayString Condition="value==RC_CLIENT_LEADERBOARD_FORMAT_SCORE">{RC_CLIENT_LEADERBOARD_FORMAT_SCORE}</DisplayString>
96
+ <DisplayString Condition="value==RC_CLIENT_LEADERBOARD_FORMAT_VALUE">{RC_CLIENT_LEADERBOARD_FORMAT_VALUE}</DisplayString>
97
+ <DisplayString>unknown ({value})</DisplayString>
98
+ </Type>
99
+ <Type Name="rc_client_leaderboard_t">
100
+ <DisplayString>{{title={title,s} id={id}}}</DisplayString>
101
+ <Expand>
102
+ <Item Name="title">title</Item>
103
+ <Item Name="description">description</Item>
104
+ <Item Name="tracker_value">tracker_value</Item>
105
+ <Item Name="id">id</Item>
106
+ <Item Name="state">*((__rc_client_leaderboard_state_enum_t*)&amp;state)</Item>
107
+ <Item Name="format">*((__rc_client_leaderboard_format_enum_t*)&amp;format)</Item>
108
+ <Item Name="lower_is_better">*((__rc_bool_enum_t*)&amp;lower_is_better)</Item>
109
+ </Expand>
110
+ </Type>
111
+ <Type Name="rc_client_leaderboard_bucket_t">
112
+ <DisplayString>{{label={label,s} count={num_leaderboards}}}</DisplayString>
113
+ <Expand>
114
+ <IndexListItems>
115
+ <Size>num_leaderboards</Size>
116
+ <ValueNode>leaderboards[$i]</ValueNode>
117
+ </IndexListItems>
118
+ </Expand>
119
+ </Type>
120
+ <Type Name="rc_client_leaderboard_list_t">
121
+ <DisplayString>{{count={num_buckets}}}</DisplayString>
122
+ <Expand>
123
+ <IndexListItems>
124
+ <Size>num_buckets</Size>
125
+ <ValueNode>buckets[$i]</ValueNode>
126
+ </IndexListItems>
127
+ </Expand>
128
+ </Type>
129
+ <Type Name="rc_client_leaderboard_scoreboard_entry_t">
130
+ <DisplayString>{{rank={rank} score={score,s} username={username}}}</DisplayString>
131
+ </Type>
132
+ <Type Name="rc_client_leaderboard_scoreboard_t">
133
+ <DisplayString>{{leaderboard_id={leaderboard_id} num_entries={num_entries}}}</DisplayString>
134
+ <Expand>
135
+ <Item Name="leaderboard_id">leaderboard_id</Item>
136
+ <Item Name="submitted_score">submitted_score</Item>
137
+ <Item Name="best_score">best_score</Item>
138
+ <Item Name="new_rank">new_rank</Item>
139
+ <Item Name="num_entries">num_entries</Item>
140
+ <IndexListItems>
141
+ <Size>num_top_entries</Size>
142
+ <ValueNode>top_entries[$i]</ValueNode>
143
+ </IndexListItems>
144
+ </Expand>
145
+ </Type>
146
+ <Type Name="__rc_client_event_type_enum_t">
147
+ <DisplayString Condition="value==RC_CLIENT_EVENT_TYPE_NONE">{RC_CLIENT_EVENT_TYPE_NONE}</DisplayString>
148
+ <DisplayString Condition="value==RC_CLIENT_EVENT_ACHIEVEMENT_TRIGGERED">{RC_CLIENT_EVENT_ACHIEVEMENT_TRIGGERED}</DisplayString>
149
+ <DisplayString Condition="value==RC_CLIENT_EVENT_LEADERBOARD_STARTED">{RC_CLIENT_EVENT_LEADERBOARD_STARTED}</DisplayString>
150
+ <DisplayString Condition="value==RC_CLIENT_EVENT_LEADERBOARD_FAILED">{RC_CLIENT_EVENT_LEADERBOARD_FAILED}</DisplayString>
151
+ <DisplayString Condition="value==RC_CLIENT_EVENT_LEADERBOARD_SUBMITTED">{RC_CLIENT_EVENT_LEADERBOARD_SUBMITTED}</DisplayString>
152
+ <DisplayString Condition="value==RC_CLIENT_EVENT_ACHIEVEMENT_CHALLENGE_INDICATOR_SHOW">{RC_CLIENT_EVENT_ACHIEVEMENT_CHALLENGE_INDICATOR_SHOW}</DisplayString>
153
+ <DisplayString Condition="value==RC_CLIENT_EVENT_ACHIEVEMENT_CHALLENGE_INDICATOR_HIDE">{RC_CLIENT_EVENT_ACHIEVEMENT_CHALLENGE_INDICATOR_HIDE}</DisplayString>
154
+ <DisplayString Condition="value==RC_CLIENT_EVENT_ACHIEVEMENT_PROGRESS_INDICATOR_SHOW">{RC_CLIENT_EVENT_ACHIEVEMENT_PROGRESS_INDICATOR_SHOW}</DisplayString>
155
+ <DisplayString Condition="value==RC_CLIENT_EVENT_ACHIEVEMENT_PROGRESS_INDICATOR_HIDE">{RC_CLIENT_EVENT_ACHIEVEMENT_PROGRESS_INDICATOR_HIDE}</DisplayString>
156
+ <DisplayString Condition="value==RC_CLIENT_EVENT_ACHIEVEMENT_PROGRESS_INDICATOR_UPDATE">{RC_CLIENT_EVENT_ACHIEVEMENT_PROGRESS_INDICATOR_UPDATE}</DisplayString>
157
+ <DisplayString Condition="value==RC_CLIENT_EVENT_LEADERBOARD_TRACKER_SHOW">{RC_CLIENT_EVENT_LEADERBOARD_TRACKER_SHOW}</DisplayString>
158
+ <DisplayString Condition="value==RC_CLIENT_EVENT_LEADERBOARD_TRACKER_HIDE">{RC_CLIENT_EVENT_LEADERBOARD_TRACKER_HIDE}</DisplayString>
159
+ <DisplayString Condition="value==RC_CLIENT_EVENT_LEADERBOARD_TRACKER_UPDATE">{RC_CLIENT_EVENT_LEADERBOARD_TRACKER_UPDATE}</DisplayString>
160
+ <DisplayString Condition="value==RC_CLIENT_EVENT_LEADERBOARD_SCOREBOARD">{RC_CLIENT_EVENT_LEADERBOARD_SCOREBOARD}</DisplayString>
161
+ <DisplayString Condition="value==RC_CLIENT_EVENT_RESET">{RC_CLIENT_EVENT_RESET}</DisplayString>
162
+ <DisplayString Condition="value==RC_CLIENT_EVENT_GAME_COMPLETED">{RC_CLIENT_EVENT_GAME_COMPLETED}</DisplayString>
163
+ <DisplayString Condition="value==RC_CLIENT_EVENT_SERVER_ERROR">{RC_CLIENT_EVENT_SERVER_ERROR}</DisplayString>
164
+ <DisplayString Condition="value==RC_CLIENT_EVENT_DISCONNECTED">{RC_CLIENT_EVENT_DISCONNECTED}</DisplayString>
165
+ <DisplayString Condition="value==RC_CLIENT_EVENT_RECONNECTED">{RC_CLIENT_EVENT_RECONNECTED}</DisplayString>
166
+ <DisplayString Condition="value==RC_CLIENT_EVENT_SUBSET_COMPLETED">{RC_CLIENT_EVENT_SUBSET_COMPLETED}</DisplayString>
167
+ <DisplayString>unknown ({value})</DisplayString>
168
+ </Type>
169
+ <Type Name="rc_client_event_t">
170
+ <DisplayString>{{type={*((__rc_client_event_type_enum_t*)&amp;type)}}}</DisplayString>
171
+ <Expand>
172
+ <Item Name="type">*((__rc_client_event_type_enum_t*)&amp;type)</Item>
173
+ <Item Condition="type==RC_CLIENT_EVENT_ACHIEVEMENT_TRIGGERED" Name="achievement">*achievement</Item>
174
+ <Item Condition="type==RC_CLIENT_EVENT_LEADERBOARD_STARTED" Name="leaderboard">*leaderboard</Item>
175
+ <Item Condition="type==RC_CLIENT_EVENT_LEADERBOARD_FAILED" Name="leaderboard">*leaderboard</Item>
176
+ <Item Condition="type==RC_CLIENT_EVENT_LEADERBOARD_SUBMITTED" Name="leaderboard">*leaderboard</Item>
177
+ <Item Condition="type==RC_CLIENT_EVENT_ACHIEVEMENT_CHALLENGE_INDICATOR_SHOW" Name="achievement">*achievement</Item>
178
+ <Item Condition="type==RC_CLIENT_EVENT_ACHIEVEMENT_CHALLENGE_INDICATOR_HIDE" Name="achievement">*achievement</Item>
179
+ <Item Condition="type==RC_CLIENT_EVENT_ACHIEVEMENT_PROGRESS_INDICATOR_SHOW" Name="achievement">*achievement</Item>
180
+ <Item Condition="type==RC_CLIENT_EVENT_ACHIEVEMENT_PROGRESS_INDICATOR_HIDE" Name="achievement">*achievement</Item>
181
+ <Item Condition="type==RC_CLIENT_EVENT_ACHIEVEMENT_PROGRESS_INDICATOR_UPDATE" Name="achievement">*achievement</Item>
182
+ <Item Condition="type==RC_CLIENT_EVENT_LEADERBOARD_TRACKER_SHOW" Name="leaderboard_tracker">*leaderboard_tracker</Item>
183
+ <Item Condition="type==RC_CLIENT_EVENT_LEADERBOARD_TRACKER_HIDE" Name="leaderboard_tracker">*leaderboard_tracker</Item>
184
+ <Item Condition="type==RC_CLIENT_EVENT_LEADERBOARD_TRACKER_UPDATE" Name="leaderboard_tracker">*leaderboard_tracker</Item>
185
+ <Item Condition="type==RC_CLIENT_EVENT_LEADERBOARD_SCOREBOARD" Name="leaderboard_scoreboard">*leaderboard_scoreboard</Item>
186
+ <Item Condition="type==RC_CLIENT_EVENT_LEADERBOARD_SCOREBOARD" Name="leaderboard">*leaderboard</Item>
187
+ <Item Condition="type==RC_CLIENT_EVENT_SERVER_ERROR" Name="server_error">*server_error</Item>
188
+ <Item Condition="type==RC_CLIENT_EVENT_SUBSET_COMPLETED" Name="subset">*subset</Item>
189
+ </Expand>
190
+ </Type>
191
+ <Type Name="__rc_client_subset_info_achievements_list_t">
192
+ <DisplayString>{{count={info.public_.num_achievements}}}</DisplayString>
193
+ <Expand>
194
+ <IndexListItems>
195
+ <Size>info.public_.num_achievements</Size>
196
+ <ValueNode>info.achievements[$i]</ValueNode>
197
+ </IndexListItems>
198
+ </Expand>
199
+ </Type>
200
+ <Type Name="__rc_client_subset_info_leaderboards_list_t">
201
+ <DisplayString>{{count={info.public_.num_leaderboards}}}</DisplayString>
202
+ <Expand>
203
+ <IndexListItems>
204
+ <Size>info.public_.num_leaderboards</Size>
205
+ <ValueNode>info.leaderboards[$i]</ValueNode>
206
+ </IndexListItems>
207
+ </Expand>
208
+ </Type>
209
+ <Type Name="__rc_client_mastery_state_enum_t">
210
+ <DisplayString Condition="value==RC_CLIENT_MASTERY_STATE_NONE">{RC_CLIENT_MASTERY_STATE_NONE}</DisplayString>
211
+ <DisplayString Condition="value==RC_CLIENT_MASTERY_STATE_PENDING">{RC_CLIENT_MASTERY_STATE_PENDING}</DisplayString>
212
+ <DisplayString Condition="value==RC_CLIENT_MASTERY_STATE_SHOWN">{RC_CLIENT_MASTERY_STATE_SHOWN}</DisplayString>
213
+ <DisplayString>unknown ({value})</DisplayString>
214
+ </Type>
215
+ <Type Name="rc_client_subset_info_t">
216
+ <DisplayString>{{title={public_.title,s} id={public_.id}}}</DisplayString>
217
+ <Expand>
218
+ <Item Name="public_">public_</Item>
219
+ <Item Name="active">*((__rc_bool_enum_t*)&amp;active)</Item>
220
+ <Item Name="mastery">*((__rc_client_mastery_state_enum_t*)&amp;mastery)</Item>
221
+ <Item Name="achievements">*((__rc_client_subset_info_achievements_list_t*)this)</Item>
222
+ <Item Name="leaderboards">*((__rc_client_subset_info_leaderboards_list_t*)this)</Item>
223
+ </Expand>
224
+ </Type>
225
+ <Type Name="__rc_client_leaderboard_tracker_list_t">
226
+ <DisplayString Condition="first==0">{{NULL}}</DisplayString>
227
+ <DisplayString>{(void**)&amp;first,na}</DisplayString>
228
+ <Expand>
229
+ <LinkedListItems>
230
+ <HeadPointer>first</HeadPointer>
231
+ <NextPointer>next</NextPointer>
232
+ <ValueNode>this</ValueNode>
233
+ </LinkedListItems>
234
+ </Expand>
235
+ </Type>
236
+ <Type Name="__rc_client_subset_info_list_t">
237
+ <DisplayString Condition="first==0">{{NULL}}</DisplayString>
238
+ <DisplayString>{(void**)&amp;first,na}</DisplayString>
239
+ <Expand>
240
+ <LinkedListItems>
241
+ <HeadPointer>first</HeadPointer>
242
+ <NextPointer>next</NextPointer>
243
+ <ValueNode>this</ValueNode>
244
+ </LinkedListItems>
245
+ </Expand>
246
+ </Type>
247
+ <Type Name="__rc_client_media_hash_list_t">
248
+ <DisplayString Condition="first==0">{{NULL}}</DisplayString>
249
+ <DisplayString>{(void**)&amp;first,na}</DisplayString>
250
+ <Expand>
251
+ <LinkedListItems>
252
+ <HeadPointer>first</HeadPointer>
253
+ <NextPointer>next</NextPointer>
254
+ <ValueNode>this</ValueNode>
255
+ </LinkedListItems>
256
+ </Expand>
257
+ </Type>
258
+ <Type Name="rc_client_achievement_info_t">
259
+ <DisplayString>{{title={public_.title,s} id={public_.id}}}</DisplayString>
260
+ </Type>
261
+ <Type Name="rc_client_leaderboard_info_t">
262
+ <DisplayString>{{title={public_.title,s} id={public_.id}}}</DisplayString>
263
+ </Type>
264
+ <Type Name="rc_client_game_info_t">
265
+ <DisplayString>{{title={public_.title,s} id={public_.id}}}</DisplayString>
266
+ <Expand>
267
+ <Item Name="public_">public_</Item>
268
+ <Item Name="subsets">*((__rc_client_subset_info_list_t*)&amp;subsets)</Item>
269
+ <Item Name="media_hash">*((__rc_client_media_hash_list_t*)&amp;media_hash)</Item>
270
+ <Item Name="leaderboard_trackers">*((__rc_client_leaderboard_tracker_list_t*)&amp;leaderboard_trackers)</Item>
271
+ <Item Name="progress_tracker">progress_tracker</Item>
272
+ <Item Name="runtime">runtime</Item>
273
+ </Expand>
274
+ </Type>
275
+ <Type Name="rc_client_game_hash_t">
276
+ <DisplayString>{{hash={hash,s} game_id={game_id}}}</DisplayString>
277
+ </Type>
278
+ <Type Name="__rc_client_game_hash_list_t">
279
+ <DisplayString>{client.hashes}</DisplayString>
280
+ <Expand>
281
+ <LinkedListItems>
282
+ <HeadPointer>client.hashes</HeadPointer>
283
+ <NextPointer>next</NextPointer>
284
+ <ValueNode>*this</ValueNode>
285
+ </LinkedListItems>
286
+ </Expand>
287
+ </Type>
288
+ <Type Name="__rc_client_load_game_state_enum_t">
289
+ <DisplayString Condition="value==RC_CLIENT_LOAD_GAME_STATE_NONE">{RC_CLIENT_LOAD_GAME_STATE_NONE}</DisplayString>
290
+ <DisplayString Condition="value==RC_CLIENT_LOAD_GAME_STATE_IDENTIFYING_GAME">{RC_CLIENT_LOAD_GAME_STATE_IDENTIFYING_GAME}</DisplayString>
291
+ <DisplayString Condition="value==RC_CLIENT_LOAD_GAME_STATE_AWAIT_LOGIN">{RC_CLIENT_LOAD_GAME_STATE_AWAIT_LOGIN}</DisplayString>
292
+ <DisplayString Condition="value==RC_CLIENT_LOAD_GAME_STATE_STARTING_SESSION">{RC_CLIENT_LOAD_GAME_STATE_STARTING_SESSION}</DisplayString>
293
+ <DisplayString Condition="value==RC_CLIENT_LOAD_GAME_STATE_DONE">{RC_CLIENT_LOAD_GAME_STATE_DONE}</DisplayString>
294
+ <DisplayString Condition="value==RC_CLIENT_LOAD_GAME_STATE_ABORTED">{RC_CLIENT_LOAD_GAME_STATE_ABORTED}</DisplayString>
295
+ <DisplayString>unknown ({value})</DisplayString>
296
+ </Type>
297
+ <Type Name="rc_client_load_state_t">
298
+ <Expand>
299
+ <Item Name="progress">*((__rc_client_load_game_state_enum_t*)&amp;progress)</Item>
300
+ <Item Name="game">*game</Item>
301
+ <Item Name="subset">subset</Item>
302
+ <Item Name="hash">*hash</Item>
303
+ <Item Name="pending_media">pending_media</Item>
304
+ <Item Name="start_session_response">start_session_response</Item>
305
+ <Item Name="outstanding_requests">(int)outstanding_requests</Item>
306
+ </Expand>
307
+ </Type>
308
+ <Type Name="rc_client_scheduled_callback_data_t">
309
+ <DisplayString>{{when={when} callback={callback,na}}}</DisplayString>
310
+ </Type>
311
+ <Type Name="__rc_client_scheduled_callback_list_t">
312
+ <DisplayString>{state.scheduled_callbacks}</DisplayString>
313
+ <Expand>
314
+ <LinkedListItems>
315
+ <HeadPointer>state.scheduled_callbacks</HeadPointer>
316
+ <NextPointer>next</NextPointer>
317
+ <ValueNode>*this</ValueNode>
318
+ </LinkedListItems>
319
+ </Expand>
320
+ </Type>
321
+ <Type Name="__rc_client_log_level_enum_t">
322
+ <DisplayString Condition="value==RC_CLIENT_LOG_LEVEL_NONE">{RC_CLIENT_LOG_LEVEL_NONE}</DisplayString>
323
+ <DisplayString Condition="value==RC_CLIENT_LOG_LEVEL_ERROR">{RC_CLIENT_LOG_LEVEL_ERROR}</DisplayString>
324
+ <DisplayString Condition="value==RC_CLIENT_LOG_LEVEL_WARN">{RC_CLIENT_LOG_LEVEL_WARN}</DisplayString>
325
+ <DisplayString Condition="value==RC_CLIENT_LOG_LEVEL_INFO">{RC_CLIENT_LOG_LEVEL_INFO}</DisplayString>
326
+ <DisplayString Condition="value==RC_CLIENT_LOG_LEVEL_VERBOSE">{RC_CLIENT_LOG_LEVEL_VERBOSE}</DisplayString>
327
+ <DisplayString>unknown ({value})</DisplayString>
328
+ </Type>
329
+ <Type Name="__rc_client_user_state_enum_t">
330
+ <DisplayString Condition="value==RC_CLIENT_USER_STATE_NONE">{RC_CLIENT_USER_STATE_NONE}</DisplayString>
331
+ <DisplayString Condition="value==RC_CLIENT_USER_STATE_LOGIN_REQUESTED">{RC_CLIENT_USER_STATE_LOGIN_REQUESTED}</DisplayString>
332
+ <DisplayString Condition="value==RC_CLIENT_USER_STATE_LOGGED_IN">{RC_CLIENT_USER_STATE_LOGGED_IN}</DisplayString>
333
+ <DisplayString>unknown ({value})</DisplayString>
334
+ </Type>
335
+ <Type Name="__rc_client_spectator_mode_enum_t">
336
+ <DisplayString Condition="value==RC_CLIENT_SPECTATOR_MODE_OFF">{RC_CLIENT_SPECTATOR_MODE_OFF}</DisplayString>
337
+ <DisplayString Condition="value==RC_CLIENT_SPECTATOR_MODE_ON">{RC_CLIENT_SPECTATOR_MODE_ON}</DisplayString>
338
+ <DisplayString Condition="value==RC_CLIENT_SPECTATOR_MODE_LOCKED">{RC_CLIENT_SPECTATOR_MODE_LOCKED}</DisplayString>
339
+ <DisplayString>unknown ({value})</DisplayString>
340
+ </Type>
341
+ <Type Name="__rc_client_disconnect_enum_t">
342
+ <DisplayString Condition="value==RC_CLIENT_DISCONNECT_HIDDEN">{RC_CLIENT_DISCONNECT_HIDDEN}</DisplayString>
343
+ <DisplayString Condition="value==RC_CLIENT_DISCONNECT_VISIBLE">{RC_CLIENT_DISCONNECT_VISIBLE}</DisplayString>
344
+ <DisplayString Condition="value==RC_CLIENT_DISCONNECT_SHOW_PENDING">{RC_CLIENT_DISCONNECT_SHOW_PENDING}</DisplayString>
345
+ <DisplayString Condition="value==RC_CLIENT_DISCONNECT_HIDE_PENDING">{RC_CLIENT_DISCONNECT_HIDE_PENDING}</DisplayString>
346
+ <DisplayString Condition="value==RC_CLIENT_DISCONNECT_VISIBLE|RC_CLIENT_DISCONNECT_HIDE_PENDING">{RC_CLIENT_DISCONNECT_VISIBLE|RC_CLIENT_DISCONNECT_HIDE_PENDING}</DisplayString>
347
+ <DisplayString>unknown ({value})</DisplayString>
348
+ </Type>
349
+ <Type Name="rc_client_state_t">
350
+ <Expand>
351
+ <Item Name="hardcore">*((__rc_bool_enum_t*)&amp;hardcore)</Item>
352
+ <Item Name="unofficial_enabled">*((__rc_bool_enum_t*)&amp;unofficial_enabled)</Item>
353
+ <Item Name="encore_mode">*((__rc_bool_enum_t*)&amp;encore_mode)</Item>
354
+ <Item Name="spectator_mode">*((__rc_client_spectator_mode_enum_t*)&amp;spectator_mode)</Item>
355
+ <Item Name="disconnect">*((__rc_client_disconnect_enum_t*)&amp;disconnect)</Item>
356
+ <Item Name="log_level">*((__rc_client_log_level_enum_t*)&amp;log_level)</Item>
357
+ <Item Name="user">*((__rc_client_user_state_enum_t*)&amp;user)</Item>
358
+ <Item Name="scheduled_callbacks">*((__rc_client_scheduled_callback_list_t*)this)</Item>
359
+ <Item Name="host">host</Item>
360
+ <Item Name="load">load</Item>
361
+ </Expand>
362
+ </Type>
363
+ <Type Name="rc_client_t">
364
+ <Expand>
365
+ <Item Name="game">game</Item>
366
+ <Item Name="hashes">*((__rc_client_game_hash_list_t*)this)</Item>
367
+ <Item Name="user">user</Item>
368
+ <Item Name="callbacks">callbacks</Item>
369
+ <Item Name="state">state</Item>
370
+ </Expand>
371
+ </Type>
372
+ <Type Name="rc_client_raintegration_menu_t">
373
+ <DisplayString>{{count={num_items}}}</DisplayString>
374
+ <Expand>
375
+ <IndexListItems>
376
+ <Size>num_items</Size>
377
+ <ValueNode>items[$i]</ValueNode>
378
+ </IndexListItems>
379
+ </Expand>
380
+ </Type>
381
+ <Type Name="__rc_client_raintegration_event_enum_t">
382
+ <DisplayString Condition="value==RC_CLIENT_RAINTEGRATION_EVENT_TYPE_NONE">{RC_CLIENT_RAINTEGRATION_EVENT_TYPE_NONE}</DisplayString>
383
+ <DisplayString Condition="value==RC_CLIENT_RAINTEGRATION_EVENT_MENUITEM_CHECKED_CHANGED">{RC_CLIENT_RAINTEGRATION_EVENT_MENUITEM_CHECKED_CHANGED}</DisplayString>
384
+ <DisplayString Condition="value==RC_CLIENT_RAINTEGRATION_EVENT_HARDCORE_CHANGED">{RC_CLIENT_RAINTEGRATION_EVENT_HARDCORE_CHANGED}</DisplayString>
385
+ <DisplayString Condition="value==RC_CLIENT_RAINTEGRATION_EVENT_PAUSE">{RC_CLIENT_RAINTEGRATION_EVENT_PAUSE}</DisplayString>
386
+ <DisplayString Condition="value==RC_CLIENT_RAINTEGRATION_EVENT_MENU_CHANGED">{RC_CLIENT_RAINTEGRATION_EVENT_MENU_CHANGED}</DisplayString>
387
+ <DisplayString>unknown ({value})</DisplayString>
388
+ </Type>
389
+ <Type Name="rc_client_raintegration_event_t">
390
+ <DisplayString>{{type={*((__rc_client_raintegration_event_enum_t*)&amp;type)}}}</DisplayString>
391
+ <Expand>
392
+ <Item Name="type">*((__rc_client_raintegration_event_enum_t*)&amp;type)</Item>
393
+ <Item Condition="type==RC_CLIENT_RAINTEGRATION_EVENT_MENUITEM_CHECKED_CHANGED" Name="menu_item">menu_item</Item>
394
+ </Expand>
395
+ </Type>
396
+ </AutoVisualizer>
@@ -0,0 +1,251 @@
1
+ #if !defined(RC_NO_THREADS) && !defined(_WIN32) && !defined(GEKKO) && !defined(_3DS) && (!defined(_XOPEN_SOURCE) || (_XOPEN_SOURCE - 0) < 500)
2
+ /* We'll want to use pthread_mutexattr_settype/PTHREAD_MUTEX_RECURSIVE, but glibc only conditionally exposes pthread_mutexattr_settype and PTHREAD_MUTEX_RECURSIVE depending on feature flags
3
+ * Defining _XOPEN_SOURCE must be done at the top of the source file, before including any headers
4
+ * pthread_mutexattr_settype/PTHREAD_MUTEX_RECURSIVE are specified the Single UNIX Specification (Version 2, 1997), along with POSIX later on (IEEE Standard 1003.1-2008), so should cover practically any pthread implementation
5
+ */
6
+ #undef _XOPEN_SOURCE
7
+ #define _XOPEN_SOURCE 500
8
+ #endif
9
+
10
+ #include "rc_compat.h"
11
+
12
+ #include <assert.h>
13
+ #include <ctype.h>
14
+ #include <stdarg.h>
15
+
16
+ #ifdef RC_C89_HELPERS
17
+
18
+ int rc_strncasecmp(const char* left, const char* right, size_t length)
19
+ {
20
+ while (length)
21
+ {
22
+ if (*left != *right)
23
+ {
24
+ const int diff = tolower(*left) - tolower(*right);
25
+ if (diff != 0)
26
+ return diff;
27
+ }
28
+
29
+ ++left;
30
+ ++right;
31
+ --length;
32
+ }
33
+
34
+ return 0;
35
+ }
36
+
37
+ int rc_strcasecmp(const char* left, const char* right)
38
+ {
39
+ while (*left || *right)
40
+ {
41
+ if (*left != *right)
42
+ {
43
+ const int diff = tolower(*left) - tolower(*right);
44
+ if (diff != 0)
45
+ return diff;
46
+ }
47
+
48
+ ++left;
49
+ ++right;
50
+ }
51
+
52
+ return 0;
53
+ }
54
+
55
+ char* rc_strdup(const char* str)
56
+ {
57
+ const size_t length = strlen(str);
58
+ char* buffer = (char*)malloc(length + 1);
59
+ if (buffer)
60
+ memcpy(buffer, str, length + 1);
61
+ return buffer;
62
+ }
63
+
64
+ int rc_snprintf(char* buffer, size_t size, const char* format, ...)
65
+ {
66
+ int result;
67
+ va_list args;
68
+
69
+ va_start(args, format);
70
+
71
+ #ifdef __STDC_SECURE_LIB__
72
+ result = vsprintf_s(buffer, size, format, args);
73
+ #else
74
+ /* assume buffer is large enough and ignore size */
75
+ (void)size;
76
+ result = vsprintf(buffer, format, args);
77
+ #endif
78
+
79
+ va_end(args);
80
+
81
+ return result;
82
+ }
83
+
84
+ #endif
85
+
86
+ #ifndef __STDC_SECURE_LIB__
87
+
88
+ struct tm* rc_gmtime_s(struct tm* buf, const time_t* timer)
89
+ {
90
+ struct tm* tm = gmtime(timer);
91
+ memcpy(buf, tm, sizeof(*tm));
92
+ return buf;
93
+ }
94
+
95
+ #endif
96
+
97
+ #ifndef RC_NO_THREADS
98
+
99
+ #if defined(_WIN32)
100
+
101
+ /* https://learn.microsoft.com/en-us/archive/msdn-magazine/2012/november/windows-with-c-the-evolution-of-synchronization-in-windows-and-c */
102
+ /* implementation largely taken from https://github.com/libsdl-org/SDL/blob/0fc3574/src/thread/windows/SDL_sysmutex.c */
103
+
104
+ #if defined(WINVER) && WINVER >= 0x0600
105
+
106
+ void rc_mutex_init(rc_mutex_t* mutex)
107
+ {
108
+ InitializeSRWLock(&mutex->srw_lock);
109
+ /* https://learn.microsoft.com/en-us/windows/win32/procthread/thread-handles-and-identifiers */
110
+ /* thread ids are never 0 */
111
+ mutex->owner = 0;
112
+ mutex->count = 0;
113
+ }
114
+
115
+ void rc_mutex_destroy(rc_mutex_t* mutex)
116
+ {
117
+ /* Nothing to do here */
118
+ (void)mutex;
119
+ }
120
+
121
+ void rc_mutex_lock(rc_mutex_t* mutex)
122
+ {
123
+ DWORD current_thread = GetCurrentThreadId();
124
+ if (mutex->owner == current_thread) {
125
+ ++mutex->count;
126
+ assert(mutex->count > 0);
127
+ }
128
+ else {
129
+ AcquireSRWLockExclusive(&mutex->srw_lock);
130
+ assert(mutex->owner == 0 && mutex->count == 0);
131
+ mutex->owner = current_thread;
132
+ mutex->count = 1;
133
+ }
134
+ }
135
+
136
+ void rc_mutex_unlock(rc_mutex_t* mutex)
137
+ {
138
+ if (mutex->owner == GetCurrentThreadId()) {
139
+ assert(mutex->count > 0);
140
+ if (--mutex->count == 0) {
141
+ mutex->owner = 0;
142
+ ReleaseSRWLockExclusive(&mutex->srw_lock);
143
+ }
144
+ }
145
+ else {
146
+ assert(!"Tried to unlock unowned mutex");
147
+ }
148
+ }
149
+
150
+ #else
151
+
152
+ void rc_mutex_init(rc_mutex_t* mutex)
153
+ {
154
+ InitializeCriticalSection(&mutex->critical_section);
155
+ }
156
+
157
+ void rc_mutex_destroy(rc_mutex_t* mutex)
158
+ {
159
+ DeleteCriticalSection(&mutex->critical_section);
160
+ }
161
+
162
+ void rc_mutex_lock(rc_mutex_t* mutex)
163
+ {
164
+ EnterCriticalSection(&mutex->critical_section);
165
+ }
166
+
167
+ void rc_mutex_unlock(rc_mutex_t* mutex)
168
+ {
169
+ LeaveCriticalSection(&mutex->critical_section);
170
+ }
171
+
172
+ #endif
173
+
174
+ #elif defined(GEKKO)
175
+
176
+ /* https://github.com/libretro/RetroArch/pull/16116 */
177
+
178
+ void rc_mutex_init(rc_mutex_t* mutex)
179
+ {
180
+ /* LWP_MutexInit has the handle passed by reference */
181
+ /* Other LWP_Mutex* calls have the handle passed by value */
182
+ LWP_MutexInit(&mutex->handle, 1);
183
+ }
184
+
185
+ void rc_mutex_destroy(rc_mutex_t* mutex)
186
+ {
187
+ LWP_MutexDestroy(mutex->handle);
188
+ }
189
+
190
+ void rc_mutex_lock(rc_mutex_t* mutex)
191
+ {
192
+ LWP_MutexLock(mutex->handle);
193
+ }
194
+
195
+ void rc_mutex_unlock(rc_mutex_t* mutex)
196
+ {
197
+ LWP_MutexUnlock(mutex->handle);
198
+ }
199
+
200
+ #elif defined(_3DS)
201
+
202
+ void rc_mutex_init(rc_mutex_t* mutex)
203
+ {
204
+ RecursiveLock_Init(mutex);
205
+ }
206
+
207
+ void rc_mutex_destroy(rc_mutex_t* mutex)
208
+ {
209
+ /* Nothing to do here */
210
+ (void)mutex;
211
+ }
212
+
213
+ void rc_mutex_lock(rc_mutex_t* mutex)
214
+ {
215
+ RecursiveLock_Lock(mutex);
216
+ }
217
+
218
+ void rc_mutex_unlock(rc_mutex_t* mutex)
219
+ {
220
+ RecursiveLock_Unlock(mutex);
221
+ }
222
+
223
+ #else
224
+
225
+ void rc_mutex_init(rc_mutex_t* mutex)
226
+ {
227
+ /* Define the mutex as recursive, for consistent semantics against other rc_mutex_t implementations */
228
+ pthread_mutexattr_t attr;
229
+ pthread_mutexattr_init(&attr);
230
+ pthread_mutexattr_settype(&attr, PTHREAD_MUTEX_RECURSIVE);
231
+ pthread_mutex_init(mutex, &attr);
232
+ pthread_mutexattr_destroy(&attr);
233
+ }
234
+
235
+ void rc_mutex_destroy(rc_mutex_t* mutex)
236
+ {
237
+ pthread_mutex_destroy(mutex);
238
+ }
239
+
240
+ void rc_mutex_lock(rc_mutex_t* mutex)
241
+ {
242
+ pthread_mutex_lock(mutex);
243
+ }
244
+
245
+ void rc_mutex_unlock(rc_mutex_t* mutex)
246
+ {
247
+ pthread_mutex_unlock(mutex);
248
+ }
249
+
250
+ #endif
251
+ #endif /* RC_NO_THREADS */