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,1821 @@
1
+ #include "rc_runtime.h"
2
+ #include "rc_internal.h"
3
+
4
+ #include "../test_framework.h"
5
+ #include "../rhash/md5.h"
6
+ #include "mock_memory.h"
7
+
8
+ static void _assert_activate_achievement(rc_runtime_t* runtime, uint32_t id, const char* memaddr)
9
+ {
10
+ int result = rc_runtime_activate_achievement(runtime, id, memaddr, NULL, 0);
11
+ ASSERT_NUM_EQUALS(result, RC_OK);
12
+ }
13
+ #define assert_activate_achievement(runtime, id, memaddr) ASSERT_HELPER(_assert_activate_achievement(runtime, id, memaddr), "assert_activate_achievement")
14
+
15
+ static void _assert_activate_leaderboard(rc_runtime_t* runtime, uint32_t id, const char* script)
16
+ {
17
+ int result = rc_runtime_activate_lboard(runtime, id, script, NULL, 0);
18
+ ASSERT_NUM_EQUALS(result, RC_OK);
19
+ }
20
+ #define assert_activate_leaderboard(runtime, id, script) ASSERT_HELPER(_assert_activate_leaderboard(runtime, id, script), "assert_activate_leaderboard")
21
+
22
+ static void _assert_activate_rich_presence(rc_runtime_t* runtime, const char* script)
23
+ {
24
+ int result = rc_runtime_activate_richpresence(runtime, script, NULL, 0);
25
+ ASSERT_NUM_EQUALS(result, RC_OK);
26
+ }
27
+ #define assert_activate_rich_presence(runtime, script) ASSERT_HELPER(_assert_activate_rich_presence(runtime, script), "assert_activate_rich_presence")
28
+
29
+ static void _assert_richpresence_output(rc_runtime_t* runtime, memory_t* memory, const char* expected_display_string) {
30
+ char output[256];
31
+ int result;
32
+
33
+ result = rc_runtime_get_richpresence(runtime, output, sizeof(output), peek, memory, NULL);
34
+ ASSERT_STR_EQUALS(output, expected_display_string);
35
+ ASSERT_NUM_EQUALS(result, strlen(expected_display_string));
36
+ }
37
+ #define assert_richpresence_output(runtime, memory, expected_display_string) ASSERT_HELPER(_assert_richpresence_output(runtime, memory, expected_display_string), "assert_richpresence_output")
38
+
39
+ static void event_handler(const rc_runtime_event_t* e)
40
+ {
41
+ (void)e;
42
+ }
43
+
44
+ static void assert_do_frame(rc_runtime_t* runtime, memory_t* memory)
45
+ {
46
+ rc_runtime_do_frame(runtime, event_handler, peek, memory, NULL);
47
+ }
48
+
49
+ static void _assert_serialize(rc_runtime_t* runtime, uint8_t* buffer, size_t buffer_size)
50
+ {
51
+ int result;
52
+ unsigned* overflow;
53
+
54
+ uint32_t size = rc_runtime_progress_size(runtime, NULL);
55
+ ASSERT_NUM_LESS(size, buffer_size);
56
+
57
+ overflow = (unsigned*)(buffer + size);
58
+ *overflow = 0xCDCDCDCD;
59
+
60
+ result = rc_runtime_serialize_progress(buffer, runtime, NULL);
61
+ ASSERT_NUM_EQUALS(result, RC_OK);
62
+
63
+ if (*overflow != 0xCDCDCDCD) {
64
+ ASSERT_FAIL("write past end of buffer");
65
+ }
66
+ }
67
+ #define assert_serialize(runtime, buffer, buffer_size) ASSERT_HELPER(_assert_serialize(runtime, buffer, buffer_size), "assert_serialize")
68
+
69
+ static void _assert_deserialize(rc_runtime_t* runtime, uint8_t* buffer)
70
+ {
71
+ int result = rc_runtime_deserialize_progress(runtime, buffer, NULL);
72
+ ASSERT_NUM_EQUALS(result, RC_OK);
73
+ }
74
+ #define assert_deserialize(runtime, buffer) ASSERT_HELPER(_assert_deserialize(runtime, buffer), "assert_deserialize")
75
+
76
+ static void _assert_sized_memref(rc_runtime_t* runtime, uint32_t address, uint8_t size, uint32_t value, uint32_t prev, uint32_t prior)
77
+ {
78
+ rc_memref_list_t* memref_list = &runtime->memrefs->memrefs;
79
+ for (; memref_list; memref_list = memref_list->next) {
80
+ const rc_memref_t* memref = memref_list->items;
81
+ const rc_memref_t* memref_end = memref + memref_list->count;
82
+ for (; memref < memref_end; ++memref) {
83
+ if (memref->address == address && memref->value.size == size) {
84
+ ASSERT_NUM_EQUALS(memref->value.value, value);
85
+ ASSERT_NUM_EQUALS(memref->value.prior, prior);
86
+
87
+ if (value == prior) {
88
+ ASSERT_NUM_EQUALS(memref->value.changed, 0);
89
+ }
90
+ else {
91
+ ASSERT_NUM_EQUALS(memref->value.changed, (prev == prior) ? 1 : 0);
92
+ }
93
+
94
+ return;
95
+ }
96
+ }
97
+ }
98
+
99
+ ASSERT_FAIL("could not find memref for address %u", address);
100
+ }
101
+ #define assert_sized_memref(runtime, address, size, value, prev, prior) ASSERT_HELPER(_assert_sized_memref(runtime, address, size, value, prev, prior), "assert_sized_memref")
102
+ #define assert_memref(runtime, address, value, prev, prior) ASSERT_HELPER(_assert_sized_memref(runtime, address, RC_MEMSIZE_8_BITS, value, prev, prior), "assert_memref")
103
+
104
+ static rc_trigger_t* find_trigger(rc_runtime_t* runtime, uint32_t ach_id)
105
+ {
106
+ uint32_t i;
107
+ for (i = 0; i < runtime->trigger_count; ++i) {
108
+ if (runtime->triggers[i].id == ach_id && runtime->triggers[i].trigger)
109
+ return runtime->triggers[i].trigger;
110
+ }
111
+
112
+ ASSERT_MESSAGE("could not find trigger for achievement %u", ach_id);
113
+ return NULL;
114
+ }
115
+
116
+ static rc_condition_t* find_trigger_cond(rc_trigger_t* trigger, uint32_t group_idx, uint32_t cond_idx)
117
+ {
118
+ rc_condset_t* condset;
119
+ rc_condition_t* cond;
120
+
121
+ if (!trigger)
122
+ return NULL;
123
+
124
+ condset = trigger->requirement;
125
+ if (group_idx > 0) {
126
+ condset = trigger->alternative;
127
+ while (condset && --group_idx != 0)
128
+ condset = condset->next;
129
+ }
130
+
131
+ if (!condset)
132
+ return NULL;
133
+
134
+ cond = condset->conditions;
135
+ while (cond && cond_idx > 0) {
136
+ --cond_idx;
137
+ cond = cond->next;
138
+ }
139
+
140
+ return cond;
141
+ }
142
+
143
+ static void _assert_hitcount(rc_runtime_t* runtime, uint32_t ach_id, uint32_t group_idx, uint32_t cond_idx, uint32_t expected_hits)
144
+ {
145
+ rc_trigger_t* trigger = find_trigger(runtime, ach_id);
146
+ rc_condition_t* cond = find_trigger_cond(trigger, group_idx, cond_idx);
147
+ ASSERT_PTR_NOT_NULL(cond);
148
+
149
+ ASSERT_NUM_EQUALS(cond->current_hits, expected_hits);
150
+ }
151
+ #define assert_hitcount(runtime, ach_id, group_idx, cond_idx, expected_hits) ASSERT_HELPER(_assert_hitcount(runtime, ach_id, group_idx, cond_idx, expected_hits), "assert_hitcount")
152
+
153
+ static void _assert_cond_memref(rc_runtime_t* runtime, uint32_t ach_id, uint32_t group_idx, uint32_t cond_idx, uint32_t expected_value, uint32_t expected_prior, uint8_t expected_changed)
154
+ {
155
+ rc_trigger_t* trigger = find_trigger(runtime, ach_id);
156
+ rc_condition_t* cond = find_trigger_cond(trigger, group_idx, cond_idx);
157
+ ASSERT_PTR_NOT_NULL(cond);
158
+
159
+ ASSERT_NUM_EQUALS(cond->operand1.value.memref->value.value, expected_value);
160
+ ASSERT_NUM_EQUALS(cond->operand1.value.memref->value.prior, expected_prior);
161
+ ASSERT_NUM_EQUALS(cond->operand1.value.memref->value.changed, expected_changed);
162
+ }
163
+ #define assert_cond_memref(runtime, ach_id, group_idx, cond_idx, expected_value, expected_prior, expected_changed) \
164
+ ASSERT_HELPER(_assert_cond_memref(runtime, ach_id, group_idx, cond_idx, expected_value, expected_prior, expected_changed), "assert_cond_memref")
165
+
166
+ static void _assert_cond_memref2(rc_runtime_t* runtime, uint32_t ach_id, uint32_t group_idx, uint32_t cond_idx, uint32_t expected_value, uint32_t expected_prior, uint8_t expected_changed)
167
+ {
168
+ rc_trigger_t* trigger = find_trigger(runtime, ach_id);
169
+ rc_condition_t* cond = find_trigger_cond(trigger, group_idx, cond_idx);
170
+ ASSERT_PTR_NOT_NULL(cond);
171
+
172
+ ASSERT_NUM_EQUALS(cond->operand2.value.memref->value.value, expected_value);
173
+ ASSERT_NUM_EQUALS(cond->operand2.value.memref->value.prior, expected_prior);
174
+ ASSERT_NUM_EQUALS(cond->operand2.value.memref->value.changed, expected_changed);
175
+ }
176
+ #define assert_cond_memref2(runtime, ach_id, group_idx, cond_idx, expected_value, expected_prior, expected_changed) \
177
+ ASSERT_HELPER(_assert_cond_memref2(runtime, ach_id, group_idx, cond_idx, expected_value, expected_prior, expected_changed), "assert_cond_memref2")
178
+
179
+ static void _assert_achievement_state(rc_runtime_t* runtime, uint32_t ach_id, uint8_t state)
180
+ {
181
+ rc_trigger_t* trigger = find_trigger(runtime, ach_id);
182
+ ASSERT_PTR_NOT_NULL(trigger);
183
+
184
+ ASSERT_NUM_EQUALS(trigger->state, state);
185
+ }
186
+ #define assert_achievement_state(runtime, ach_id, state) ASSERT_HELPER(_assert_achievement_state(runtime, ach_id, state), "assert_achievement_state")
187
+
188
+ static rc_lboard_t* find_lboard(rc_runtime_t* runtime, uint32_t lboard_id)
189
+ {
190
+ uint32_t i;
191
+ for (i = 0; i < runtime->lboard_count; ++i) {
192
+ if (runtime->lboards[i].id == lboard_id && runtime->lboards[i].lboard)
193
+ return runtime->lboards[i].lboard;
194
+ }
195
+
196
+ ASSERT_MESSAGE("could not find leaderboard %u", lboard_id);
197
+ return NULL;
198
+ }
199
+
200
+ static void _assert_sta_hitcount(rc_runtime_t* runtime, uint32_t lboard_id, uint32_t group_idx, uint32_t cond_idx, uint32_t expected_hits)
201
+ {
202
+ rc_lboard_t* lboard = find_lboard(runtime, lboard_id);
203
+ rc_condition_t* cond = find_trigger_cond(&lboard->start, group_idx, cond_idx);
204
+ ASSERT_PTR_NOT_NULL(cond);
205
+
206
+ ASSERT_NUM_EQUALS(cond->current_hits, expected_hits);
207
+ }
208
+ #define assert_sta_hitcount(runtime, lboard_id, group_idx, cond_idx, expected_hits) ASSERT_HELPER(_assert_sta_hitcount(runtime, lboard_id, group_idx, cond_idx, expected_hits), "assert_sta_hitcount")
209
+
210
+ static void _assert_sub_hitcount(rc_runtime_t* runtime, uint32_t lboard_id, uint32_t group_idx, uint32_t cond_idx, uint32_t expected_hits)
211
+ {
212
+ rc_lboard_t* lboard = find_lboard(runtime, lboard_id);
213
+ rc_condition_t* cond = find_trigger_cond(&lboard->submit, group_idx, cond_idx);
214
+ ASSERT_PTR_NOT_NULL(cond);
215
+
216
+ ASSERT_NUM_EQUALS(cond->current_hits, expected_hits);
217
+ }
218
+ #define assert_sub_hitcount(runtime, lboard_id, group_idx, cond_idx, expected_hits) ASSERT_HELPER(_assert_sub_hitcount(runtime, lboard_id, group_idx, cond_idx, expected_hits), "assert_sub_hitcount")
219
+
220
+ static void _assert_can_hitcount(rc_runtime_t* runtime, uint32_t lboard_id, uint32_t group_idx, uint32_t cond_idx, uint32_t expected_hits)
221
+ {
222
+ rc_lboard_t* lboard = find_lboard(runtime, lboard_id);
223
+ rc_condition_t* cond = find_trigger_cond(&lboard->cancel, group_idx, cond_idx);
224
+ ASSERT_PTR_NOT_NULL(cond);
225
+
226
+ ASSERT_NUM_EQUALS(cond->current_hits, expected_hits);
227
+ }
228
+ #define assert_can_hitcount(runtime, lboard_id, group_idx, cond_idx, expected_hits) ASSERT_HELPER(_assert_can_hitcount(runtime, lboard_id, group_idx, cond_idx, expected_hits), "assert_can_hitcount")
229
+
230
+ static void update_md5(uint8_t* buffer)
231
+ {
232
+ md5_state_t state;
233
+
234
+ uint8_t* ptr = buffer;
235
+ while (ptr[0] != 'D' || ptr[1] != 'O' || ptr[2] != 'N' || ptr[3] != 'E')
236
+ ++ptr;
237
+
238
+ ptr += 8;
239
+
240
+ md5_init(&state);
241
+ md5_append(&state, buffer, (int)(ptr - buffer));
242
+ md5_finish(&state, ptr);
243
+ }
244
+
245
+ static void reset_runtime(rc_runtime_t* runtime)
246
+ {
247
+ rc_memref_list_t* memref_list;
248
+ rc_memref_t* memref;
249
+ rc_trigger_t* trigger;
250
+ rc_condition_t* cond;
251
+ rc_condset_t* condset;
252
+ uint32_t i;
253
+
254
+ for (memref_list = &runtime->memrefs->memrefs; memref_list; memref_list = memref_list->next) {
255
+ const rc_memref_t* memref_end;
256
+ memref = memref_list->items;
257
+ memref_end = memref + memref_list->count;
258
+ for (; memref < memref_end; ++memref) {
259
+ memref->value.value = 0xFF;
260
+ memref->value.changed = 0;
261
+ memref->value.prior = 0xFF;
262
+ }
263
+ }
264
+
265
+ for (i = 0; i < runtime->trigger_count; ++i) {
266
+ trigger = runtime->triggers[i].trigger;
267
+ if (trigger) {
268
+ trigger->measured_value = 0xFF;
269
+ trigger->measured_target = 0xFF;
270
+
271
+ if (trigger->requirement) {
272
+ cond = trigger->requirement->conditions;
273
+ while (cond) {
274
+ cond->current_hits = 0xFF;
275
+ cond = cond->next;
276
+ }
277
+ }
278
+
279
+ condset = trigger->alternative;
280
+ while (condset) {
281
+ cond = condset->conditions;
282
+ while (cond) {
283
+ cond->current_hits = 0xFF;
284
+ cond = cond->next;
285
+ }
286
+
287
+ condset = condset->next;
288
+ }
289
+ }
290
+ }
291
+ }
292
+
293
+ static void test_empty()
294
+ {
295
+ uint8_t buffer[2048];
296
+ rc_runtime_t runtime;
297
+
298
+ rc_runtime_init(&runtime);
299
+
300
+ assert_serialize(&runtime, buffer, sizeof(buffer));
301
+
302
+ reset_runtime(&runtime);
303
+ assert_deserialize(&runtime, buffer);
304
+
305
+ ASSERT_NUM_EQUALS(runtime.memrefs->memrefs.count, 0);
306
+ ASSERT_NUM_EQUALS(runtime.memrefs->modified_memrefs.count, 0);
307
+ ASSERT_NUM_EQUALS(runtime.trigger_count, 0);
308
+ ASSERT_NUM_EQUALS(runtime.lboard_count, 0);
309
+
310
+ rc_runtime_destroy(&runtime);
311
+ }
312
+
313
+ static void test_single_achievement()
314
+ {
315
+ uint8_t ram[] = { 2, 3, 6 };
316
+ uint8_t buffer[2048];
317
+ memory_t memory;
318
+ rc_runtime_t runtime;
319
+
320
+ memory.ram = ram;
321
+ memory.size = sizeof(ram);
322
+
323
+ rc_runtime_init(&runtime);
324
+
325
+ assert_activate_achievement(&runtime, 1, "0xH0001=4_0xH0002=5");
326
+ assert_do_frame(&runtime, &memory);
327
+ ram[1] = 4;
328
+ assert_do_frame(&runtime, &memory);
329
+ assert_do_frame(&runtime, &memory);
330
+ assert_do_frame(&runtime, &memory);
331
+ ram[1] = 5;
332
+ assert_do_frame(&runtime, &memory);
333
+ assert_do_frame(&runtime, &memory);
334
+
335
+ assert_memref(&runtime, 1, 5, 5, 4);
336
+ assert_memref(&runtime, 2, 6, 6, 0);
337
+ assert_hitcount(&runtime, 1, 0, 0, 3);
338
+ assert_hitcount(&runtime, 1, 0, 1, 0);
339
+
340
+ assert_serialize(&runtime, buffer, sizeof(buffer));
341
+
342
+ reset_runtime(&runtime);
343
+ assert_deserialize(&runtime, buffer);
344
+
345
+ assert_memref(&runtime, 1, 5, 5, 4);
346
+ assert_memref(&runtime, 2, 6, 6, 0);
347
+ assert_hitcount(&runtime, 1, 0, 0, 3);
348
+ assert_hitcount(&runtime, 1, 0, 1, 0);
349
+
350
+ rc_runtime_destroy(&runtime);
351
+ }
352
+
353
+ static void test_invalid_marker()
354
+ {
355
+ uint8_t ram[] = { 2, 3, 6 };
356
+ uint8_t buffer[2048];
357
+ memory_t memory;
358
+ rc_runtime_t runtime;
359
+
360
+ memory.ram = ram;
361
+ memory.size = sizeof(ram);
362
+
363
+ rc_runtime_init(&runtime);
364
+
365
+ assert_activate_achievement(&runtime, 1, "0xH0001=4_0xH0002=5");
366
+ assert_do_frame(&runtime, &memory);
367
+ ram[1] = 4;
368
+ assert_do_frame(&runtime, &memory);
369
+ assert_do_frame(&runtime, &memory);
370
+ assert_do_frame(&runtime, &memory);
371
+ ram[1] = 5;
372
+ assert_do_frame(&runtime, &memory);
373
+ assert_do_frame(&runtime, &memory);
374
+
375
+ assert_memref(&runtime, 1, 5, 5, 4);
376
+ assert_memref(&runtime, 2, 6, 6, 0);
377
+ assert_hitcount(&runtime, 1, 0, 0, 3);
378
+ assert_hitcount(&runtime, 1, 0, 1, 0);
379
+
380
+ assert_serialize(&runtime, buffer, sizeof(buffer));
381
+
382
+ /* invalid header prevents anything from being deserialized */
383
+ buffer[0] = 0x40;
384
+ update_md5(buffer);
385
+
386
+ reset_runtime(&runtime);
387
+ ASSERT_NUM_EQUALS(rc_runtime_deserialize_progress(&runtime, buffer, NULL), RC_INVALID_STATE);
388
+
389
+ assert_memref(&runtime, 1, 0xFF, 0xFF, 0xFF);
390
+ assert_memref(&runtime, 2, 0xFF, 0xFF, 0xFF);
391
+ assert_hitcount(&runtime, 1, 0, 0, 0);
392
+ assert_hitcount(&runtime, 1, 0, 1, 0);
393
+
394
+ rc_runtime_destroy(&runtime);
395
+ }
396
+
397
+ static void test_invalid_memref_chunk_id()
398
+ {
399
+ uint8_t ram[] = { 2, 3, 6 };
400
+ uint8_t buffer[2048];
401
+ memory_t memory;
402
+ rc_runtime_t runtime;
403
+
404
+ memory.ram = ram;
405
+ memory.size = sizeof(ram);
406
+
407
+ rc_runtime_init(&runtime);
408
+
409
+ assert_activate_achievement(&runtime, 1, "0xH0001=4_0xH0002=5");
410
+ assert_do_frame(&runtime, &memory);
411
+ ram[1] = 4;
412
+ assert_do_frame(&runtime, &memory);
413
+ assert_do_frame(&runtime, &memory);
414
+ assert_do_frame(&runtime, &memory);
415
+ ram[1] = 5;
416
+ assert_do_frame(&runtime, &memory);
417
+ assert_do_frame(&runtime, &memory);
418
+
419
+ assert_memref(&runtime, 1, 5, 5, 4);
420
+ assert_memref(&runtime, 2, 6, 6, 0);
421
+ assert_hitcount(&runtime, 1, 0, 0, 3);
422
+ assert_hitcount(&runtime, 1, 0, 1, 0);
423
+
424
+ assert_serialize(&runtime, buffer, sizeof(buffer));
425
+
426
+ /* invalid chunk is ignored, achievement hits will still be read */
427
+ buffer[5] = 0x40;
428
+ update_md5(buffer);
429
+
430
+ reset_runtime(&runtime);
431
+ assert_deserialize(&runtime, buffer);
432
+
433
+ assert_memref(&runtime, 1, 0xFF, 0xFF, 0xFF);
434
+ assert_memref(&runtime, 2, 0xFF, 0xFF, 0xFF);
435
+ assert_hitcount(&runtime, 1, 0, 0, 3);
436
+ assert_hitcount(&runtime, 1, 0, 1, 0);
437
+
438
+ rc_runtime_destroy(&runtime);
439
+ }
440
+
441
+ static void test_modified_data()
442
+ {
443
+ uint8_t ram[] = { 2, 3, 6 };
444
+ uint8_t buffer[2048];
445
+ memory_t memory;
446
+ rc_runtime_t runtime;
447
+
448
+ memory.ram = ram;
449
+ memory.size = sizeof(ram);
450
+
451
+ rc_runtime_init(&runtime);
452
+
453
+ assert_activate_achievement(&runtime, 1, "0xH0001=4_0xH0002=5");
454
+ assert_do_frame(&runtime, &memory);
455
+ ram[1] = 4;
456
+ assert_do_frame(&runtime, &memory);
457
+ assert_do_frame(&runtime, &memory);
458
+ assert_do_frame(&runtime, &memory);
459
+ ram[1] = 5;
460
+ assert_do_frame(&runtime, &memory);
461
+ assert_do_frame(&runtime, &memory);
462
+
463
+ assert_memref(&runtime, 1, 5, 5, 4);
464
+ assert_memref(&runtime, 2, 6, 6, 0);
465
+ assert_hitcount(&runtime, 1, 0, 0, 3);
466
+ assert_hitcount(&runtime, 1, 0, 1, 0);
467
+
468
+ assert_serialize(&runtime, buffer, sizeof(buffer));
469
+
470
+ /* this changes the current hits for the test condition to 6, but doesn't update the checksum, so should be ignored */
471
+ ASSERT_NUM_EQUALS(buffer[84], 3);
472
+ buffer[84] = 6;
473
+
474
+ reset_runtime(&runtime);
475
+ ASSERT_NUM_EQUALS(rc_runtime_deserialize_progress(&runtime, buffer, NULL), RC_INVALID_STATE);
476
+
477
+ /* memrefs will have been processed and cannot be "reset" */
478
+ assert_memref(&runtime, 1, 5, 5, 4);
479
+ assert_memref(&runtime, 2, 6, 6, 0);
480
+
481
+ /* deserialization failure causes all hits to be reset */
482
+ assert_hitcount(&runtime, 1, 0, 0, 0);
483
+ assert_hitcount(&runtime, 1, 0, 1, 0);
484
+
485
+ rc_runtime_destroy(&runtime);
486
+ }
487
+
488
+ static void test_single_achievement_deactivated()
489
+ {
490
+ uint8_t ram[] = { 2, 3, 6 };
491
+ uint8_t buffer[2048];
492
+ memory_t memory;
493
+ rc_runtime_t runtime;
494
+
495
+ memory.ram = ram;
496
+ memory.size = sizeof(ram);
497
+
498
+ rc_runtime_init(&runtime);
499
+
500
+ assert_activate_achievement(&runtime, 1, "0xH0001=4_0xH0002=5");
501
+ assert_do_frame(&runtime, &memory);
502
+ ram[1] = 4;
503
+ assert_do_frame(&runtime, &memory);
504
+ assert_do_frame(&runtime, &memory);
505
+ assert_do_frame(&runtime, &memory);
506
+ ram[1] = 5;
507
+ assert_do_frame(&runtime, &memory);
508
+ assert_do_frame(&runtime, &memory);
509
+
510
+ assert_memref(&runtime, 1, 5, 5, 4);
511
+ assert_memref(&runtime, 2, 6, 6, 0);
512
+ assert_hitcount(&runtime, 1, 0, 0, 3);
513
+ assert_hitcount(&runtime, 1, 0, 1, 0);
514
+
515
+ assert_serialize(&runtime, buffer, sizeof(buffer));
516
+
517
+ reset_runtime(&runtime);
518
+
519
+ /* disabled achievement */
520
+ rc_runtime_deactivate_achievement(&runtime, 1);
521
+ assert_deserialize(&runtime, buffer);
522
+
523
+ assert_memref(&runtime, 1, 5, 5, 4);
524
+ assert_memref(&runtime, 2, 6, 6, 0);
525
+
526
+ /* reactivate */
527
+ assert_activate_achievement(&runtime, 1, "0xH0001=4_0xH0002=5");
528
+ assert_achievement_state(&runtime, 1, RC_TRIGGER_STATE_WAITING);
529
+ assert_hitcount(&runtime, 1, 0, 0, 0);
530
+ assert_hitcount(&runtime, 1, 0, 1, 0);
531
+
532
+ reset_runtime(&runtime);
533
+ assert_deserialize(&runtime, buffer);
534
+ assert_memref(&runtime, 1, 5, 5, 4);
535
+ assert_memref(&runtime, 2, 6, 6, 0);
536
+ assert_hitcount(&runtime, 1, 0, 0, 3);
537
+ assert_hitcount(&runtime, 1, 0, 1, 0);
538
+
539
+ rc_runtime_destroy(&runtime);
540
+ }
541
+
542
+ static void test_single_achievement_md5_changed()
543
+ {
544
+ uint8_t ram[] = { 2, 3, 6 };
545
+ uint8_t buffer[2048];
546
+ memory_t memory;
547
+ rc_runtime_t runtime;
548
+
549
+ memory.ram = ram;
550
+ memory.size = sizeof(ram);
551
+
552
+ rc_runtime_init(&runtime);
553
+
554
+ assert_activate_achievement(&runtime, 1, "0xH0001=4_0xH0002=5");
555
+ assert_do_frame(&runtime, &memory);
556
+ ram[1] = 4;
557
+ assert_do_frame(&runtime, &memory);
558
+ assert_do_frame(&runtime, &memory);
559
+ assert_do_frame(&runtime, &memory);
560
+ ram[1] = 5;
561
+ assert_do_frame(&runtime, &memory);
562
+ assert_do_frame(&runtime, &memory);
563
+
564
+ assert_memref(&runtime, 1, 5, 5, 4);
565
+ assert_memref(&runtime, 2, 6, 6, 0);
566
+ assert_hitcount(&runtime, 1, 0, 0, 3);
567
+ assert_hitcount(&runtime, 1, 0, 1, 0);
568
+
569
+ assert_serialize(&runtime, buffer, sizeof(buffer));
570
+
571
+ reset_runtime(&runtime);
572
+
573
+ /* new achievement definition - rack up a couple hits */
574
+ assert_activate_achievement(&runtime, 1, "0xH0001=4_0xH0002=5.1.");
575
+ ram[1] = 3;
576
+ assert_do_frame(&runtime, &memory);
577
+ ram[1] = 4;
578
+ assert_do_frame(&runtime, &memory);
579
+ assert_do_frame(&runtime, &memory);
580
+ assert_hitcount(&runtime, 1, 0, 0, 2);
581
+ assert_hitcount(&runtime, 1, 0, 1, 0);
582
+ assert_memref(&runtime, 1, 4, 4, 3);
583
+
584
+ assert_deserialize(&runtime, buffer);
585
+
586
+ /* memrefs should be restored */
587
+ assert_memref(&runtime, 1, 5, 5, 4);
588
+ assert_memref(&runtime, 2, 6, 6, 0);
589
+
590
+ /* achievement definition changed, achievement should be reset */
591
+ assert_hitcount(&runtime, 1, 0, 0, 0);
592
+ assert_hitcount(&runtime, 1, 0, 1, 0);
593
+
594
+ rc_runtime_destroy(&runtime);
595
+ }
596
+
597
+ static void setup_multiple_achievements(rc_runtime_t* runtime, memory_t* memory)
598
+ {
599
+ rc_runtime_init(runtime);
600
+
601
+ assert_activate_achievement(runtime, 1, "0xH0001=4_0xH0000=1");
602
+ assert_activate_achievement(runtime, 2, "0xH0002=7_0xH0000=2");
603
+ assert_activate_achievement(runtime, 3, "0xH0003=9_0xH0000=3");
604
+ assert_activate_achievement(runtime, 4, "0xH0004=1_0xH0000=4");
605
+ assert_do_frame(runtime, memory);
606
+ memory->ram[1] = 4;
607
+ assert_do_frame(runtime, memory);
608
+ memory->ram[2] = 7;
609
+ assert_do_frame(runtime, memory);
610
+ memory->ram[3] = 9;
611
+ assert_do_frame(runtime, memory);
612
+ memory->ram[4] = 1;
613
+ assert_do_frame(runtime, memory);
614
+
615
+ assert_memref(runtime, 0, 0, 0, 0);
616
+ assert_memref(runtime, 1, 4, 4, 1);
617
+ assert_memref(runtime, 2, 7, 7, 2);
618
+ assert_memref(runtime, 3, 9, 9, 3);
619
+ assert_memref(runtime, 4, 1, 4, 4);
620
+ assert_hitcount(runtime, 1, 0, 0, 4);
621
+ assert_hitcount(runtime, 2, 0, 0, 3);
622
+ assert_hitcount(runtime, 3, 0, 0, 2);
623
+ assert_hitcount(runtime, 4, 0, 0, 1);
624
+ }
625
+
626
+ static void test_single_achievement_sized()
627
+ {
628
+ uint8_t ram[] = { 2, 3, 6 };
629
+ uint8_t buffer[2048];
630
+ memory_t memory;
631
+ rc_runtime_t runtime;
632
+ uint32_t size;
633
+ int result;
634
+
635
+ memory.ram = ram;
636
+ memory.size = sizeof(ram);
637
+
638
+ rc_runtime_init(&runtime);
639
+
640
+ assert_activate_achievement(&runtime, 1, "0xH0001=4_0xH0002=5");
641
+ assert_do_frame(&runtime, &memory);
642
+ ram[1] = 4;
643
+ assert_do_frame(&runtime, &memory);
644
+ assert_do_frame(&runtime, &memory);
645
+ assert_do_frame(&runtime, &memory);
646
+ ram[1] = 5;
647
+ assert_do_frame(&runtime, &memory);
648
+ assert_do_frame(&runtime, &memory);
649
+
650
+ assert_memref(&runtime, 1, 5, 5, 4);
651
+ assert_memref(&runtime, 2, 6, 6, 0);
652
+ assert_hitcount(&runtime, 1, 0, 0, 3);
653
+ assert_hitcount(&runtime, 1, 0, 1, 0);
654
+
655
+ size = rc_runtime_progress_size(&runtime, NULL);
656
+ ASSERT_NUM_LESS(size, sizeof(buffer));
657
+
658
+ result = rc_runtime_serialize_progress_sized(buffer, size - 1, &runtime, NULL);
659
+ ASSERT_NUM_EQUALS(result, RC_INSUFFICIENT_BUFFER);
660
+
661
+ result = rc_runtime_serialize_progress_sized(buffer, size, &runtime, NULL);
662
+ ASSERT_NUM_EQUALS(result, RC_OK);
663
+
664
+ result = rc_runtime_deserialize_progress_sized(&runtime, buffer, size - 1, NULL);
665
+ ASSERT_NUM_EQUALS(result, RC_INSUFFICIENT_BUFFER);
666
+
667
+ assert_memref(&runtime, 1, 5, 5, 4); /* memrefs don't get reset on failure */
668
+ assert_memref(&runtime, 2, 6, 6, 0);
669
+ assert_hitcount(&runtime, 1, 0, 0, 0);
670
+ assert_hitcount(&runtime, 1, 0, 1, 0);
671
+
672
+ result = rc_runtime_deserialize_progress_sized(&runtime, buffer, 16, NULL);
673
+ ASSERT_NUM_EQUALS(result, RC_INSUFFICIENT_BUFFER);
674
+
675
+ result = rc_runtime_deserialize_progress_sized(&runtime, buffer, 0, NULL);
676
+ ASSERT_NUM_EQUALS(result, RC_INSUFFICIENT_BUFFER);
677
+
678
+ assert_memref(&runtime, 1, 5, 5, 4); /* memrefs don't get reset on failure */
679
+ assert_memref(&runtime, 2, 6, 6, 0);
680
+ assert_hitcount(&runtime, 1, 0, 0, 0);
681
+ assert_hitcount(&runtime, 1, 0, 1, 0);
682
+
683
+ result = rc_runtime_deserialize_progress_sized(&runtime, buffer, size, NULL);
684
+ ASSERT_NUM_EQUALS(result, RC_OK);
685
+
686
+ assert_memref(&runtime, 1, 5, 5, 4);
687
+ assert_memref(&runtime, 2, 6, 6, 0);
688
+ assert_hitcount(&runtime, 1, 0, 0, 3);
689
+ assert_hitcount(&runtime, 1, 0, 1, 0);
690
+
691
+ rc_runtime_destroy(&runtime);
692
+ }
693
+
694
+ static void test_empty_sized()
695
+ {
696
+ uint8_t buffer[2048];
697
+ rc_runtime_t runtime;
698
+ uint32_t size;
699
+ int result;
700
+
701
+ rc_runtime_init(&runtime);
702
+
703
+ size = rc_runtime_progress_size(&runtime, NULL);
704
+ ASSERT_NUM_LESS(size, sizeof(buffer));
705
+
706
+ result = rc_runtime_serialize_progress_sized(buffer, size - 1, &runtime, NULL);
707
+ ASSERT_NUM_EQUALS(result, RC_INSUFFICIENT_BUFFER);
708
+
709
+ result = rc_runtime_serialize_progress_sized(buffer, size, &runtime, NULL);
710
+ ASSERT_NUM_EQUALS(result, RC_OK);
711
+
712
+ result = rc_runtime_deserialize_progress_sized(&runtime, buffer, size - 1, NULL);
713
+ ASSERT_NUM_EQUALS(result, RC_INSUFFICIENT_BUFFER);
714
+
715
+ result = rc_runtime_deserialize_progress_sized(&runtime, buffer, 16, NULL);
716
+ ASSERT_NUM_EQUALS(result, RC_INSUFFICIENT_BUFFER);
717
+
718
+ result = rc_runtime_deserialize_progress_sized(&runtime, buffer, 0, NULL);
719
+ ASSERT_NUM_EQUALS(result, RC_INSUFFICIENT_BUFFER);
720
+
721
+ result = rc_runtime_deserialize_progress_sized(&runtime, buffer, size, NULL);
722
+ ASSERT_NUM_EQUALS(result, RC_OK);
723
+
724
+ rc_runtime_destroy(&runtime);
725
+ }
726
+
727
+ static void test_no_core_group()
728
+ {
729
+ uint8_t ram[] = { 2, 3, 6 };
730
+ uint8_t buffer[2048];
731
+ memory_t memory;
732
+ rc_runtime_t runtime;
733
+
734
+ memory.ram = ram;
735
+ memory.size = sizeof(ram);
736
+
737
+ rc_runtime_init(&runtime);
738
+
739
+ assert_activate_achievement(&runtime, 1, "S0xH0001=4_0xH0002=5");
740
+ assert_do_frame(&runtime, &memory);
741
+ ram[1] = 4;
742
+ assert_do_frame(&runtime, &memory);
743
+ assert_do_frame(&runtime, &memory);
744
+ assert_do_frame(&runtime, &memory);
745
+ ram[1] = 5;
746
+ assert_do_frame(&runtime, &memory);
747
+ assert_do_frame(&runtime, &memory);
748
+
749
+ assert_memref(&runtime, 1, 5, 5, 4);
750
+ assert_memref(&runtime, 2, 6, 6, 0);
751
+ assert_hitcount(&runtime, 1, 1, 0, 3);
752
+ assert_hitcount(&runtime, 1, 1, 1, 0);
753
+
754
+ assert_serialize(&runtime, buffer, sizeof(buffer));
755
+
756
+ reset_runtime(&runtime);
757
+ assert_deserialize(&runtime, buffer);
758
+
759
+ assert_memref(&runtime, 1, 5, 5, 4);
760
+ assert_memref(&runtime, 2, 6, 6, 0);
761
+ assert_hitcount(&runtime, 1, 1, 0, 3);
762
+ assert_hitcount(&runtime, 1, 1, 1, 0);
763
+
764
+ rc_runtime_destroy(&runtime);
765
+ }
766
+
767
+ static void test_memref_shared_address()
768
+ {
769
+ uint8_t ram[] = { 2, 3, 0, 0, 0 };
770
+ uint8_t buffer[2048];
771
+ memory_t memory;
772
+ rc_runtime_t runtime;
773
+
774
+ memory.ram = ram;
775
+ memory.size = sizeof(ram);
776
+
777
+ rc_runtime_init(&runtime);
778
+
779
+ assert_activate_achievement(&runtime, 1, "0xH0001=4_0x 0001=5_0xX0001=6");
780
+ assert_do_frame(&runtime, &memory);
781
+ ram[1] = 4;
782
+ assert_do_frame(&runtime, &memory);
783
+ assert_do_frame(&runtime, &memory);
784
+ assert_do_frame(&runtime, &memory);
785
+ ram[1] = 5;
786
+ assert_do_frame(&runtime, &memory);
787
+ assert_do_frame(&runtime, &memory);
788
+ ram[1] = 6;
789
+ assert_do_frame(&runtime, &memory);
790
+
791
+ assert_sized_memref(&runtime, 1, RC_MEMSIZE_8_BITS, 6, 5, 5);
792
+ assert_sized_memref(&runtime, 1, RC_MEMSIZE_16_BITS, 6, 5, 5);
793
+ assert_sized_memref(&runtime, 1, RC_MEMSIZE_32_BITS, 6, 5, 5);
794
+ assert_hitcount(&runtime, 1, 0, 0, 3);
795
+ assert_hitcount(&runtime, 1, 0, 1, 2);
796
+ assert_hitcount(&runtime, 1, 0, 2, 1);
797
+
798
+ assert_serialize(&runtime, buffer, sizeof(buffer));
799
+
800
+ reset_runtime(&runtime);
801
+ assert_deserialize(&runtime, buffer);
802
+
803
+ assert_sized_memref(&runtime, 1, RC_MEMSIZE_8_BITS, 6, 5, 5);
804
+ assert_sized_memref(&runtime, 1, RC_MEMSIZE_16_BITS, 6, 5, 5);
805
+ assert_sized_memref(&runtime, 1, RC_MEMSIZE_32_BITS, 6, 5, 5);
806
+ assert_hitcount(&runtime, 1, 0, 0, 3);
807
+ assert_hitcount(&runtime, 1, 0, 1, 2);
808
+ assert_hitcount(&runtime, 1, 0, 2, 1);
809
+
810
+ rc_runtime_destroy(&runtime);
811
+ }
812
+
813
+ static void test_memref_addsource() {
814
+ uint8_t ram[] = { 1, 2, 3, 4, 5 };
815
+ uint8_t buffer1[512];
816
+ uint8_t buffer2[512];
817
+ memory_t memory;
818
+ rc_runtime_t runtime;
819
+
820
+ memory.ram = ram;
821
+ memory.size = sizeof(ram);
822
+
823
+ rc_runtime_init(&runtime);
824
+
825
+ /* byte(2) + byte(1) == 5 - third condition just prevents the achievement from triggering*/
826
+ assert_activate_achievement(&runtime, 1, "A:0xH0002_0xH0001=3_0xH0004=99");
827
+ assert_do_frame(&runtime, &memory); /* $2 = 3, $1 = 2, 3 + 2 = 5 */
828
+ ram[1] = 3;
829
+ ram[2] = 0;
830
+ assert_do_frame(&runtime, &memory); /* $2 = 0, $1 = 3, 0 + 3 = 3 */
831
+ assert_do_frame(&runtime, &memory);
832
+ assert_do_frame(&runtime, &memory);
833
+ assert_do_frame(&runtime, &memory);
834
+
835
+ assert_hitcount(&runtime, 1, 0, 0, 0);
836
+ assert_hitcount(&runtime, 1, 0, 1, 4);
837
+ assert_cond_memref(&runtime, 1, 0, 1, 3, 5, 0);
838
+
839
+ assert_serialize(&runtime, buffer1, sizeof(buffer1));
840
+
841
+ assert_do_frame(&runtime, &memory);
842
+ ram[1] = 6;
843
+ ram[2] = 1;
844
+ assert_do_frame(&runtime, &memory); /* $2 = 1, $1 = 6, 1 + 6 = 7 */
845
+ assert_hitcount(&runtime, 1, 0, 0, 0);
846
+ assert_hitcount(&runtime, 1, 0, 1, 5);
847
+ assert_cond_memref(&runtime, 1, 0, 1, 7, 3, 1);
848
+
849
+ assert_serialize(&runtime, buffer2, sizeof(buffer2));
850
+
851
+ reset_runtime(&runtime);
852
+ assert_deserialize(&runtime, buffer1);
853
+ assert_hitcount(&runtime, 1, 0, 0, 0);
854
+ assert_hitcount(&runtime, 1, 0, 1, 4);
855
+ assert_cond_memref(&runtime, 1, 0, 1, 3, 5, 0);
856
+
857
+ reset_runtime(&runtime);
858
+ assert_deserialize(&runtime, buffer2);
859
+ assert_hitcount(&runtime, 1, 0, 0, 0);
860
+ assert_hitcount(&runtime, 1, 0, 1, 5);
861
+ assert_cond_memref(&runtime, 1, 0, 1, 7, 3, 1);
862
+
863
+ rc_runtime_destroy(&runtime);
864
+ }
865
+
866
+ static void test_memref_indirect()
867
+ {
868
+ uint8_t ram[] = { 1, 2, 3, 4, 5 };
869
+ uint8_t buffer1[512];
870
+ uint8_t buffer2[512];
871
+ memory_t memory;
872
+ rc_runtime_t runtime;
873
+
874
+ memory.ram = ram;
875
+ memory.size = sizeof(ram);
876
+
877
+ rc_runtime_init(&runtime);
878
+
879
+ /* byte(byte(2) + 1) == 5 - third condition just prevents the achievement from triggering*/
880
+ assert_activate_achievement(&runtime, 1, "I:0xH0002_0xH0001=3_0xH0004=99");
881
+ assert_do_frame(&runtime, &memory); /* $2 = 3, $(3+1) = 5 */
882
+ ram[1] = 3;
883
+ ram[2] = 0;
884
+ assert_do_frame(&runtime, &memory); /* $2 = 0, $(0+1) = 3 */
885
+ assert_do_frame(&runtime, &memory);
886
+ assert_do_frame(&runtime, &memory);
887
+ assert_do_frame(&runtime, &memory);
888
+
889
+ assert_hitcount(&runtime, 1, 0, 0, 0);
890
+ assert_hitcount(&runtime, 1, 0, 1, 4);
891
+ assert_cond_memref(&runtime, 1, 0, 0, 0, 3, 0);
892
+ assert_cond_memref(&runtime, 1, 0, 1, 3, 5, 0);
893
+
894
+ assert_serialize(&runtime, buffer1, sizeof(buffer1));
895
+
896
+ assert_do_frame(&runtime, &memory);
897
+ ram[1] = 6;
898
+ ram[2] = 1;
899
+ assert_do_frame(&runtime, &memory); /* $2 = 1, $(1+1) = 1 */
900
+ assert_hitcount(&runtime, 1, 0, 0, 0);
901
+ assert_hitcount(&runtime, 1, 0, 1, 5);
902
+ assert_cond_memref(&runtime, 1, 0, 0, 1, 0, 1);
903
+ assert_cond_memref(&runtime, 1, 0, 1, 1, 3, 1);
904
+
905
+ assert_serialize(&runtime, buffer2, sizeof(buffer2));
906
+
907
+ reset_runtime(&runtime);
908
+ assert_deserialize(&runtime, buffer1);
909
+ assert_hitcount(&runtime, 1, 0, 0, 0);
910
+ assert_hitcount(&runtime, 1, 0, 1, 4);
911
+ assert_cond_memref(&runtime, 1, 0, 0, 0, 3, 0);
912
+ assert_cond_memref(&runtime, 1, 0, 1, 3, 5, 0);
913
+
914
+ reset_runtime(&runtime);
915
+ assert_deserialize(&runtime, buffer2);
916
+ assert_hitcount(&runtime, 1, 0, 0, 0);
917
+ assert_hitcount(&runtime, 1, 0, 1, 5);
918
+ assert_cond_memref(&runtime, 1, 0, 0, 1, 0, 1);
919
+ assert_cond_memref(&runtime, 1, 0, 1, 1, 3, 1);
920
+
921
+ rc_runtime_destroy(&runtime);
922
+ }
923
+
924
+ static void test_memref_indirect_delta()
925
+ {
926
+ uint8_t ram[] = { 1, 2, 3, 4, 5 };
927
+ uint8_t buffer1[512];
928
+ uint8_t buffer2[512];
929
+ memory_t memory;
930
+ rc_runtime_t runtime;
931
+
932
+ memory.ram = ram;
933
+ memory.size = sizeof(ram);
934
+
935
+ rc_runtime_init(&runtime);
936
+
937
+ /* byte(byte(2) + 1) == 5 - third condition just prevents the achievement from triggering*/
938
+ assert_activate_achievement(&runtime, 1, "I:0xH0002_d0xH0001=3_0xH0004=99");
939
+ assert_do_frame(&runtime, &memory); /* $2 = 3, $(3+1) = 5, delta = 0 */
940
+ ram[1] = 3;
941
+ ram[2] = 0;
942
+ assert_do_frame(&runtime, &memory); /* $2 = 0, $(0+1) = 3, delta = 5 */
943
+ assert_do_frame(&runtime, &memory); /* $2 = 0, $(0+1) = 3, delta = 3 */
944
+
945
+ assert_hitcount(&runtime, 1, 0, 0, 0);
946
+ assert_hitcount(&runtime, 1, 0, 1, 1);
947
+ assert_cond_memref(&runtime, 1, 0, 0, 0, 3, 0);
948
+ assert_cond_memref(&runtime, 1, 0, 1, 3, 5, 0);
949
+
950
+ assert_serialize(&runtime, buffer1, sizeof(buffer1));
951
+
952
+ assert_do_frame(&runtime, &memory); /* $2 = 0, $(0+1) = 3, delta = 3 */
953
+ ram[1] = 6;
954
+ ram[2] = 1;
955
+ assert_do_frame(&runtime, &memory); /* $2 = 1, $(1+1) = 1, delta = 3 */
956
+ assert_do_frame(&runtime, &memory); /* $2 = 1, $(1+1) = 1, delta = 1 */
957
+ assert_hitcount(&runtime, 1, 0, 0, 0);
958
+ assert_hitcount(&runtime, 1, 0, 1, 3);
959
+ assert_cond_memref(&runtime, 1, 0, 0, 1, 0, 0);
960
+ assert_cond_memref(&runtime, 1, 0, 1, 1, 3, 0);
961
+
962
+ assert_serialize(&runtime, buffer2, sizeof(buffer2));
963
+
964
+ reset_runtime(&runtime);
965
+ assert_deserialize(&runtime, buffer1);
966
+ assert_hitcount(&runtime, 1, 0, 0, 0);
967
+ assert_hitcount(&runtime, 1, 0, 1, 1);
968
+ assert_cond_memref(&runtime, 1, 0, 0, 0, 3, 0);
969
+ assert_cond_memref(&runtime, 1, 0, 1, 3, 5, 0);
970
+
971
+ reset_runtime(&runtime);
972
+ assert_deserialize(&runtime, buffer2);
973
+ assert_hitcount(&runtime, 1, 0, 0, 0);
974
+ assert_hitcount(&runtime, 1, 0, 1, 3);
975
+ assert_cond_memref(&runtime, 1, 0, 0, 1, 0, 0);
976
+ assert_cond_memref(&runtime, 1, 0, 1, 1, 3, 0);
977
+
978
+ rc_runtime_destroy(&runtime);
979
+ }
980
+
981
+ static void test_memref_double_indirect()
982
+ {
983
+ uint8_t ram[] = { 1, 2, 3, 4, 5 };
984
+ uint8_t buffer1[512];
985
+ uint8_t buffer2[512];
986
+ memory_t memory;
987
+ rc_runtime_t runtime;
988
+
989
+ memory.ram = ram;
990
+ memory.size = sizeof(ram);
991
+
992
+ rc_runtime_init(&runtime);
993
+
994
+ /* byte(byte(2) + 1) == byte(byte(2)) - third condition just prevents the achievement from triggering*/
995
+ assert_activate_achievement(&runtime, 1, "I:0xH0002_0xH0001=0xH0000_0xH0004=99");
996
+ assert_do_frame(&runtime, &memory); /* $2 = 3, $(3+1) = 5, $(3+0) = 4 */
997
+ ram[0] = 3;
998
+ ram[1] = 3;
999
+ ram[2] = 0;
1000
+ assert_do_frame(&runtime, &memory); /* $2 = 0, $(0+1) = 3, $(0+0) = 3 */
1001
+ assert_do_frame(&runtime, &memory);
1002
+ assert_do_frame(&runtime, &memory);
1003
+ assert_do_frame(&runtime, &memory);
1004
+
1005
+ assert_hitcount(&runtime, 1, 0, 0, 0);
1006
+ assert_hitcount(&runtime, 1, 0, 1, 4);
1007
+ assert_cond_memref(&runtime, 1, 0, 0, 0, 3, 0);
1008
+ assert_cond_memref(&runtime, 1, 0, 1, 3, 5, 0);
1009
+ assert_cond_memref2(&runtime, 1, 0, 1, 3, 4, 0);
1010
+
1011
+ assert_serialize(&runtime, buffer1, sizeof(buffer1));
1012
+
1013
+ assert_do_frame(&runtime, &memory);
1014
+ ram[1] = 6;
1015
+ ram[2] = 1;
1016
+ assert_do_frame(&runtime, &memory); /* $2 = 1, $(1+1) = 1, $(1+0) = 6 */
1017
+ assert_hitcount(&runtime, 1, 0, 0, 0);
1018
+ assert_hitcount(&runtime, 1, 0, 1, 5);
1019
+ assert_cond_memref(&runtime, 1, 0, 0, 1, 0, 1);
1020
+ assert_cond_memref(&runtime, 1, 0, 1, 1, 3, 1);
1021
+ assert_cond_memref2(&runtime, 1, 0, 1, 6, 3, 1);
1022
+
1023
+ assert_serialize(&runtime, buffer2, sizeof(buffer2));
1024
+
1025
+ reset_runtime(&runtime);
1026
+ assert_deserialize(&runtime, buffer1);
1027
+ assert_hitcount(&runtime, 1, 0, 0, 0);
1028
+ assert_hitcount(&runtime, 1, 0, 1, 4);
1029
+ assert_cond_memref(&runtime, 1, 0, 0, 0, 3, 0);
1030
+ assert_cond_memref(&runtime, 1, 0, 1, 3, 5, 0);
1031
+ assert_cond_memref2(&runtime, 1, 0, 1, 3, 4, 0);
1032
+
1033
+ reset_runtime(&runtime);
1034
+ assert_deserialize(&runtime, buffer2);
1035
+ assert_hitcount(&runtime, 1, 0, 0, 0);
1036
+ assert_hitcount(&runtime, 1, 0, 1, 5);
1037
+ assert_cond_memref(&runtime, 1, 0, 0, 1, 0, 1);
1038
+ assert_cond_memref(&runtime, 1, 0, 1, 1, 3, 1);
1039
+ assert_cond_memref2(&runtime, 1, 0, 1, 6, 3, 1);
1040
+
1041
+ rc_runtime_destroy(&runtime);
1042
+ }
1043
+
1044
+ static void test_multiple_achievements()
1045
+ {
1046
+ uint8_t ram[] = { 0, 1, 2, 3, 4, 5, 6, 7 };
1047
+ uint8_t buffer[2048];
1048
+ memory_t memory;
1049
+ rc_runtime_t runtime;
1050
+
1051
+ memory.ram = ram;
1052
+ memory.size = sizeof(ram);
1053
+ setup_multiple_achievements(&runtime, &memory);
1054
+
1055
+ assert_serialize(&runtime, buffer, sizeof(buffer));
1056
+
1057
+ reset_runtime(&runtime);
1058
+ assert_deserialize(&runtime, buffer);
1059
+
1060
+ assert_memref(&runtime, 0, 0, 0, 0);
1061
+ assert_memref(&runtime, 1, 4, 4, 1);
1062
+ assert_memref(&runtime, 2, 7, 7, 2);
1063
+ assert_memref(&runtime, 3, 9, 9, 3);
1064
+ assert_memref(&runtime, 4, 1, 4, 4);
1065
+ assert_hitcount(&runtime, 1, 0, 0, 4);
1066
+ assert_hitcount(&runtime, 1, 0, 1, 0);
1067
+ assert_hitcount(&runtime, 2, 0, 0, 3);
1068
+ assert_hitcount(&runtime, 2, 0, 1, 0);
1069
+ assert_hitcount(&runtime, 3, 0, 0, 2);
1070
+ assert_hitcount(&runtime, 3, 0, 1, 0);
1071
+ assert_hitcount(&runtime, 4, 0, 0, 1);
1072
+ assert_hitcount(&runtime, 4, 0, 1, 0);
1073
+
1074
+ rc_runtime_destroy(&runtime);
1075
+ }
1076
+
1077
+ static void test_multiple_achievements_ignore_triggered_and_inactive()
1078
+ {
1079
+ uint8_t ram[] = { 0, 1, 2, 3, 4, 5, 6, 7 };
1080
+ uint8_t buffer[2048];
1081
+ memory_t memory;
1082
+ rc_runtime_t runtime;
1083
+
1084
+ memory.ram = ram;
1085
+ memory.size = sizeof(ram);
1086
+ setup_multiple_achievements(&runtime, &memory);
1087
+
1088
+ assert_serialize(&runtime, buffer, sizeof(buffer));
1089
+
1090
+ /* trigger achievement 3 */
1091
+ ram[0] = 3;
1092
+ assert_do_frame(&runtime, &memory);
1093
+ assert_achievement_state(&runtime, 3, RC_TRIGGER_STATE_TRIGGERED);
1094
+
1095
+ /* reset achievement 2 to inactive */
1096
+ find_trigger(&runtime, 2)->state = RC_TRIGGER_STATE_INACTIVE;
1097
+
1098
+ reset_runtime(&runtime);
1099
+ assert_deserialize(&runtime, buffer);
1100
+
1101
+ assert_memref(&runtime, 0, 0, 0, 0);
1102
+ assert_memref(&runtime, 1, 4, 4, 1);
1103
+ assert_memref(&runtime, 2, 7, 7, 2);
1104
+ assert_memref(&runtime, 3, 9, 9, 3);
1105
+ assert_memref(&runtime, 4, 1, 4, 4);
1106
+ assert_achievement_state(&runtime, 1, RC_TRIGGER_STATE_ACTIVE);
1107
+ assert_achievement_state(&runtime, 2, RC_TRIGGER_STATE_INACTIVE);
1108
+ assert_achievement_state(&runtime, 3, RC_TRIGGER_STATE_TRIGGERED);
1109
+ assert_achievement_state(&runtime, 4, RC_TRIGGER_STATE_ACTIVE);
1110
+ assert_hitcount(&runtime, 1, 0, 0, 4);
1111
+ assert_hitcount(&runtime, 1, 0, 1, 0);
1112
+ assert_hitcount(&runtime, 2, 0, 0, 0xFF); /* inactive achievement should be ignored */
1113
+ assert_hitcount(&runtime, 2, 0, 1, 0xFF);
1114
+ assert_hitcount(&runtime, 3, 0, 0, 0xFF); /* triggered achievement should be ignored */
1115
+ assert_hitcount(&runtime, 3, 0, 1, 0xFF);
1116
+ assert_hitcount(&runtime, 4, 0, 0, 1);
1117
+ assert_hitcount(&runtime, 4, 0, 1, 0);
1118
+
1119
+ rc_runtime_destroy(&runtime);
1120
+ }
1121
+
1122
+ static void test_multiple_achievements_overwrite_waiting()
1123
+ {
1124
+ uint8_t ram[] = { 0, 1, 2, 3, 4, 5, 6, 7 };
1125
+ uint8_t buffer[2048];
1126
+ memory_t memory;
1127
+ rc_runtime_t runtime;
1128
+
1129
+ memory.ram = ram;
1130
+ memory.size = sizeof(ram);
1131
+ setup_multiple_achievements(&runtime, &memory);
1132
+
1133
+ assert_serialize(&runtime, buffer, sizeof(buffer));
1134
+
1135
+ /* reset achievement 2 to waiting */
1136
+ rc_reset_trigger(find_trigger(&runtime, 2));
1137
+ assert_achievement_state(&runtime, 2, RC_TRIGGER_STATE_WAITING);
1138
+
1139
+ reset_runtime(&runtime);
1140
+ assert_deserialize(&runtime, buffer);
1141
+
1142
+ assert_achievement_state(&runtime, 1, RC_TRIGGER_STATE_ACTIVE);
1143
+ assert_achievement_state(&runtime, 2, RC_TRIGGER_STATE_ACTIVE);
1144
+ assert_achievement_state(&runtime, 3, RC_TRIGGER_STATE_ACTIVE);
1145
+ assert_achievement_state(&runtime, 4, RC_TRIGGER_STATE_ACTIVE);
1146
+ assert_hitcount(&runtime, 1, 0, 0, 4);
1147
+ assert_hitcount(&runtime, 1, 0, 1, 0);
1148
+ assert_hitcount(&runtime, 2, 0, 0, 3); /* waiting achievement should be set back to active */
1149
+ assert_hitcount(&runtime, 2, 0, 1, 0);
1150
+ assert_hitcount(&runtime, 3, 0, 0, 2);
1151
+ assert_hitcount(&runtime, 3, 0, 1, 0);
1152
+ assert_hitcount(&runtime, 4, 0, 0, 1);
1153
+ assert_hitcount(&runtime, 4, 0, 1, 0);
1154
+
1155
+ rc_runtime_destroy(&runtime);
1156
+ }
1157
+
1158
+ static void test_multiple_achievements_reactivate_waiting()
1159
+ {
1160
+ uint8_t ram[] = { 0, 1, 2, 3, 4, 5, 6, 7 };
1161
+ uint8_t buffer[2048];
1162
+ memory_t memory;
1163
+ rc_runtime_t runtime;
1164
+
1165
+ memory.ram = ram;
1166
+ memory.size = sizeof(ram);
1167
+ setup_multiple_achievements(&runtime, &memory);
1168
+
1169
+ /* reset achievement 2 to waiting */
1170
+ rc_reset_trigger(find_trigger(&runtime, 2));
1171
+ assert_achievement_state(&runtime, 2, RC_TRIGGER_STATE_WAITING);
1172
+
1173
+ assert_serialize(&runtime, buffer, sizeof(buffer));
1174
+
1175
+ /* reactivate achievement 2 */
1176
+ assert_do_frame(&runtime, &memory);
1177
+ assert_achievement_state(&runtime, 2, RC_TRIGGER_STATE_ACTIVE);
1178
+
1179
+ reset_runtime(&runtime);
1180
+ assert_deserialize(&runtime, buffer);
1181
+
1182
+ assert_achievement_state(&runtime, 1, RC_TRIGGER_STATE_ACTIVE);
1183
+ assert_achievement_state(&runtime, 2, RC_TRIGGER_STATE_WAITING);
1184
+ assert_achievement_state(&runtime, 3, RC_TRIGGER_STATE_ACTIVE);
1185
+ assert_achievement_state(&runtime, 4, RC_TRIGGER_STATE_ACTIVE);
1186
+ assert_hitcount(&runtime, 1, 0, 0, 4);
1187
+ assert_hitcount(&runtime, 1, 0, 1, 0);
1188
+ assert_hitcount(&runtime, 2, 0, 0, 0); /* active achievement should be set back to waiting */
1189
+ assert_hitcount(&runtime, 2, 0, 1, 0);
1190
+ assert_hitcount(&runtime, 3, 0, 0, 2);
1191
+ assert_hitcount(&runtime, 3, 0, 1, 0);
1192
+ assert_hitcount(&runtime, 4, 0, 0, 1);
1193
+ assert_hitcount(&runtime, 4, 0, 1, 0);
1194
+
1195
+ rc_runtime_destroy(&runtime);
1196
+ }
1197
+
1198
+ static void test_multiple_achievements_paused_and_primed()
1199
+ {
1200
+ uint8_t ram[] = { 0, 1, 2, 3, 4, 5, 6, 7 };
1201
+ uint8_t buffer[2048];
1202
+ uint8_t buffer2[2048];
1203
+ memory_t memory;
1204
+ rc_runtime_t runtime;
1205
+
1206
+ memory.ram = ram;
1207
+ memory.size = sizeof(ram);
1208
+ rc_runtime_init(&runtime);
1209
+
1210
+ assert_activate_achievement(&runtime, 1, "0xH0001=4_0xH0000=1");
1211
+ assert_activate_achievement(&runtime, 2, "0xH0002=7_0xH0000=2_P:0xH0005=4");
1212
+ assert_activate_achievement(&runtime, 3, "0xH0003=9_0xH0000=3");
1213
+ assert_activate_achievement(&runtime, 4, "0xH0004=1_T:0xH0000=4");
1214
+
1215
+ assert_do_frame(&runtime, &memory);
1216
+ ram[1] = 4;
1217
+ ram[2] = 7;
1218
+ ram[3] = 9;
1219
+ ram[4] = 1;
1220
+ ram[5] = 4;
1221
+ assert_do_frame(&runtime, &memory);
1222
+ assert_achievement_state(&runtime, 1, RC_TRIGGER_STATE_ACTIVE);
1223
+ assert_achievement_state(&runtime, 2, RC_TRIGGER_STATE_PAUSED);
1224
+ assert_achievement_state(&runtime, 3, RC_TRIGGER_STATE_ACTIVE);
1225
+ assert_achievement_state(&runtime, 4, RC_TRIGGER_STATE_PRIMED);
1226
+ ASSERT_TRUE(find_trigger(&runtime, 2)->requirement->is_paused);
1227
+
1228
+ assert_serialize(&runtime, buffer, sizeof(buffer));
1229
+
1230
+ /* unpause achievement 2 and unprime achievement 4 */
1231
+ ram[5] = 2;
1232
+ ram[4] = 2;
1233
+ assert_do_frame(&runtime, &memory);
1234
+ assert_achievement_state(&runtime, 1, RC_TRIGGER_STATE_ACTIVE);
1235
+ assert_achievement_state(&runtime, 2, RC_TRIGGER_STATE_ACTIVE);
1236
+ assert_achievement_state(&runtime, 3, RC_TRIGGER_STATE_ACTIVE);
1237
+ assert_achievement_state(&runtime, 4, RC_TRIGGER_STATE_ACTIVE);
1238
+ ASSERT_FALSE(find_trigger(&runtime, 2)->requirement->is_paused);
1239
+
1240
+ assert_serialize(&runtime, buffer2, sizeof(buffer2));
1241
+
1242
+ reset_runtime(&runtime);
1243
+ assert_deserialize(&runtime, buffer);
1244
+
1245
+ assert_achievement_state(&runtime, 1, RC_TRIGGER_STATE_ACTIVE);
1246
+ assert_achievement_state(&runtime, 2, RC_TRIGGER_STATE_PAUSED);
1247
+ assert_achievement_state(&runtime, 3, RC_TRIGGER_STATE_ACTIVE);
1248
+ assert_achievement_state(&runtime, 4, RC_TRIGGER_STATE_PRIMED);
1249
+ ASSERT_TRUE(find_trigger(&runtime, 2)->requirement->is_paused);
1250
+
1251
+ reset_runtime(&runtime);
1252
+ assert_deserialize(&runtime, buffer2);
1253
+
1254
+ assert_achievement_state(&runtime, 1, RC_TRIGGER_STATE_ACTIVE);
1255
+ assert_achievement_state(&runtime, 2, RC_TRIGGER_STATE_ACTIVE);
1256
+ assert_achievement_state(&runtime, 3, RC_TRIGGER_STATE_ACTIVE);
1257
+ assert_achievement_state(&runtime, 4, RC_TRIGGER_STATE_ACTIVE);
1258
+ ASSERT_FALSE(find_trigger(&runtime, 2)->requirement->is_paused);
1259
+
1260
+ rc_runtime_destroy(&runtime);
1261
+ }
1262
+
1263
+ static void test_multiple_achievements_deactivated_memrefs()
1264
+ {
1265
+ uint8_t ram[] = { 0, 1, 2, 3, 4, 5, 6, 7 };
1266
+ uint8_t buffer[2048];
1267
+ memory_t memory;
1268
+ rc_runtime_t runtime;
1269
+
1270
+ memory.ram = ram;
1271
+ memory.size = sizeof(ram);
1272
+ rc_runtime_init(&runtime);
1273
+
1274
+ assert_activate_achievement(&runtime, 1, "0xH0001=4_0xH0000=1");
1275
+ assert_activate_achievement(&runtime, 2, "0xH0001=5_0xH0000=2");
1276
+ assert_activate_achievement(&runtime, 3, "0xH0001=6_0xH0000=3");
1277
+
1278
+ ram[1] = 4;
1279
+ assert_do_frame(&runtime, &memory);
1280
+ assert_do_frame(&runtime, &memory);
1281
+ assert_do_frame(&runtime, &memory);
1282
+ ram[1] = 5;
1283
+ assert_do_frame(&runtime, &memory);
1284
+ assert_do_frame(&runtime, &memory);
1285
+ ram[1] = 6;
1286
+ assert_do_frame(&runtime, &memory);
1287
+
1288
+ assert_hitcount(&runtime, 1, 0, 0, 3);
1289
+ assert_hitcount(&runtime, 2, 0, 0, 2);
1290
+ assert_hitcount(&runtime, 3, 0, 0, 1);
1291
+
1292
+ /* deactivate an achievement with memrefs */
1293
+ ASSERT_NUM_EQUALS(runtime.trigger_count, 3);
1294
+ rc_runtime_deactivate_achievement(&runtime, 1);
1295
+ ASSERT_NUM_EQUALS(runtime.trigger_count, 2);
1296
+
1297
+ assert_serialize(&runtime, buffer, sizeof(buffer));
1298
+
1299
+ /* reactivate achievement 1 */
1300
+ assert_activate_achievement(&runtime, 1, "0xH0001=4_0xH0000=2");
1301
+
1302
+ reset_runtime(&runtime);
1303
+ assert_deserialize(&runtime, buffer);
1304
+
1305
+ assert_achievement_state(&runtime, 1, RC_TRIGGER_STATE_WAITING);
1306
+ assert_achievement_state(&runtime, 2, RC_TRIGGER_STATE_ACTIVE);
1307
+ assert_achievement_state(&runtime, 3, RC_TRIGGER_STATE_ACTIVE);
1308
+ assert_hitcount(&runtime, 1, 0, 0, 0);
1309
+ assert_hitcount(&runtime, 2, 0, 0, 2);
1310
+ assert_hitcount(&runtime, 3, 0, 0, 1);
1311
+
1312
+ rc_runtime_destroy(&runtime);
1313
+ }
1314
+
1315
+ static void test_multiple_achievements_deactivated_no_memrefs()
1316
+ {
1317
+ uint8_t ram[] = { 0, 1, 2, 3, 4, 5, 6, 7 };
1318
+ uint8_t buffer[2048];
1319
+ memory_t memory;
1320
+ rc_runtime_t runtime;
1321
+
1322
+ memory.ram = ram;
1323
+ memory.size = sizeof(ram);
1324
+ rc_runtime_init(&runtime);
1325
+
1326
+ assert_activate_achievement(&runtime, 1, "0xH0001=4_0xH0000=1");
1327
+ assert_activate_achievement(&runtime, 2, "0xH0001=5_0xH0000=2");
1328
+ assert_activate_achievement(&runtime, 3, "0xH0001=6_0xH0000=3");
1329
+
1330
+ ram[1] = 4;
1331
+ assert_do_frame(&runtime, &memory);
1332
+ assert_do_frame(&runtime, &memory);
1333
+ assert_do_frame(&runtime, &memory);
1334
+ ram[1] = 5;
1335
+ assert_do_frame(&runtime, &memory);
1336
+ assert_do_frame(&runtime, &memory);
1337
+ ram[1] = 6;
1338
+ assert_do_frame(&runtime, &memory);
1339
+
1340
+ assert_hitcount(&runtime, 1, 0, 0, 3);
1341
+ assert_hitcount(&runtime, 2, 0, 0, 2);
1342
+ assert_hitcount(&runtime, 3, 0, 0, 1);
1343
+
1344
+ /* deactivate an achievement without memrefs - trigger should be removed */
1345
+ ASSERT_NUM_EQUALS(runtime.trigger_count, 3);
1346
+ rc_runtime_deactivate_achievement(&runtime, 2);
1347
+ ASSERT_NUM_EQUALS(runtime.trigger_count, 2);
1348
+
1349
+ assert_serialize(&runtime, buffer, sizeof(buffer));
1350
+
1351
+ /* reactivate achievement 2 */
1352
+ assert_activate_achievement(&runtime, 2, "0xH0001=5_0xH0000=2");
1353
+
1354
+ reset_runtime(&runtime);
1355
+ assert_deserialize(&runtime, buffer);
1356
+
1357
+ assert_achievement_state(&runtime, 1, RC_TRIGGER_STATE_ACTIVE);
1358
+ assert_achievement_state(&runtime, 2, RC_TRIGGER_STATE_WAITING);
1359
+ assert_achievement_state(&runtime, 3, RC_TRIGGER_STATE_ACTIVE);
1360
+ assert_hitcount(&runtime, 1, 0, 0, 3);
1361
+ assert_hitcount(&runtime, 2, 0, 0, 0);
1362
+ assert_hitcount(&runtime, 3, 0, 0, 1);
1363
+
1364
+ rc_runtime_destroy(&runtime);
1365
+ }
1366
+
1367
+ static void test_single_leaderboard()
1368
+ {
1369
+ uint8_t ram[] = { 2, 3, 6 };
1370
+ uint8_t buffer[2048];
1371
+ memory_t memory;
1372
+ rc_runtime_t runtime;
1373
+
1374
+ memory.ram = ram;
1375
+ memory.size = sizeof(ram);
1376
+
1377
+ rc_runtime_init(&runtime);
1378
+
1379
+ assert_activate_leaderboard(&runtime, 1, "STA:0xH0001=4::SUB:0xH0001=5.4.::CAN:0xH0001=0.4.::VAL:0xH0002");
1380
+ assert_do_frame(&runtime, &memory);
1381
+ ram[1] = 4;
1382
+ assert_do_frame(&runtime, &memory);
1383
+ assert_do_frame(&runtime, &memory);
1384
+ assert_do_frame(&runtime, &memory);
1385
+ ram[1] = 5;
1386
+ assert_do_frame(&runtime, &memory);
1387
+ assert_do_frame(&runtime, &memory);
1388
+
1389
+ assert_memref(&runtime, 1, 5, 5, 4);
1390
+ assert_memref(&runtime, 2, 6, 6, 0);
1391
+ assert_sta_hitcount(&runtime, 1, 0, 0, 3);
1392
+ assert_sub_hitcount(&runtime, 1, 0, 0, 2);
1393
+ assert_can_hitcount(&runtime, 1, 0, 0, 0);
1394
+ ASSERT_NUM_EQUALS(find_lboard(&runtime, 1)->state, RC_LBOARD_STATE_STARTED);
1395
+ ASSERT_NUM_EQUALS(find_lboard(&runtime, 1)->value.value.value, 6);
1396
+ ASSERT_NUM_EQUALS(find_lboard(&runtime, 1)->value.value.prior, 0);
1397
+
1398
+ assert_serialize(&runtime, buffer, sizeof(buffer));
1399
+
1400
+ reset_runtime(&runtime);
1401
+ assert_deserialize(&runtime, buffer);
1402
+
1403
+ assert_memref(&runtime, 1, 5, 5, 4);
1404
+ assert_memref(&runtime, 2, 6, 6, 0);
1405
+ assert_sta_hitcount(&runtime, 1, 0, 0, 3);
1406
+ assert_sub_hitcount(&runtime, 1, 0, 0, 2);
1407
+ assert_can_hitcount(&runtime, 1, 0, 0, 0);
1408
+ ASSERT_NUM_EQUALS(find_lboard(&runtime, 1)->state, RC_LBOARD_STATE_STARTED);
1409
+ ASSERT_NUM_EQUALS(find_lboard(&runtime, 1)->value.value.value, 6);
1410
+ ASSERT_NUM_EQUALS(find_lboard(&runtime, 1)->value.value.prior, 0);
1411
+
1412
+ rc_runtime_destroy(&runtime);
1413
+ }
1414
+
1415
+ static void test_multiple_leaderboards()
1416
+ {
1417
+ uint8_t ram[] = { 2, 3, 6 };
1418
+ uint8_t buffer[2048];
1419
+ memory_t memory;
1420
+ rc_runtime_t runtime;
1421
+
1422
+ memory.ram = ram;
1423
+ memory.size = sizeof(ram);
1424
+
1425
+ rc_runtime_init(&runtime);
1426
+
1427
+ assert_activate_leaderboard(&runtime, 1, "STA:0xH0001=4::SUB:0xH0001=5.4.::CAN:0xH0001=0.4.::VAL:0xH0002");
1428
+ assert_activate_leaderboard(&runtime, 2, "STA:0xH0001=5::SUB:0xH0002=5::CAN:0xH0001=0::VAL:0xH0000");
1429
+ assert_do_frame(&runtime, &memory);
1430
+ ram[1] = 4;
1431
+ assert_do_frame(&runtime, &memory);
1432
+ assert_do_frame(&runtime, &memory);
1433
+ assert_do_frame(&runtime, &memory);
1434
+ ram[1] = 5;
1435
+ assert_do_frame(&runtime, &memory);
1436
+ assert_do_frame(&runtime, &memory);
1437
+
1438
+ assert_sta_hitcount(&runtime, 1, 0, 0, 3);
1439
+ assert_sub_hitcount(&runtime, 1, 0, 0, 2);
1440
+ assert_sta_hitcount(&runtime, 2, 0, 0, 2);
1441
+ assert_sub_hitcount(&runtime, 2, 0, 0, 0);
1442
+ ASSERT_NUM_EQUALS(find_lboard(&runtime, 1)->state, RC_LBOARD_STATE_STARTED);
1443
+ ASSERT_NUM_EQUALS(find_lboard(&runtime, 1)->value.value.value, 6);
1444
+ ASSERT_NUM_EQUALS(find_lboard(&runtime, 1)->value.value.prior, 0);
1445
+ ASSERT_NUM_EQUALS(find_lboard(&runtime, 2)->state, RC_LBOARD_STATE_STARTED);
1446
+ ASSERT_NUM_EQUALS(find_lboard(&runtime, 2)->value.value.value, 2);
1447
+ ASSERT_NUM_EQUALS(find_lboard(&runtime, 2)->value.value.prior, 0);
1448
+
1449
+ assert_serialize(&runtime, buffer, sizeof(buffer));
1450
+
1451
+ assert_do_frame(&runtime, &memory);
1452
+ assert_do_frame(&runtime, &memory);
1453
+ assert_deserialize(&runtime, buffer);
1454
+
1455
+ assert_sta_hitcount(&runtime, 1, 0, 0, 3);
1456
+ assert_sub_hitcount(&runtime, 1, 0, 0, 2);
1457
+ assert_sta_hitcount(&runtime, 2, 0, 0, 2);
1458
+ assert_sub_hitcount(&runtime, 2, 0, 0, 0);
1459
+ ASSERT_NUM_EQUALS(find_lboard(&runtime, 1)->state, RC_LBOARD_STATE_STARTED);
1460
+ ASSERT_NUM_EQUALS(find_lboard(&runtime, 1)->value.value.value, 6);
1461
+ ASSERT_NUM_EQUALS(find_lboard(&runtime, 1)->value.value.prior, 0);
1462
+ ASSERT_NUM_EQUALS(find_lboard(&runtime, 2)->state, RC_LBOARD_STATE_STARTED);
1463
+ ASSERT_NUM_EQUALS(find_lboard(&runtime, 2)->value.value.value, 2);
1464
+ ASSERT_NUM_EQUALS(find_lboard(&runtime, 2)->value.value.prior, 0);
1465
+
1466
+ rc_runtime_destroy(&runtime);
1467
+ }
1468
+
1469
+ static void test_multiple_leaderboards_ignore_inactive()
1470
+ {
1471
+ uint8_t ram[] = { 2, 3, 6 };
1472
+ uint8_t buffer[2048];
1473
+ memory_t memory;
1474
+ rc_runtime_t runtime;
1475
+
1476
+ memory.ram = ram;
1477
+ memory.size = sizeof(ram);
1478
+
1479
+ rc_runtime_init(&runtime);
1480
+
1481
+ assert_activate_leaderboard(&runtime, 1, "STA:0xH0001=4::SUB:0xH0001=5.4.::CAN:0xH0001=0.4.::VAL:0xH0002");
1482
+ assert_activate_leaderboard(&runtime, 2, "STA:0xH0001=5::SUB:0xH0002=5::CAN:0xH0001=0::VAL:0xH0000");
1483
+ assert_do_frame(&runtime, &memory);
1484
+ ram[1] = 4;
1485
+ assert_do_frame(&runtime, &memory);
1486
+ assert_do_frame(&runtime, &memory);
1487
+ assert_do_frame(&runtime, &memory);
1488
+ ram[1] = 5;
1489
+ assert_do_frame(&runtime, &memory);
1490
+ assert_do_frame(&runtime, &memory);
1491
+
1492
+ find_lboard(&runtime, 1)->state = RC_LBOARD_STATE_DISABLED;
1493
+ assert_sta_hitcount(&runtime, 1, 0, 0, 3);
1494
+ assert_sub_hitcount(&runtime, 1, 0, 0, 2);
1495
+ assert_sta_hitcount(&runtime, 2, 0, 0, 2);
1496
+ assert_sub_hitcount(&runtime, 2, 0, 0, 0);
1497
+ ASSERT_NUM_EQUALS(find_lboard(&runtime, 1)->state, RC_LBOARD_STATE_DISABLED);
1498
+ ASSERT_NUM_EQUALS(find_lboard(&runtime, 1)->value.value.value, 6);
1499
+ ASSERT_NUM_EQUALS(find_lboard(&runtime, 1)->value.value.prior, 0);
1500
+ ASSERT_NUM_EQUALS(find_lboard(&runtime, 2)->state, RC_LBOARD_STATE_STARTED);
1501
+ ASSERT_NUM_EQUALS(find_lboard(&runtime, 2)->value.value.value, 2);
1502
+ ASSERT_NUM_EQUALS(find_lboard(&runtime, 2)->value.value.prior, 0);
1503
+
1504
+ assert_serialize(&runtime, buffer, sizeof(buffer));
1505
+
1506
+ find_lboard(&runtime, 1)->state = RC_LBOARD_STATE_ACTIVE;
1507
+ assert_do_frame(&runtime, &memory);
1508
+ assert_do_frame(&runtime, &memory);
1509
+ assert_deserialize(&runtime, buffer);
1510
+
1511
+ /* non-serialized leaderboard should be reset */
1512
+ assert_sta_hitcount(&runtime, 1, 0, 0, 0);
1513
+ assert_sub_hitcount(&runtime, 1, 0, 0, 0);
1514
+ ASSERT_NUM_EQUALS(find_lboard(&runtime, 1)->state, RC_LBOARD_STATE_WAITING);
1515
+ ASSERT_NUM_EQUALS(find_lboard(&runtime, 1)->value.value.value, 0);
1516
+ ASSERT_NUM_EQUALS(find_lboard(&runtime, 1)->value.value.prior, 0);
1517
+
1518
+ /* serialized leaderboard should be restored */
1519
+ assert_sta_hitcount(&runtime, 2, 0, 0, 2);
1520
+ assert_sub_hitcount(&runtime, 2, 0, 0, 0);
1521
+ ASSERT_NUM_EQUALS(find_lboard(&runtime, 2)->state, RC_LBOARD_STATE_STARTED);
1522
+ ASSERT_NUM_EQUALS(find_lboard(&runtime, 2)->value.value.value, 2);
1523
+ ASSERT_NUM_EQUALS(find_lboard(&runtime, 2)->value.value.prior, 0);
1524
+
1525
+ rc_runtime_destroy(&runtime);
1526
+ }
1527
+
1528
+ static void test_multiple_leaderboards_ignore_modified()
1529
+ {
1530
+ uint8_t ram[] = { 2, 3, 6 };
1531
+ uint8_t buffer[2048];
1532
+ memory_t memory;
1533
+ rc_runtime_t runtime;
1534
+
1535
+ memory.ram = ram;
1536
+ memory.size = sizeof(ram);
1537
+
1538
+ rc_runtime_init(&runtime);
1539
+
1540
+ assert_activate_leaderboard(&runtime, 1, "STA:0xH0001=4::SUB:0xH0001=5.4.::CAN:0xH0001=0.4.::VAL:0xH0002");
1541
+ assert_activate_leaderboard(&runtime, 2, "STA:0xH0001=5::SUB:0xH0002=5::CAN:0xH0001=0::VAL:0xH0000");
1542
+ assert_do_frame(&runtime, &memory);
1543
+ ram[1] = 4;
1544
+ assert_do_frame(&runtime, &memory);
1545
+ assert_do_frame(&runtime, &memory);
1546
+ assert_do_frame(&runtime, &memory);
1547
+ ram[1] = 5;
1548
+ assert_do_frame(&runtime, &memory);
1549
+ assert_do_frame(&runtime, &memory);
1550
+
1551
+ assert_sta_hitcount(&runtime, 1, 0, 0, 3);
1552
+ assert_sub_hitcount(&runtime, 1, 0, 0, 2);
1553
+ assert_sta_hitcount(&runtime, 2, 0, 0, 2);
1554
+ assert_sub_hitcount(&runtime, 2, 0, 0, 0);
1555
+ ASSERT_NUM_EQUALS(find_lboard(&runtime, 1)->state, RC_LBOARD_STATE_STARTED);
1556
+ ASSERT_NUM_EQUALS(find_lboard(&runtime, 1)->value.value.value, 6);
1557
+ ASSERT_NUM_EQUALS(find_lboard(&runtime, 1)->value.value.prior, 0);
1558
+ ASSERT_NUM_EQUALS(find_lboard(&runtime, 2)->state, RC_LBOARD_STATE_STARTED);
1559
+ ASSERT_NUM_EQUALS(find_lboard(&runtime, 2)->value.value.value, 2);
1560
+ ASSERT_NUM_EQUALS(find_lboard(&runtime, 2)->value.value.prior, 0);
1561
+
1562
+ assert_serialize(&runtime, buffer, sizeof(buffer));
1563
+
1564
+ assert_activate_leaderboard(&runtime, 1, "STA:0xH0001=4::SUB:0xH0001=5.4.::CAN:0xH0001=0.3.::VAL:0xH0002");
1565
+ assert_do_frame(&runtime, &memory);
1566
+ assert_do_frame(&runtime, &memory);
1567
+ assert_deserialize(&runtime, buffer);
1568
+
1569
+ /* modified leaderboard should be reset */
1570
+ assert_sta_hitcount(&runtime, 1, 0, 0, 0);
1571
+ assert_sub_hitcount(&runtime, 1, 0, 0, 0);
1572
+ ASSERT_NUM_EQUALS(find_lboard(&runtime, 1)->state, RC_LBOARD_STATE_WAITING);
1573
+ ASSERT_NUM_EQUALS(find_lboard(&runtime, 1)->value.value.value, 0);
1574
+ ASSERT_NUM_EQUALS(find_lboard(&runtime, 1)->value.value.prior, 0);
1575
+
1576
+ /* serialized leaderboard should be restored */
1577
+ assert_sta_hitcount(&runtime, 2, 0, 0, 2);
1578
+ assert_sub_hitcount(&runtime, 2, 0, 0, 0);
1579
+ ASSERT_NUM_EQUALS(find_lboard(&runtime, 2)->state, RC_LBOARD_STATE_STARTED);
1580
+ ASSERT_NUM_EQUALS(find_lboard(&runtime, 2)->value.value.value, 2);
1581
+ ASSERT_NUM_EQUALS(find_lboard(&runtime, 2)->value.value.prior, 0);
1582
+
1583
+ rc_runtime_destroy(&runtime);
1584
+ }
1585
+
1586
+ static void test_rich_presence_none()
1587
+ {
1588
+ uint8_t buffer[2048];
1589
+ rc_runtime_t runtime;
1590
+ rc_runtime_init(&runtime);
1591
+
1592
+ assert_serialize(&runtime, buffer, sizeof(buffer));
1593
+
1594
+ reset_runtime(&runtime);
1595
+ assert_deserialize(&runtime, buffer);
1596
+
1597
+ rc_runtime_destroy(&runtime);
1598
+ }
1599
+
1600
+ static void test_rich_presence_static()
1601
+ {
1602
+ uint8_t buffer[2048];
1603
+ rc_runtime_t runtime;
1604
+ rc_runtime_init(&runtime);
1605
+
1606
+ assert_activate_rich_presence(&runtime, "Display:\nTest");
1607
+
1608
+ assert_serialize(&runtime, buffer, sizeof(buffer));
1609
+
1610
+ reset_runtime(&runtime);
1611
+ assert_deserialize(&runtime, buffer);
1612
+
1613
+ rc_runtime_destroy(&runtime);
1614
+ }
1615
+
1616
+ static void test_rich_presence_simple_lookup()
1617
+ {
1618
+ uint8_t ram[] = { 0, 1, 2, 3, 4, 5, 6, 7 };
1619
+ uint8_t buffer[2048];
1620
+ memory_t memory;
1621
+ rc_runtime_t runtime;
1622
+
1623
+ memory.ram = ram;
1624
+ memory.size = sizeof(ram);
1625
+ rc_runtime_init(&runtime);
1626
+
1627
+ assert_activate_rich_presence(&runtime, "Display:\n@Number(p0xH02)");
1628
+ assert_do_frame(&runtime, &memory); /* prev[2] = 0 */
1629
+
1630
+ ram[2] = 4;
1631
+ assert_do_frame(&runtime, &memory); /* prev[2] = 2 */
1632
+
1633
+ ram[2] = 8;
1634
+ assert_do_frame(&runtime, &memory); /* prev[2] = 4 */
1635
+
1636
+ assert_serialize(&runtime, buffer, sizeof(buffer));
1637
+
1638
+ ram[2] = 12;
1639
+ assert_do_frame(&runtime, &memory); /* prev[2] = 8 */
1640
+
1641
+ reset_runtime(&runtime);
1642
+ assert_deserialize(&runtime, buffer);
1643
+
1644
+ /* deserialized should remember prev[2] = 4 */
1645
+ assert_richpresence_output(&runtime, &memory, "4");
1646
+
1647
+ rc_runtime_destroy(&runtime);
1648
+ }
1649
+
1650
+ static void test_rich_presence_tracked_hits()
1651
+ {
1652
+ uint8_t ram[] = { 0, 1, 2, 3, 4, 5, 6, 7 };
1653
+ uint8_t buffer[2048];
1654
+ memory_t memory;
1655
+ rc_runtime_t runtime;
1656
+
1657
+ memory.ram = ram;
1658
+ memory.size = sizeof(ram);
1659
+ rc_runtime_init(&runtime);
1660
+
1661
+ assert_activate_rich_presence(&runtime, "Display:\n@Number(M:0xH02=2)");
1662
+ assert_do_frame(&runtime, &memory); /* count = 1 */
1663
+ assert_do_frame(&runtime, &memory); /* count = 2 */
1664
+ assert_do_frame(&runtime, &memory); /* count = 3 */
1665
+
1666
+ assert_serialize(&runtime, buffer, sizeof(buffer));
1667
+
1668
+ assert_do_frame(&runtime, &memory); /* count = 4 */
1669
+
1670
+ reset_runtime(&runtime);
1671
+ assert_deserialize(&runtime, buffer);
1672
+
1673
+ /* deserialized should remember count = 3 */
1674
+ assert_richpresence_output(&runtime, &memory, "3");
1675
+
1676
+ rc_runtime_destroy(&runtime);
1677
+ }
1678
+
1679
+ static void test_rich_presence_tracked_hits_md5_changed()
1680
+ {
1681
+ uint8_t ram[] = { 0, 1, 2, 3, 4, 5, 6, 7 };
1682
+ uint8_t buffer[2048];
1683
+ memory_t memory;
1684
+ rc_runtime_t runtime;
1685
+
1686
+ memory.ram = ram;
1687
+ memory.size = sizeof(ram);
1688
+ rc_runtime_init(&runtime);
1689
+
1690
+ assert_activate_rich_presence(&runtime, "Display:\n@Number(M:0xH02=2)");
1691
+ assert_do_frame(&runtime, &memory); /* count = 1 */
1692
+ assert_do_frame(&runtime, &memory); /* count = 2 */
1693
+ assert_do_frame(&runtime, &memory); /* count = 3 */
1694
+
1695
+ assert_serialize(&runtime, buffer, sizeof(buffer));
1696
+
1697
+ assert_do_frame(&runtime, &memory); /* count = 4 */
1698
+
1699
+ assert_activate_rich_presence(&runtime, "Display:\n@Number(M:0xH02=2)!");
1700
+ reset_runtime(&runtime);
1701
+ assert_deserialize(&runtime, buffer);
1702
+
1703
+ /* md5 changed, but variable is stored external to RP, 3 should be remembered */
1704
+ assert_richpresence_output(&runtime, &memory, "3!");
1705
+
1706
+ rc_runtime_destroy(&runtime);
1707
+ }
1708
+
1709
+ static void test_rich_presence_conditional_display()
1710
+ {
1711
+ uint8_t ram[] = { 0, 1, 2, 3, 4, 5, 6, 7 };
1712
+ uint8_t buffer[2048];
1713
+ memory_t memory;
1714
+ rc_runtime_t runtime;
1715
+
1716
+ memory.ram = ram;
1717
+ memory.size = sizeof(ram);
1718
+ rc_runtime_init(&runtime);
1719
+
1720
+ assert_activate_rich_presence(&runtime, "Display:\n?0xH02=2.3.?Three\nLess");
1721
+ assert_do_frame(&runtime, &memory); /* count = 1 */
1722
+ assert_do_frame(&runtime, &memory); /* count = 2 */
1723
+
1724
+ assert_serialize(&runtime, buffer, sizeof(buffer));
1725
+
1726
+ assert_do_frame(&runtime, &memory); /* count = 3 */
1727
+ assert_do_frame(&runtime, &memory); /* count = 4 */
1728
+ assert_richpresence_output(&runtime, &memory, "Three");
1729
+
1730
+ reset_runtime(&runtime);
1731
+ assert_deserialize(&runtime, buffer);
1732
+
1733
+ /* deserialized should remember count = 2 */
1734
+ assert_richpresence_output(&runtime, &memory, "Less");
1735
+
1736
+ rc_runtime_destroy(&runtime);
1737
+ }
1738
+
1739
+ static void test_rich_presence_conditional_display_md5_changed()
1740
+ {
1741
+ uint8_t ram[] = { 0, 1, 2, 3, 4, 5, 6, 7 };
1742
+ uint8_t buffer[2048];
1743
+ memory_t memory;
1744
+ rc_runtime_t runtime;
1745
+
1746
+ memory.ram = ram;
1747
+ memory.size = sizeof(ram);
1748
+ rc_runtime_init(&runtime);
1749
+
1750
+ assert_activate_rich_presence(&runtime, "Display:\n?0xH02=2.3.?Three\nLess");
1751
+ assert_do_frame(&runtime, &memory); /* count = 1 */
1752
+ assert_do_frame(&runtime, &memory); /* count = 2 */
1753
+
1754
+ assert_serialize(&runtime, buffer, sizeof(buffer));
1755
+
1756
+ assert_do_frame(&runtime, &memory); /* count = 3 */
1757
+ assert_do_frame(&runtime, &memory); /* count = 4 */
1758
+ assert_richpresence_output(&runtime, &memory, "Three");
1759
+
1760
+ reset_runtime(&runtime);
1761
+ assert_activate_rich_presence(&runtime, "Display:\n?0xH02=2.3.?Three!\nLess");
1762
+ assert_deserialize(&runtime, buffer);
1763
+
1764
+ /* md5 changed, hit count should be discarded */
1765
+ assert_richpresence_output(&runtime, &memory, "Less");
1766
+
1767
+ assert_do_frame(&runtime, &memory); /* count = 1 */
1768
+ assert_do_frame(&runtime, &memory); /* count = 2 */
1769
+ assert_richpresence_output(&runtime, &memory, "Less");
1770
+
1771
+ assert_do_frame(&runtime, &memory); /* count = 3 */
1772
+ assert_richpresence_output(&runtime, &memory, "Three!");
1773
+
1774
+ rc_runtime_destroy(&runtime);
1775
+ }
1776
+
1777
+ /* ======================================================== */
1778
+
1779
+ void test_runtime_progress(void) {
1780
+ TEST_SUITE_BEGIN();
1781
+
1782
+ TEST(test_empty);
1783
+ TEST(test_single_achievement);
1784
+ TEST(test_invalid_marker);
1785
+ TEST(test_invalid_memref_chunk_id);
1786
+ TEST(test_modified_data);
1787
+ TEST(test_single_achievement_deactivated);
1788
+ TEST(test_single_achievement_md5_changed);
1789
+ TEST(test_single_achievement_sized);
1790
+ TEST(test_empty_sized);
1791
+
1792
+ TEST(test_no_core_group);
1793
+ TEST(test_memref_shared_address);
1794
+ TEST(test_memref_addsource);
1795
+ TEST(test_memref_indirect);
1796
+ TEST(test_memref_indirect_delta);
1797
+ TEST(test_memref_double_indirect);
1798
+
1799
+ TEST(test_multiple_achievements);
1800
+ TEST(test_multiple_achievements_ignore_triggered_and_inactive);
1801
+ TEST(test_multiple_achievements_overwrite_waiting);
1802
+ TEST(test_multiple_achievements_reactivate_waiting);
1803
+ TEST(test_multiple_achievements_paused_and_primed);
1804
+ TEST(test_multiple_achievements_deactivated_memrefs);
1805
+ TEST(test_multiple_achievements_deactivated_no_memrefs);
1806
+
1807
+ TEST(test_single_leaderboard);
1808
+ TEST(test_multiple_leaderboards);
1809
+ TEST(test_multiple_leaderboards_ignore_inactive);
1810
+ TEST(test_multiple_leaderboards_ignore_modified);
1811
+
1812
+ TEST(test_rich_presence_none);
1813
+ TEST(test_rich_presence_static);
1814
+ TEST(test_rich_presence_simple_lookup);
1815
+ TEST(test_rich_presence_tracked_hits);
1816
+ TEST(test_rich_presence_tracked_hits_md5_changed);
1817
+ TEST(test_rich_presence_conditional_display);
1818
+ TEST(test_rich_presence_conditional_display_md5_changed);
1819
+
1820
+ TEST_SUITE_END();
1821
+ }