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,1564 @@
1
+ #include "rc_internal.h"
2
+
3
+ #include "../test_framework.h"
4
+ #include "mock_memory.h"
5
+
6
+ #include "../src/rc_compat.h"
7
+
8
+ static void _assert_parse_richpresence(rc_richpresence_t** richpresence, void* buffer, size_t buffer_size, const char* script) {
9
+ int size;
10
+ unsigned* overflow;
11
+ *richpresence = NULL;
12
+
13
+ size = rc_richpresence_size(script);
14
+ ASSERT_NUM_GREATER(size, 0);
15
+ ASSERT_NUM_LESS_EQUALS(size + 4, buffer_size);
16
+
17
+ overflow = (unsigned*)(((char*)buffer) + size);
18
+ *overflow = 0xCDCDCDCD;
19
+
20
+ *richpresence = rc_parse_richpresence(buffer, script, NULL, 0);
21
+ ASSERT_PTR_NOT_NULL(*richpresence);
22
+
23
+ if (*overflow != 0xCDCDCDCD) {
24
+ ASSERT_FAIL("write past end of buffer");
25
+ }
26
+ }
27
+ #define assert_parse_richpresence(richpresence_out, buffer, script) ASSERT_HELPER(_assert_parse_richpresence(richpresence_out, buffer, sizeof(buffer), script), "assert_parse_richpresence")
28
+
29
+ static void _assert_richpresence_output(rc_richpresence_t* richpresence, memory_t* memory, const char* expected_display_string) {
30
+ char output[256];
31
+ int result;
32
+
33
+ result = rc_evaluate_richpresence(richpresence, 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(richpresence, memory, expected_display_string) ASSERT_HELPER(_assert_richpresence_output(richpresence, memory, expected_display_string), "assert_richpresence_output")
38
+
39
+ static void test_empty_script() {
40
+ int lines;
41
+ int result = rc_richpresence_size_lines("", &lines);
42
+ ASSERT_NUM_EQUALS(result, RC_MISSING_DISPLAY_STRING);
43
+ ASSERT_NUM_EQUALS(lines, 1);
44
+ }
45
+
46
+ static void test_simple_richpresence(const char* script, const char* expected_display_string) {
47
+ uint8_t ram[] = { 0x00, 0x12, 0x34, 0xAB, 0x56 };
48
+ memory_t memory;
49
+ rc_richpresence_t* richpresence;
50
+ char buffer[1024];
51
+
52
+ memory.ram = ram;
53
+ memory.size = sizeof(ram);
54
+
55
+ assert_parse_richpresence(&richpresence, buffer, script);
56
+ assert_richpresence_output(richpresence, &memory, expected_display_string);
57
+ }
58
+
59
+ static void assert_buffer_boundary(rc_richpresence_t* richpresence, memory_t* memory, int buffersize, int expected_result, const char* expected_display_string) {
60
+ char output[256];
61
+ int result;
62
+ unsigned* overflow = (unsigned*)(&output[buffersize]);
63
+ *overflow = 0xCDCDCDCD;
64
+
65
+ result = rc_evaluate_richpresence(richpresence, output, buffersize, peek, memory, NULL);
66
+ ASSERT_NUM_EQUALS(result, expected_result);
67
+
68
+ if (*overflow != 0xCDCDCDCD) {
69
+ ASSERT_FAIL("write past end of buffer");
70
+ }
71
+
72
+ ASSERT_STR_EQUALS(output, expected_display_string);
73
+ }
74
+
75
+ static void test_buffer_boundary() {
76
+ uint8_t ram[] = { 0x00, 0x00, 0x00, 0x01, 0x00 };
77
+ memory_t memory;
78
+ rc_richpresence_t* richpresence;
79
+ char buffer[2048];
80
+
81
+ memory.ram = ram;
82
+ memory.size = sizeof(ram);
83
+
84
+ /* static strings */
85
+ assert_parse_richpresence(&richpresence, buffer, "Display:\nABCDEFGH");
86
+ TEST_PARAMS5(assert_buffer_boundary, richpresence, &memory, 7, 8, "ABCDEF"); /* only 6 chars written */
87
+ TEST_PARAMS5(assert_buffer_boundary, richpresence, &memory, 8, 8, "ABCDEFG"); /* only 7 chars written */
88
+ TEST_PARAMS5(assert_buffer_boundary, richpresence, &memory, 9, 8, "ABCDEFGH"); /* all 8 chars written */
89
+
90
+ /* number formatting */
91
+ assert_parse_richpresence(&richpresence, buffer, "Format:V\nFormatType=VALUE\n\nDisplay:\n@V(0xX0000)");
92
+ TEST_PARAMS5(assert_buffer_boundary, richpresence, &memory, 9, 10, "16,777,2"); /* only 8 chars written */
93
+ TEST_PARAMS5(assert_buffer_boundary, richpresence, &memory, 10, 10, "16,777,21"); /* only 8 chars written */
94
+ TEST_PARAMS5(assert_buffer_boundary, richpresence, &memory, 11, 10, "16,777,216"); /* all 10 chars written */
95
+
96
+ /* lookup */
97
+ assert_parse_richpresence(&richpresence, buffer, "Lookup:L\n1=ABCDEFGH\n\nDisplay:\n@L(0xH0003)");
98
+ TEST_PARAMS5(assert_buffer_boundary, richpresence, &memory, 7, 8, "ABCDEF"); /* only 6 chars written */
99
+ TEST_PARAMS5(assert_buffer_boundary, richpresence, &memory, 8, 8, "ABCDEFG"); /* only 7 chars written */
100
+ TEST_PARAMS5(assert_buffer_boundary, richpresence, &memory, 9, 8, "ABCDEFGH"); /* all 8 chars written */
101
+
102
+ /* unknown macro - "[Unknown macro]L(0xH0003)" = 25 chars */
103
+ assert_parse_richpresence(&richpresence, buffer, "Display:\n@L(0xH0003)");
104
+ TEST_PARAMS5(assert_buffer_boundary, richpresence, &memory, 7, 25, "[Unkno"); /* only 6 chars written */
105
+ TEST_PARAMS5(assert_buffer_boundary, richpresence, &memory, 25, 25, "[Unknown macro]L(0xH0003"); /* only 24 chars written */
106
+ TEST_PARAMS5(assert_buffer_boundary, richpresence, &memory, 26, 25, "[Unknown macro]L(0xH0003)"); /* all 25 chars written */
107
+
108
+ /* multipart */
109
+ assert_parse_richpresence(&richpresence, buffer, "Lookup:L\n0=\n1=A\n4=ABCD\n8=ABCDEFGH\n\nFormat:V\nFormatType=VALUE\n\nDisplay:\n@L(0xH0000)--@L(0xH0001)--@V(0xH0002)");
110
+ TEST_PARAMS5(assert_buffer_boundary, richpresence, &memory, 8, 5, "----0"); /* initial value fits */
111
+ ram[1] = 4;
112
+ TEST_PARAMS5(assert_buffer_boundary, richpresence, &memory, 8, 9, "--ABCD-"); /* only 7 chars written */
113
+ TEST_PARAMS5(assert_buffer_boundary, richpresence, &memory, 9, 9, "--ABCD--"); /* only 8 chars written */
114
+ TEST_PARAMS5(assert_buffer_boundary, richpresence, &memory, 10, 9, "--ABCD--0"); /* all 9 chars written */
115
+ TEST_PARAMS5(assert_buffer_boundary, richpresence, &memory, 5, 9, "--AB"); /* only 7 chars written */
116
+ ram[2] = 123;
117
+ TEST_PARAMS5(assert_buffer_boundary, richpresence, &memory, 10, 11, "--ABCD--1"); /* only 9 chars written */
118
+ TEST_PARAMS5(assert_buffer_boundary, richpresence, &memory, 11, 11, "--ABCD--12"); /* only 10 chars written */
119
+ TEST_PARAMS5(assert_buffer_boundary, richpresence, &memory, 12, 11, "--ABCD--123"); /* all 11 chars written */
120
+ TEST_PARAMS5(assert_buffer_boundary, richpresence, &memory, 2, 11, "-"); /* only 1 char written */
121
+ }
122
+
123
+ static void test_conditional_display_simple() {
124
+ uint8_t ram[] = { 0x00, 0x12, 0x34, 0xAB, 0x56 };
125
+ memory_t memory;
126
+ rc_richpresence_t* richpresence;
127
+ char buffer[1024];
128
+
129
+ memory.ram = ram;
130
+ memory.size = sizeof(ram);
131
+
132
+ assert_parse_richpresence(&richpresence, buffer, "Display:\n?0xH0000=0?Zero\n?0xH0000=1?One\nOther");
133
+ assert_richpresence_output(richpresence, &memory, "Zero");
134
+
135
+ ram[0] = 1;
136
+ assert_richpresence_output(richpresence, &memory, "One");
137
+
138
+ ram[0] = 2;
139
+ assert_richpresence_output(richpresence, &memory, "Other");
140
+ }
141
+
142
+ static void test_conditional_display_after_default() {
143
+ uint8_t ram[] = { 0x00, 0x12, 0x34, 0xAB, 0x56 };
144
+ memory_t memory;
145
+ rc_richpresence_t* richpresence;
146
+ char buffer[1024];
147
+
148
+ memory.ram = ram;
149
+ memory.size = sizeof(ram);
150
+
151
+ assert_parse_richpresence(&richpresence, buffer, "Display:\nOther\n?0xH0000=0?Zero\n?0xH0000=1?One");
152
+ assert_richpresence_output(richpresence, &memory, "Other");
153
+
154
+ ram[0] = 1;
155
+ assert_richpresence_output(richpresence, &memory, "Other");
156
+ }
157
+
158
+ static void test_conditional_display_no_default() {
159
+ int lines;
160
+ int result = rc_richpresence_size_lines("Display:\n?0xH0000=0?Zero", &lines);
161
+ ASSERT_NUM_EQUALS(result, RC_MISSING_DISPLAY_STRING);
162
+ ASSERT_NUM_EQUALS(lines, 3);
163
+ }
164
+
165
+ static void test_conditional_display_common_condition() {
166
+ uint8_t ram[] = { 0x00, 0x12, 0x34, 0xAB, 0x56 };
167
+ memory_t memory;
168
+ rc_richpresence_t* richpresence;
169
+ char buffer[1024];
170
+
171
+ memory.ram = ram;
172
+ memory.size = sizeof(ram);
173
+
174
+ /* condition for Second is a sub-clause of First */
175
+ assert_parse_richpresence(&richpresence, buffer, "Display:\n?0xH0000=0_0xH0001=18?First\n?0xH0000=0?Second\nThird");
176
+ assert_richpresence_output(richpresence, &memory, "First");
177
+
178
+ /* secondary part of first condition is false, will match second condition */
179
+ ram[1] = 1;
180
+ assert_richpresence_output(richpresence, &memory, "Second");
181
+
182
+ /* common condition is false, will use default */
183
+ ram[0] = 1;
184
+ assert_richpresence_output(richpresence, &memory, "Third");
185
+
186
+ /* ================================================================ */
187
+ /* == reverse the conditions so the First is a sub-clause of Second */
188
+ assert_parse_richpresence(&richpresence, buffer, "Display:\n?0xH0000=0?First\n?0xH0000=0_0xH0001=18?Second\nThird");
189
+
190
+ /* reset the memory so it matches the first test, First clause will be matched before even looking at Second */
191
+ ram[0] = 0;
192
+ ram[1] = 18;
193
+ assert_richpresence_output(richpresence, &memory, "First");
194
+
195
+ /* secondary part of second condition is false, will still match first condition */
196
+ ram[1] = 1;
197
+ assert_richpresence_output(richpresence, &memory, "First");
198
+
199
+ /* common condition is false, will use default */
200
+ ram[0] = 1;
201
+ assert_richpresence_output(richpresence, &memory, "Third");
202
+ }
203
+
204
+ static void test_conditional_display_duplicated_condition() {
205
+ uint8_t ram[] = { 0x00, 0x12, 0x34, 0xAB, 0x56 };
206
+ memory_t memory;
207
+ rc_richpresence_t* richpresence;
208
+ char buffer[1024];
209
+
210
+ memory.ram = ram;
211
+ memory.size = sizeof(ram);
212
+
213
+ assert_parse_richpresence(&richpresence, buffer, "Display:\n?0xH0000=0?First\n?0xH0000=0?Second\nThird");
214
+ assert_richpresence_output(richpresence, &memory, "First");
215
+
216
+ /* cannot activate Second */
217
+
218
+ ram[0] = 1;
219
+ assert_richpresence_output(richpresence, &memory, "Third");
220
+ }
221
+
222
+ static void test_conditional_display_invalid_condition_logic() {
223
+ int lines;
224
+ int result = rc_richpresence_size_lines("Display:\n?BANANA?Zero\nDefault", &lines);
225
+ ASSERT_NUM_EQUALS(result, RC_INVALID_MEMORY_OPERAND);
226
+ ASSERT_NUM_EQUALS(lines, 2);
227
+ }
228
+
229
+ static void test_conditional_display_shared_lookup() {
230
+ uint8_t ram[] = { 0x00, 0x12, 0x34, 0xAB, 0x56 };
231
+ memory_t memory;
232
+ rc_richpresence_t* richpresence;
233
+ char buffer[1024];
234
+
235
+ memory.ram = ram;
236
+ memory.size = sizeof(ram);
237
+
238
+ assert_parse_richpresence(&richpresence, buffer, "Format:Points\nFormatType=VALUE\n\nDisplay:\n?0xH0001=1?One @Points(0xL0002)\n?0xH0001=0?Zero @Points(0xL0002)\nDefault @Points(0xL0002)");
239
+ assert_richpresence_output(richpresence, &memory, "Default 4");
240
+
241
+ ram[1] = 1;
242
+ ram[2] = 24;
243
+ assert_richpresence_output(richpresence, &memory, "One 8");
244
+
245
+ ram[1] = 0;
246
+ assert_richpresence_output(richpresence, &memory, "Zero 8");
247
+ }
248
+
249
+ static void test_conditional_display_whitespace_text() {
250
+ uint8_t ram[] = { 0x00, 0x12, 0x34, 0xAB, 0x56 };
251
+ memory_t memory;
252
+ rc_richpresence_t* richpresence;
253
+ char buffer[1024];
254
+
255
+ memory.ram = ram;
256
+ memory.size = sizeof(ram);
257
+
258
+ assert_parse_richpresence(&richpresence, buffer, "Display:\n?0xH0000=0? \n?0xH0000=1?One\nOther");
259
+ assert_richpresence_output(richpresence, &memory, " ");
260
+
261
+ ram[0] = 1;
262
+ assert_richpresence_output(richpresence, &memory, "One");
263
+
264
+ ram[0] = 2;
265
+ assert_richpresence_output(richpresence, &memory, "Other");
266
+ }
267
+
268
+ static void test_macro_value() {
269
+ uint8_t ram[] = { 0x00, 0x12, 0x34, 0xAB, 0x56 };
270
+ memory_t memory;
271
+ rc_richpresence_t* richpresence;
272
+ char buffer[1024];
273
+
274
+ memory.ram = ram;
275
+ memory.size = sizeof(ram);
276
+
277
+ assert_parse_richpresence(&richpresence, buffer, "Format:Points\nFormatType=VALUE\n\nDisplay:\n@Points(0x 0001) Points");
278
+ assert_richpresence_output(richpresence, &memory, "13,330 Points");
279
+
280
+ ram[1] = 20;
281
+ assert_richpresence_output(richpresence, &memory, "13,332 Points");
282
+ }
283
+
284
+ static void test_macro_value_nibble() {
285
+ uint8_t ram[] = { 0x00, 0x12, 0x34, 0xAB, 0x56 };
286
+ memory_t memory;
287
+ rc_richpresence_t* richpresence;
288
+ char buffer[1024];
289
+
290
+ memory.ram = ram;
291
+ memory.size = sizeof(ram);
292
+
293
+ /* nibble first, see if byte overwrites */
294
+ assert_parse_richpresence(&richpresence, buffer, "Format:Points\nFormatType=VALUE\n\nDisplay:\n@Points(0xL0001)@Points(0xH0001) Points");
295
+ assert_richpresence_output(richpresence, &memory, "218 Points");
296
+
297
+ ram[1] = 20;
298
+ assert_richpresence_output(richpresence, &memory, "420 Points");
299
+
300
+ /* put byte first, see if nibble overwrites */
301
+ assert_parse_richpresence(&richpresence, buffer, "Format:Points\nFormatType=VALUE\n\nDisplay:\n@Points(0xH0001)@Points(0xL0001) Points");
302
+ assert_richpresence_output(richpresence, &memory, "204 Points");
303
+ }
304
+
305
+ static void test_macro_value_bcd() {
306
+ uint8_t ram[] = { 0x00, 0x12, 0x34, 0xAB, 0x56 };
307
+ memory_t memory;
308
+ rc_richpresence_t* richpresence;
309
+ char buffer[1024];
310
+
311
+ memory.ram = ram;
312
+ memory.size = sizeof(ram);
313
+
314
+ assert_parse_richpresence(&richpresence, buffer, "Format:Points\nFormatType=VALUE\n\nDisplay:\n@Points(b0xH0001) Points");
315
+ assert_richpresence_output(richpresence, &memory, "12 Points");
316
+
317
+ ram[1] = 20;
318
+ assert_richpresence_output(richpresence, &memory, "14 Points");
319
+ }
320
+
321
+ static void test_macro_value_bitcount() {
322
+ uint8_t ram[] = { 0x00, 0x12, 0x34, 0xAB, 0x56 };
323
+ memory_t memory;
324
+ rc_richpresence_t* richpresence;
325
+ char buffer[1024];
326
+
327
+ memory.ram = ram;
328
+ memory.size = sizeof(ram);
329
+
330
+ assert_parse_richpresence(&richpresence, buffer, "Format:Bits\nFormatType=VALUE\n\nDisplay:\n@Bits(0xK0001) Bits");
331
+ assert_richpresence_output(richpresence, &memory, "2 Bits");
332
+
333
+ ram[1] = 0x76;
334
+ assert_richpresence_output(richpresence, &memory, "5 Bits");
335
+ }
336
+
337
+ static void test_conditional_display_indirect() {
338
+ uint8_t ram[] = { 0x00, 0x12, 0x34, 0xAB, 0x56 };
339
+ memory_t memory;
340
+ rc_richpresence_t* richpresence;
341
+ char buffer[1024];
342
+
343
+ memory.ram = ram;
344
+ memory.size = sizeof(ram);
345
+
346
+ assert_parse_richpresence(&richpresence, buffer, "Display:\n?I:0xH0000_0xH0002=h01?True\nFalse\n");
347
+ assert_richpresence_output(richpresence, &memory, "False");
348
+
349
+ ram[0] = 1;
350
+ assert_richpresence_output(richpresence, &memory, "False");
351
+
352
+ ram[3] = 1;
353
+ assert_richpresence_output(richpresence, &memory, "True");
354
+ }
355
+
356
+ static void test_conditional_display_unnecessary_measured() {
357
+ uint8_t ram[] = { 0x00, 0x12, 0x34, 0xAB, 0x56 };
358
+ memory_t memory;
359
+ rc_richpresence_t* richpresence;
360
+ char buffer[1024];
361
+
362
+ memory.ram = ram;
363
+ memory.size = sizeof(ram);
364
+
365
+ assert_parse_richpresence(&richpresence, buffer, "Display:\n?M:0xH0000=0?Zero\n?0xH0000=1?One\nOther");
366
+ assert_richpresence_output(richpresence, &memory, "Zero");
367
+
368
+ ram[0] = 1;
369
+ assert_richpresence_output(richpresence, &memory, "One");
370
+
371
+ ram[0] = 2;
372
+ assert_richpresence_output(richpresence, &memory, "Other");
373
+ }
374
+
375
+ static void test_conditional_display_unnecessary_measured_indirect() {
376
+ uint8_t ram[] = { 0x00, 0x12, 0x34, 0xAB, 0x56 };
377
+ memory_t memory;
378
+ rc_richpresence_t* richpresence;
379
+ char buffer[1024];
380
+
381
+ memory.ram = ram;
382
+ memory.size = sizeof(ram);
383
+
384
+ assert_parse_richpresence(&richpresence, buffer, "Display:\n?I:0xH0000_M:0xH0002=h01?True\nFalse\n");
385
+ assert_richpresence_output(richpresence, &memory, "False");
386
+
387
+ ram[0] = 1;
388
+ assert_richpresence_output(richpresence, &memory, "False");
389
+
390
+ ram[3] = 1;
391
+ assert_richpresence_output(richpresence, &memory, "True");
392
+ }
393
+
394
+ static void test_conditional_display_invalid() {
395
+ int lines_read = 0;
396
+ ASSERT_NUM_EQUALS(rc_richpresence_size_lines("Display:\n?I:0x0x0000=1?True\nFalse\n", &lines_read), RC_INVALID_MEMORY_OPERAND);
397
+ ASSERT_NUM_EQUALS(lines_read, 2);
398
+
399
+ ASSERT_NUM_EQUALS(rc_richpresence_size_lines("Display:\n?0x0000=1 0x0001=2?True\nFalse\n", &lines_read), RC_INVALID_OPERATOR);
400
+ ASSERT_NUM_EQUALS(lines_read, 2);
401
+ }
402
+
403
+ static void test_conditional_display_training_addaddress() {
404
+ uint8_t ram[] = { 0x00, 0x12, 0x34, 0xAB, 0x56 };
405
+ memory_t memory;
406
+ rc_richpresence_t* richpresence;
407
+ char buffer[1024];
408
+
409
+ memory.ram = ram;
410
+ memory.size = sizeof(ram);
411
+
412
+ assert_parse_richpresence(&richpresence, buffer, "Display:\n?I:0xH0000_M:0xH0002=h01_I:0xH0000*2?True\n@Number(I:0xH0001_M:0xH0000_Q:0xH0004=8)\n");
413
+ /* $($0 + 2) == 1 ? True : $4 == 8 ? $($1) : 0 */
414
+ assert_richpresence_output(richpresence, &memory, "0");
415
+
416
+ ram[1] = 3;
417
+ ram[4] = 8;
418
+ assert_richpresence_output(richpresence, &memory, "171"); /* $($1) = > $3 => 0xAB */
419
+
420
+ ram[2] = 1;
421
+ assert_richpresence_output(richpresence, &memory, "True"); /* $($0) => $2 => 1 */
422
+ }
423
+
424
+ static void test_macro_value_adjusted_negative() {
425
+ uint8_t ram[] = { 0x00, 0x12, 0x34, 0xAB, 0x56 };
426
+ memory_t memory;
427
+ rc_richpresence_t* richpresence;
428
+ char buffer[1024];
429
+
430
+ memory.ram = ram;
431
+ memory.size = sizeof(ram);
432
+
433
+ assert_parse_richpresence(&richpresence, buffer, "Format:Points\nFormatType=VALUE\n\nDisplay:\n@Points(0x 0001_V-10000) Points");
434
+ assert_richpresence_output(richpresence, &memory, "3,330 Points");
435
+
436
+ ram[2] = 7;
437
+ assert_richpresence_output(richpresence, &memory, "-8,190 Points");
438
+ }
439
+
440
+ static void test_macro_value_from_formula() {
441
+ uint8_t ram[] = { 0x00, 0x12, 0x34, 0xAB, 0x56 };
442
+ memory_t memory;
443
+ rc_richpresence_t* richpresence;
444
+ char buffer[1024];
445
+
446
+ memory.ram = ram;
447
+ memory.size = sizeof(ram);
448
+
449
+ assert_parse_richpresence(&richpresence, buffer, "Format:Points\nFormatType=VALUE\n\nDisplay:\n@Points(0xH0001*100_0xH0002) Points");
450
+ assert_richpresence_output(richpresence, &memory, "1,852 Points");
451
+
452
+ ram[1] = 32;
453
+ assert_richpresence_output(richpresence, &memory, "3,252 Points");
454
+ }
455
+
456
+ static void test_macro_value_from_hits() {
457
+ uint8_t ram[] = { 0x00, 0x12, 0x34, 0xAB, 0x56 };
458
+ memory_t memory;
459
+ rc_richpresence_t* richpresence;
460
+ char buffer[1024];
461
+
462
+ memory.ram = ram;
463
+ memory.size = sizeof(ram);
464
+
465
+ assert_parse_richpresence(&richpresence, buffer, "Format:Hits\nFormatType=VALUE\n\nDisplay:\n@Hits(M:0xH01=1) Hits");
466
+ assert_richpresence_output(richpresence, &memory, "0 Hits");
467
+
468
+ ram[1] = 1;
469
+ assert_richpresence_output(richpresence, &memory, "1 Hits");
470
+ assert_richpresence_output(richpresence, &memory, "2 Hits");
471
+ assert_richpresence_output(richpresence, &memory, "3 Hits");
472
+ }
473
+
474
+ static void test_macro_value_from_indirect() {
475
+ uint8_t ram[] = { 0x00, 0x12, 0x34, 0xAB, 0x56 };
476
+ memory_t memory;
477
+ rc_richpresence_t* richpresence;
478
+ char buffer[1024];
479
+
480
+ memory.ram = ram;
481
+ memory.size = sizeof(ram);
482
+
483
+ assert_parse_richpresence(&richpresence, buffer, "Format:Value\nFormatType=VALUE\n\nDisplay:\nPointing at @Value(I:0xH00_M:0xH01)");
484
+ assert_richpresence_output(richpresence, &memory, "Pointing at 18");
485
+
486
+ /* pointed at data changes */
487
+ ram[1] = 99;
488
+ assert_richpresence_output(richpresence, &memory, "Pointing at 99");
489
+
490
+ /* pointer changes */
491
+ ram[0] = 1;
492
+ assert_richpresence_output(richpresence, &memory, "Pointing at 52");
493
+ }
494
+
495
+ static void test_macro_value_divide_by_zero() {
496
+ uint8_t ram[] = { 0x00, 0x12, 0x34, 0xAB, 0x56 };
497
+ memory_t memory;
498
+ rc_richpresence_t* richpresence;
499
+ char buffer[1024];
500
+
501
+ memory.ram = ram;
502
+ memory.size = sizeof(ram);
503
+
504
+ assert_parse_richpresence(&richpresence, buffer, "Format:Value\nFormatType=VALUE\n\nDisplay:\nResult is @Value(0xH02/0xH00)");
505
+ assert_richpresence_output(richpresence, &memory, "Result is 0");
506
+
507
+ ram[0] = 1;
508
+ assert_richpresence_output(richpresence, &memory, "Result is 52");
509
+
510
+ ram[0] = 2;
511
+ assert_richpresence_output(richpresence, &memory, "Result is 26");
512
+ }
513
+
514
+ static void test_macro_value_divide_by_self() {
515
+ uint8_t ram[] = { 0x00, 0x12, 0x34, 0xAB, 0x56 };
516
+ memory_t memory;
517
+ rc_richpresence_t* richpresence;
518
+ char buffer[1024];
519
+
520
+ memory.ram = ram;
521
+ memory.size = sizeof(ram);
522
+
523
+ /* sneaky trick to turn any non-zero value into 1 */
524
+ assert_parse_richpresence(&richpresence, buffer, "Format:Value\nFormatType=VALUE\n\nDisplay:\nResult is @Value(0xH02/0xH02)");
525
+ assert_richpresence_output(richpresence, &memory, "Result is 1");
526
+
527
+ ram[2] = 1;
528
+ assert_richpresence_output(richpresence, &memory, "Result is 1");
529
+
530
+ ram[2] = 32;
531
+ assert_richpresence_output(richpresence, &memory, "Result is 1");
532
+
533
+ ram[2] = 255;
534
+ assert_richpresence_output(richpresence, &memory, "Result is 1");
535
+
536
+ ram[2] = 0;
537
+ assert_richpresence_output(richpresence, &memory, "Result is 0");
538
+ }
539
+
540
+ static void test_macro_value_remember_recall() {
541
+ uint8_t ram[] = { 0x00, 0x12, 0x34, 0xAB, 0x56 };
542
+ memory_t memory;
543
+ rc_richpresence_t* richpresence;
544
+ char buffer[1024];
545
+
546
+ memory.ram = ram;
547
+ memory.size = sizeof(ram);
548
+
549
+ /* sneaky trick to turn any non-zero value into 1 */
550
+ assert_parse_richpresence(&richpresence, buffer, "Format:Value\nFormatType=VALUE\n\nDisplay:\nResult is @Value(A:0xH02*2_K:1_M:{recall}*3)");
551
+ assert_richpresence_output(richpresence, &memory, "Result is 315");
552
+
553
+ ram[2] = 1;
554
+ assert_richpresence_output(richpresence, &memory, "Result is 9");
555
+
556
+ ram[2] = 0;
557
+ assert_richpresence_output(richpresence, &memory, "Result is 3");
558
+ }
559
+
560
+ static void test_macro_value_invalid() {
561
+ ASSERT_NUM_EQUALS(rc_richpresence_size("Format:Points\nFormatType=VALUE\n\nDisplay:\n@Points(0x0x0001) Points"), RC_INVALID_MEMORY_OPERAND);
562
+ }
563
+
564
+ static void test_macro_value_measured_if() {
565
+ uint8_t ram[] = { 0x00, 0x12, 0x34, 0xAB, 0x56 };
566
+ memory_t memory;
567
+ rc_richpresence_t* richpresence;
568
+ char buffer[1024];
569
+
570
+ memory.ram = ram;
571
+ memory.size = sizeof(ram);
572
+
573
+ assert_parse_richpresence(&richpresence, buffer, "Format:Points\nFormatType=VALUE\n\nDisplay:\n@Points(Q:0xH000=0_M:0x 0001) Points");
574
+ assert_richpresence_output(richpresence, &memory, "13,330 Points");
575
+
576
+ ram[0] = 1;
577
+ assert_richpresence_output(richpresence, &memory, "0 Points");
578
+
579
+ ram[1] = 20;
580
+ assert_richpresence_output(richpresence, &memory, "0 Points");
581
+
582
+ ram[0] = 0;
583
+ assert_richpresence_output(richpresence, &memory, "13,332 Points");
584
+ }
585
+
586
+ static void test_multiple_macros() {
587
+ uint8_t ram[] = { 0x00, 0x12, 0x34, 0xAB, 0x56 };
588
+ memory_t memory;
589
+ rc_richpresence_t* richpresence;
590
+ char buffer[1024];
591
+
592
+ memory.ram = ram;
593
+ memory.size = sizeof(ram);
594
+
595
+ assert_parse_richpresence(&richpresence, buffer, "Format:Number\nFormatType=VALUE\n\nDisplay:\n@Number(0x 0001) Points | @Number(A:0xH0002_A:0xH0003_M:0xH0004) Items");
596
+ assert_richpresence_output(richpresence, &memory, "13,330 Points | 309 Items");
597
+
598
+ ram[2] = 0x05;
599
+ assert_richpresence_output(richpresence, &memory, "1,298 Points | 262 Items");
600
+
601
+ /* both should map to memrefs, so no helper values will be created */
602
+ ASSERT_PTR_NULL(richpresence->values);
603
+ }
604
+
605
+ static void test_macro_hundreds() {
606
+ uint8_t ram[] = { 0x00, 0x12, 0x34, 0xAB, 0x56 };
607
+ memory_t memory;
608
+ rc_richpresence_t* richpresence;
609
+ char buffer[1024];
610
+
611
+ memory.ram = ram;
612
+ memory.size = sizeof(ram);
613
+
614
+ assert_parse_richpresence(&richpresence, buffer, "Format:Value\nFormatType=HUNDREDS\n\nDisplay:\nResult is @Value(0xH00)");
615
+ assert_richpresence_output(richpresence, &memory, "Result is 0");
616
+
617
+ ram[0] = 18;
618
+ assert_richpresence_output(richpresence, &memory, "Result is 1,800");
619
+
620
+ ram[0] = 255;
621
+ assert_richpresence_output(richpresence, &memory, "Result is 25,500");
622
+
623
+ ram[0] = 0;
624
+ assert_richpresence_output(richpresence, &memory, "Result is 0");
625
+ }
626
+
627
+ static void test_macro_frames() {
628
+ uint8_t ram[] = { 0x00, 0x12, 0x34, 0xAB, 0x56 };
629
+ memory_t memory;
630
+ rc_richpresence_t* richpresence;
631
+ char buffer[1024];
632
+
633
+ memory.ram = ram;
634
+ memory.size = sizeof(ram);
635
+
636
+ assert_parse_richpresence(&richpresence, buffer, "Format:Frames\nFormatType=FRAMES\n\nDisplay:\n@Frames(0x 0001)");
637
+ assert_richpresence_output(richpresence, &memory, "3:42.16");
638
+
639
+ ram[1] = 20;
640
+ assert_richpresence_output(richpresence, &memory, "3:42.20");
641
+ }
642
+
643
+ static void test_macro_float(const char* format, uint32_t value, const char* expected) {
644
+ uint8_t ram[4];
645
+ memory_t memory;
646
+ rc_richpresence_t* richpresence;
647
+ char script[128];
648
+ char buffer[512];
649
+
650
+ memory.ram = ram;
651
+ memory.size = sizeof(ram);
652
+ ram[0] = (value & 0xFF);
653
+ ram[1] = (value >> 8) & 0xFF;
654
+ ram[2] = (value >> 16) & 0xFF;
655
+ ram[3] = (value >> 24) & 0xFF;
656
+
657
+ snprintf(script, sizeof(script), "Format:N\nFormatType=%s\n\nDisplay:\n@N(fF0000)", format);
658
+
659
+ assert_parse_richpresence(&richpresence, buffer, script);
660
+ assert_richpresence_output(richpresence, &memory, expected);
661
+ }
662
+
663
+ static void test_macro_lookup_simple() {
664
+ uint8_t ram[] = { 0x00, 0x12, 0x34, 0xAB, 0x56 };
665
+ memory_t memory;
666
+ rc_richpresence_t* richpresence;
667
+ char buffer[1024];
668
+
669
+ memory.ram = ram;
670
+ memory.size = sizeof(ram);
671
+
672
+ assert_parse_richpresence(&richpresence, buffer, "Lookup:Location\n0=Zero\n1=One\n\nDisplay:\nAt @Location(0xH0000)");
673
+ assert_richpresence_output(richpresence, &memory, "At Zero");
674
+
675
+ ram[0] = 1;
676
+ assert_richpresence_output(richpresence, &memory, "At One");
677
+
678
+ /* no entry - default to empty string */
679
+ ram[0] = 2;
680
+ assert_richpresence_output(richpresence, &memory, "At ");
681
+ }
682
+
683
+ static void test_macro_lookup_with_inline_comment() {
684
+ uint8_t ram[] = { 0x00, 0x12, 0x34, 0xAB, 0x56 };
685
+ memory_t memory;
686
+ rc_richpresence_t* richpresence;
687
+ char buffer[1024];
688
+
689
+ memory.ram = ram;
690
+ memory.size = sizeof(ram);
691
+
692
+ assert_parse_richpresence(&richpresence, buffer, "Lookup:Location\n// Zero\n0=Zero\n// One\n1=One\n//2=Two\n\nDisplay:\nAt @Location(0xH0000)");
693
+ assert_richpresence_output(richpresence, &memory, "At Zero");
694
+
695
+ ram[0] = 1;
696
+ assert_richpresence_output(richpresence, &memory, "At One");
697
+
698
+ /* no entry - default to empty string */
699
+ ram[0] = 2;
700
+ assert_richpresence_output(richpresence, &memory, "At ");
701
+ }
702
+
703
+ static void test_macro_lookup_hex_keys() {
704
+ uint8_t ram[] = { 0x00, 0x12, 0x34, 0xAB, 0x56 };
705
+ memory_t memory;
706
+ rc_richpresence_t* richpresence;
707
+ char buffer[1024];
708
+
709
+ memory.ram = ram;
710
+ memory.size = sizeof(ram);
711
+
712
+ assert_parse_richpresence(&richpresence, buffer, "Lookup:Location\n0x00=Zero\n0x01=One\n\nDisplay:\nAt @Location(0xH0000)");
713
+ assert_richpresence_output(richpresence, &memory, "At Zero");
714
+
715
+ ram[0] = 1;
716
+ assert_richpresence_output(richpresence, &memory, "At One");
717
+
718
+ /* no entry - default to empty string */
719
+ ram[0] = 2;
720
+ assert_richpresence_output(richpresence, &memory, "At ");
721
+ }
722
+
723
+ static void test_macro_lookup_default() {
724
+ uint8_t ram[] = { 0x00, 0x12, 0x34, 0xAB, 0x56 };
725
+ memory_t memory;
726
+ rc_richpresence_t* richpresence;
727
+ char buffer[1024];
728
+
729
+ memory.ram = ram;
730
+ memory.size = sizeof(ram);
731
+
732
+ assert_parse_richpresence(&richpresence, buffer, "Lookup:Location\n0=Zero\n1=One\n*=Star\n\nDisplay:\nAt @Location(0xH0000)");
733
+ assert_richpresence_output(richpresence, &memory, "At Zero");
734
+
735
+ ram[0] = 1;
736
+ assert_richpresence_output(richpresence, &memory, "At One");
737
+
738
+ /* no entry - default to empty string */
739
+ ram[0] = 2;
740
+ assert_richpresence_output(richpresence, &memory, "At Star");
741
+ }
742
+
743
+ static void test_macro_lookup_crlf() {
744
+ uint8_t ram[] = { 0x00, 0x12, 0x34, 0xAB, 0x56 };
745
+ memory_t memory;
746
+ rc_richpresence_t* richpresence;
747
+ char buffer[1024];
748
+
749
+ memory.ram = ram;
750
+ memory.size = sizeof(ram);
751
+
752
+ assert_parse_richpresence(&richpresence, buffer, "Lookup:Location\r\n0=Zero\r\n1=One\r\n\r\nDisplay:\r\nAt @Location(0xH0000)");
753
+ assert_richpresence_output(richpresence, &memory, "At Zero");
754
+
755
+ ram[0] = 1;
756
+ assert_richpresence_output(richpresence, &memory, "At One");
757
+
758
+ /* no entry - default to empty string */
759
+ ram[0] = 2;
760
+ assert_richpresence_output(richpresence, &memory, "At ");
761
+ }
762
+
763
+ static void test_macro_lookup_after_display() {
764
+ uint8_t ram[] = { 0x00, 0x12, 0x34, 0xAB, 0x56 };
765
+ memory_t memory;
766
+ rc_richpresence_t* richpresence;
767
+ char buffer[1024];
768
+
769
+ memory.ram = ram;
770
+ memory.size = sizeof(ram);
771
+
772
+ assert_parse_richpresence(&richpresence, buffer, "Display:\nAt @Location(0xH0000)\n\nLookup:Location\n0=Zero\n1=One");
773
+ assert_richpresence_output(richpresence, &memory, "At Zero");
774
+
775
+ ram[0] = 1;
776
+ assert_richpresence_output(richpresence, &memory, "At One");
777
+
778
+ /* no entry - default to empty string */
779
+ ram[0] = 2;
780
+ assert_richpresence_output(richpresence, &memory, "At ");
781
+ }
782
+
783
+ static void test_macro_lookup_from_formula() {
784
+ uint8_t ram[] = { 0x00, 0x12, 0x34, 0xAB, 0x56 };
785
+ memory_t memory;
786
+ rc_richpresence_t* richpresence;
787
+ char buffer[1024];
788
+
789
+ memory.ram = ram;
790
+ memory.size = sizeof(ram);
791
+
792
+ assert_parse_richpresence(&richpresence, buffer, "Lookup:Location\n0=Zero\n1=One\n\nDisplay:\nAt @Location(0xH0000*0.5)");
793
+ assert_richpresence_output(richpresence, &memory, "At Zero");
794
+
795
+ ram[0] = 1;
796
+ assert_richpresence_output(richpresence, &memory, "At Zero");
797
+
798
+ ram[0] = 2;
799
+ assert_richpresence_output(richpresence, &memory, "At One");
800
+ }
801
+
802
+ static void test_macro_lookup_from_indirect() {
803
+ uint8_t ram[] = { 0x00, 0x00, 0x01, 0x00, 0x56 };
804
+ memory_t memory;
805
+ rc_richpresence_t* richpresence;
806
+ char buffer[1024];
807
+
808
+ memory.ram = ram;
809
+ memory.size = sizeof(ram);
810
+
811
+ assert_parse_richpresence(&richpresence, buffer, "Lookup:Location\n0=Zero\n1=One\n\nDisplay:\nAt @Location(I:0xH0000=0_M:0xH0001)");
812
+ assert_richpresence_output(richpresence, &memory, "At Zero");
813
+
814
+ ram[0] = 1;
815
+ assert_richpresence_output(richpresence, &memory, "At One");
816
+
817
+ ram[0] = 2;
818
+ assert_richpresence_output(richpresence, &memory, "At Zero");
819
+ }
820
+
821
+ static void test_macro_lookup_repeated() {
822
+ uint8_t ram[] = { 0x00, 0x12, 0x34, 0xAB, 0x56 };
823
+ memory_t memory;
824
+ rc_richpresence_t* richpresence;
825
+ char buffer[1024];
826
+
827
+ memory.ram = ram;
828
+ memory.size = sizeof(ram);
829
+
830
+ /* same lookup can be used for the same address */
831
+ assert_parse_richpresence(&richpresence, buffer, "Lookup:Location\n0=Zero\n1=One\n\nDisplay:\nAt @Location(0xH0000), Near @Location(0xH0000)");
832
+ assert_richpresence_output(richpresence, &memory, "At Zero, Near Zero");
833
+
834
+ ram[0] = 1;
835
+ assert_richpresence_output(richpresence, &memory, "At One, Near One");
836
+
837
+ /* no entry - default to empty string */
838
+ ram[0] = 2;
839
+ assert_richpresence_output(richpresence, &memory, "At , Near ");
840
+ }
841
+
842
+ static void test_macro_lookup_shared() {
843
+ uint8_t ram[] = { 0x00, 0x12, 0x34, 0xAB, 0x56 };
844
+ memory_t memory;
845
+ rc_richpresence_t* richpresence;
846
+ char buffer[1024];
847
+
848
+ memory.ram = ram;
849
+ memory.size = sizeof(ram);
850
+
851
+ /* same lookup can be used for multiple addresses */
852
+ assert_parse_richpresence(&richpresence, buffer, "Lookup:Location\n0=Zero\n1=One\n\nDisplay:\nAt @Location(0xH0000), Near @Location(0xH0001)");
853
+ assert_richpresence_output(richpresence, &memory, "At Zero, Near ");
854
+
855
+ ram[1] = 1;
856
+ assert_richpresence_output(richpresence, &memory, "At Zero, Near One");
857
+
858
+ ram[0] = 1;
859
+ assert_richpresence_output(richpresence, &memory, "At One, Near One");
860
+ }
861
+
862
+ static void test_macro_lookup_multiple() {
863
+ uint8_t ram[] = { 0x00, 0x12, 0x34, 0xAB, 0x56 };
864
+ memory_t memory;
865
+ rc_richpresence_t* richpresence;
866
+ char buffer[1024];
867
+
868
+ memory.ram = ram;
869
+ memory.size = sizeof(ram);
870
+
871
+ /* multiple lookups can be used for same address */
872
+ assert_parse_richpresence(&richpresence, buffer, "Lookup:Location\n0=Zero\n1=One\n\nLookup:Location2\n0=zero\n1=one\n\nDisplay:\nAt @Location(0xH0000), Near @Location2(0xH0000)");
873
+ assert_richpresence_output(richpresence, &memory, "At Zero, Near zero");
874
+
875
+ ram[0] = 1;
876
+ assert_richpresence_output(richpresence, &memory, "At One, Near one");
877
+
878
+ ram[0] = 2;
879
+ assert_richpresence_output(richpresence, &memory, "At , Near ");
880
+ }
881
+
882
+ static void test_macro_lookup_and_value() {
883
+ uint8_t ram[] = { 0x00, 0x12, 0x34, 0xAB, 0x56 };
884
+ memory_t memory;
885
+ rc_richpresence_t* richpresence;
886
+ char buffer[1024];
887
+
888
+ memory.ram = ram;
889
+ memory.size = sizeof(ram);
890
+
891
+ assert_parse_richpresence(&richpresence, buffer, "Lookup:Location\n0=Zero\n1=One\n\nFormat:Location2\nFormatType=VALUE\n\nDisplay:\nAt @Location(0xH0000), Near @Location2(0xH0001)");
892
+ assert_richpresence_output(richpresence, &memory, "At Zero, Near 18");
893
+
894
+ ram[1] = 1;
895
+ assert_richpresence_output(richpresence, &memory, "At Zero, Near 1");
896
+
897
+ ram[0] = 1;
898
+ assert_richpresence_output(richpresence, &memory, "At One, Near 1");
899
+ }
900
+
901
+ static void test_macro_lookup_negative_value() {
902
+ uint8_t ram[] = { 0x00, 0x00, 0x00, 0x00, 0x00 };
903
+ memory_t memory;
904
+ rc_richpresence_t* richpresence;
905
+ char buffer[1024];
906
+
907
+ memory.ram = ram;
908
+ memory.size = sizeof(ram);
909
+
910
+ /* lookup keys are signed 32-bit values. the -1 will become 0xFFFFFFFF */
911
+ assert_parse_richpresence(&richpresence, buffer, "Lookup:Diff\n0=Zero\n1=One\n-1=Negative One\n\nDisplay:\nDiff=@Diff(B:0xH0000_M:0xH0001)");
912
+ assert_richpresence_output(richpresence, &memory, "Diff=Zero");
913
+
914
+ ram[1] = 1;
915
+ assert_richpresence_output(richpresence, &memory, "Diff=One");
916
+
917
+ ram[0] = 1;
918
+ assert_richpresence_output(richpresence, &memory, "Diff=Zero");
919
+
920
+ ram[1] = 0;
921
+ assert_richpresence_output(richpresence, &memory, "Diff=Negative One");
922
+ }
923
+
924
+ static void test_macro_lookup_value_with_whitespace() {
925
+ uint8_t ram[] = { 0x00, 0x12, 0x34, 0xAB, 0x56 };
926
+ memory_t memory;
927
+ rc_richpresence_t* richpresence;
928
+ char buffer[1024];
929
+
930
+ memory.ram = ram;
931
+ memory.size = sizeof(ram);
932
+
933
+ assert_parse_richpresence(&richpresence, buffer, "Lookup:Location\n0= Zero \n1= One \n\nDisplay:\nAt '@Location(0xH0000)' ");
934
+ assert_richpresence_output(richpresence, &memory, "At ' Zero ' ");
935
+
936
+ ram[0] = 1;
937
+ assert_richpresence_output(richpresence, &memory, "At ' One ' ");
938
+
939
+ /* no entry - default to empty string */
940
+ ram[0] = 2;
941
+ assert_richpresence_output(richpresence, &memory, "At '' ");
942
+ }
943
+
944
+ static void test_macro_lookup_mapping_repeated() {
945
+ uint8_t ram[] = { 0x00, 0x04, 0x34, 0xAB, 0x56 };
946
+ memory_t memory;
947
+ rc_richpresence_t* richpresence;
948
+ char buffer[1024];
949
+
950
+ memory.ram = ram;
951
+ memory.size = sizeof(ram);
952
+
953
+ /* same lookup can be used for the same address */
954
+ assert_parse_richpresence(&richpresence, buffer, "Lookup:OddOrEven\n0=Even\n1=Odd\n2=Even\n3=Odd\n4=Even\n5=Odd\n\nDisplay:\nFirst:@OddOrEven(0xH0000), Second:@OddOrEven(0xH0001)");
955
+ assert_richpresence_output(richpresence, &memory, "First:Even, Second:Even");
956
+
957
+ ram[0] = 1;
958
+ assert_richpresence_output(richpresence, &memory, "First:Odd, Second:Even");
959
+
960
+ ram[0] = 2;
961
+ ram[1] = 3;
962
+ assert_richpresence_output(richpresence, &memory, "First:Even, Second:Odd");
963
+ }
964
+
965
+ static void test_macro_lookup_mapping_repeated_csv() {
966
+ uint8_t ram[] = { 0x00, 0x04, 0x34, 0xAB, 0x56 };
967
+ memory_t memory;
968
+ rc_richpresence_t* richpresence;
969
+ char buffer[1024];
970
+
971
+ memory.ram = ram;
972
+ memory.size = sizeof(ram);
973
+
974
+ /* same lookup can be used for the same address */
975
+ assert_parse_richpresence(&richpresence, buffer, "Lookup:OddOrEven\n0,2,4=Even\n1,3,5=Odd\n\nDisplay:\nFirst:@OddOrEven(0xH0000), Second:@OddOrEven(0xH0001)");
976
+ assert_richpresence_output(richpresence, &memory, "First:Even, Second:Even");
977
+
978
+ ram[0] = 1;
979
+ assert_richpresence_output(richpresence, &memory, "First:Odd, Second:Even");
980
+
981
+ ram[0] = 2;
982
+ ram[1] = 3;
983
+ assert_richpresence_output(richpresence, &memory, "First:Even, Second:Odd");
984
+ }
985
+
986
+ static void test_macro_lookup_mapping_merged() {
987
+ uint8_t ram[] = { 0x00, 0x04, 0x34, 0xAB, 0x56 };
988
+ memory_t memory;
989
+ rc_richpresence_t* richpresence;
990
+ char buffer[1024];
991
+
992
+ memory.ram = ram;
993
+ memory.size = sizeof(ram);
994
+
995
+ /* same lookup can be used for the same address */
996
+ assert_parse_richpresence(&richpresence, buffer, "Lookup:Place\n0=First\n1=First\n2=First\n3=Second\n4=Second\n5=Second\n\nDisplay:\nFirst:@Place(0xH0000), Second:@Place(0xH0001)");
997
+ assert_richpresence_output(richpresence, &memory, "First:First, Second:Second");
998
+
999
+ ram[0] = 1;
1000
+ assert_richpresence_output(richpresence, &memory, "First:First, Second:Second");
1001
+
1002
+ ram[0] = 5;
1003
+ ram[1] = 2;
1004
+ assert_richpresence_output(richpresence, &memory, "First:Second, Second:First");
1005
+
1006
+ ASSERT_NUM_EQUALS(richpresence->first_lookup->root->first, 0);
1007
+ ASSERT_NUM_EQUALS(richpresence->first_lookup->root->last, 2);
1008
+ ASSERT_NUM_EQUALS(richpresence->first_lookup->root->right->first, 3);
1009
+ ASSERT_NUM_EQUALS(richpresence->first_lookup->root->right->last, 5);
1010
+ ASSERT_PTR_NULL(richpresence->first_lookup->root->right->right);
1011
+ }
1012
+
1013
+ static void test_macro_lookup_mapping_range() {
1014
+ uint8_t ram[] = { 0x00, 0x04, 0x34, 0xAB, 0x56 };
1015
+ memory_t memory;
1016
+ rc_richpresence_t* richpresence;
1017
+ char buffer[1024];
1018
+
1019
+ memory.ram = ram;
1020
+ memory.size = sizeof(ram);
1021
+
1022
+ /* same lookup can be used for the same address */
1023
+ assert_parse_richpresence(&richpresence, buffer, "Lookup:Place\n0-2=First\n5,3-4=Second\n\nDisplay:\nFirst:@Place(0xH0000), Second:@Place(0xH0001)");
1024
+ assert_richpresence_output(richpresence, &memory, "First:First, Second:Second");
1025
+
1026
+ ram[0] = 1;
1027
+ assert_richpresence_output(richpresence, &memory, "First:First, Second:Second");
1028
+
1029
+ ram[0] = 5;
1030
+ ram[1] = 2;
1031
+ assert_richpresence_output(richpresence, &memory, "First:Second, Second:First");
1032
+
1033
+ ASSERT_NUM_EQUALS(richpresence->first_lookup->root->first, 0);
1034
+ ASSERT_NUM_EQUALS(richpresence->first_lookup->root->last, 2);
1035
+ ASSERT_NUM_EQUALS(richpresence->first_lookup->root->right->first, 3);
1036
+ ASSERT_NUM_EQUALS(richpresence->first_lookup->root->right->last, 5);
1037
+ ASSERT_PTR_NULL(richpresence->first_lookup->root->right->right);
1038
+ }
1039
+
1040
+ static void test_macro_lookup_mapping_range_overlap() {
1041
+ int result;
1042
+ int lines;
1043
+
1044
+ /* 2 appears in the first range (2) and the second (2) */
1045
+ result = rc_richpresence_size_lines("Lookup:Place\n2=First\n2=Second\n\nDisplay:\nFirst:@Place(0xH0000), Second:@Place(0xH0001)", &lines);
1046
+ ASSERT_NUM_EQUALS(result, RC_DUPLICATED_VALUE);
1047
+ ASSERT_NUM_EQUALS(lines, 3);
1048
+
1049
+ /* 2 appears in the first range (0-2) and the second (2-5) */
1050
+ result = rc_richpresence_size_lines("Lookup:Place\n0-2=First\n2-5=Second\n\nDisplay:\nFirst:@Place(0xH0000), Second:@Place(0xH0001)", &lines);
1051
+ ASSERT_NUM_EQUALS(result, RC_DUPLICATED_VALUE);
1052
+ ASSERT_NUM_EQUALS(lines, 3);
1053
+
1054
+ /* 2 appears in the first range (0-2) and the second (2,4-5) */
1055
+ result = rc_richpresence_size_lines("Lookup:Place\n0-2=First\n2,4-5=Second\n\nDisplay:\nFirst:@Place(0xH0000), Second:@Place(0xH0001)", &lines);
1056
+ ASSERT_NUM_EQUALS(result, RC_DUPLICATED_VALUE);
1057
+ ASSERT_NUM_EQUALS(lines, 3);
1058
+
1059
+ /* 1 and 2 appear in the first range (0-2) and the second (1,2,4-5) */
1060
+ result = rc_richpresence_size_lines("Lookup:Place\n0-2=First\n1,2,4-5=Second\n\nDisplay:\nFirst:@Place(0xH0000), Second:@Place(0xH0001)", &lines);
1061
+ ASSERT_NUM_EQUALS(result, RC_DUPLICATED_VALUE);
1062
+ ASSERT_NUM_EQUALS(lines, 3);
1063
+
1064
+ /* 2 appears in the first range (2) and the second (1-5) */
1065
+ result = rc_richpresence_size_lines("Lookup:Place\n2=First\n1-5=Second\n\nDisplay:\nFirst:@Place(0xH0000), Second:@Place(0xH0001)", &lines);
1066
+ ASSERT_NUM_EQUALS(result, RC_DUPLICATED_VALUE);
1067
+ ASSERT_NUM_EQUALS(lines, 3);
1068
+ }
1069
+
1070
+ static void test_macro_lookup_invalid() {
1071
+ int result;
1072
+ int lines;
1073
+
1074
+ /* lookup value starts with Ox instead of 0x */
1075
+ result = rc_richpresence_size_lines("Lookup:Location\nOx0=Zero\n1=One\n\nDisplay:\nAt @Location(0xH0000)", &lines);
1076
+ ASSERT_NUM_EQUALS(result, RC_INVALID_CONST_OPERAND);
1077
+ ASSERT_NUM_EQUALS(lines, 2);
1078
+
1079
+ /* lookup value contains invalid hex character */
1080
+ result = rc_richpresence_size_lines("Lookup:Location\n0xO=Zero\n1=One\n\nDisplay:\nAt @Location(0xH0000)", &lines);
1081
+ ASSERT_NUM_EQUALS(result, RC_INVALID_CONST_OPERAND);
1082
+ ASSERT_NUM_EQUALS(lines, 2);
1083
+
1084
+ /* lookup value is not numeric */
1085
+ result = rc_richpresence_size_lines("Lookup:Location\nZero=Zero\n1=One\n\nDisplay:\nAt @Location(0xH0000)", &lines);
1086
+ ASSERT_NUM_EQUALS(result, RC_INVALID_CONST_OPERAND);
1087
+ ASSERT_NUM_EQUALS(lines, 2);
1088
+ }
1089
+
1090
+ static void test_macro_escaped() {
1091
+ uint8_t ram[] = { 0x00, 0x12, 0x34, 0xAB, 0x56 };
1092
+ memory_t memory;
1093
+ rc_richpresence_t* richpresence;
1094
+ char buffer[1024];
1095
+
1096
+ memory.ram = ram;
1097
+ memory.size = sizeof(ram);
1098
+
1099
+ /* ensures @ can be used in the display string by escaping it */
1100
+ assert_parse_richpresence(&richpresence, buffer, "Format:Points\nFormatType=VALUE\n\nDisplay:\n\\@Points(0x 0001) \\@@Points(0x 0001) Points");
1101
+ assert_richpresence_output(richpresence, &memory, "@Points(0x 0001) @13,330 Points");
1102
+ }
1103
+
1104
+ static void test_macro_undefined() {
1105
+ uint8_t ram[] = { 0x00, 0x12, 0x34, 0xAB, 0x56 };
1106
+ memory_t memory;
1107
+ rc_richpresence_t* richpresence;
1108
+ char buffer[1024];
1109
+
1110
+ memory.ram = ram;
1111
+ memory.size = sizeof(ram);
1112
+
1113
+ assert_parse_richpresence(&richpresence, buffer, "Display:\n@Points(0x 0001) Points");
1114
+ assert_richpresence_output(richpresence, &memory, "[Unknown macro]Points(0x 0001) Points");
1115
+ }
1116
+
1117
+ static void test_macro_undefined_at_end_of_line() {
1118
+ uint8_t ram[] = { 0x00, 0x12, 0x34, 0xAB, 0x56 };
1119
+ memory_t memory;
1120
+ rc_richpresence_t* richpresence;
1121
+ char buffer[1024];
1122
+
1123
+ memory.ram = ram;
1124
+ memory.size = sizeof(ram);
1125
+
1126
+ /* adding [Unknown macro] to the output effectively makes the script larger than it started.
1127
+ * since we don't detect unknown macros in `rc_richpresence_size`, this was causing a
1128
+ * write-past-end-of-buffer memory corruption error. this test recreated that error. */
1129
+ assert_parse_richpresence(&richpresence, buffer, "Display:\n@Points(0x 0001)");
1130
+ assert_richpresence_output(richpresence, &memory, "[Unknown macro]Points(0x 0001)");
1131
+ }
1132
+
1133
+ static void test_macro_unterminated() {
1134
+ uint8_t ram[] = { 0x00, 0x12, 0x34, 0xAB, 0x56 };
1135
+ memory_t memory;
1136
+ rc_richpresence_t* richpresence;
1137
+ char buffer[1024];
1138
+
1139
+ memory.ram = ram;
1140
+ memory.size = sizeof(ram);
1141
+
1142
+ /* valid macro with no closing parenthesis should just be dumped as-is */
1143
+ assert_parse_richpresence(&richpresence, buffer, "Format:Points\nFormatType=VALUE\n\nDisplay:\n@Points(0x 0001");
1144
+ assert_richpresence_output(richpresence, &memory, "@Points(0x 0001");
1145
+
1146
+ /* adding [Unknown macro] to the output effectively makes the script larger than it started.
1147
+ * since we don't detect unknown macros in `rc_richpresence_size`, this was causing a
1148
+ * write-past-end-of-buffer memory corruption error. this test recreated that error. */
1149
+ assert_parse_richpresence(&richpresence, buffer, "Display:\n@Points(0x 0001");
1150
+ assert_richpresence_output(richpresence, &memory, "@Points(0x 0001");
1151
+ }
1152
+
1153
+ static void test_macro_without_parameter() {
1154
+ int result;
1155
+ int lines;
1156
+
1157
+ result = rc_richpresence_size_lines("Format:Points\nFormatType=VALUE\n\nDisplay:\n@Points Points", &lines);
1158
+ ASSERT_NUM_EQUALS(result, RC_MISSING_VALUE);
1159
+ ASSERT_NUM_EQUALS(lines, 5);
1160
+
1161
+ result = rc_richpresence_size_lines("Format:Points\nFormatType=VALUE\n\nDisplay:\n@Points() Points", &lines);
1162
+ ASSERT_NUM_EQUALS(result, RC_INVALID_MEMORY_OPERAND);
1163
+ ASSERT_NUM_EQUALS(lines, 5);
1164
+ }
1165
+
1166
+ static void test_macro_without_parameter_conditional_display() {
1167
+ int result;
1168
+ int lines;
1169
+
1170
+ result = rc_richpresence_size_lines("Format:Points\nFormatType=VALUE\n\nDisplay:\n?0x0h0001=1?@Points Points\nDefault", &lines);
1171
+ ASSERT_NUM_EQUALS(result, RC_MISSING_VALUE);
1172
+ ASSERT_NUM_EQUALS(lines, 5);
1173
+
1174
+ result = rc_richpresence_size_lines("Format:Points\nFormatType=VALUE\n\nDisplay:\n?0x0h0001=1?@Points() Points\nDefault", &lines);
1175
+ ASSERT_NUM_EQUALS(result, RC_INVALID_MEMORY_OPERAND);
1176
+ ASSERT_NUM_EQUALS(lines, 5);
1177
+ }
1178
+
1179
+ static void test_macro_non_numeric_parameter() {
1180
+ int lines;
1181
+ int result = rc_richpresence_size_lines("Format:Points\nFormatType=VALUE\n\nDisplay:\n@Points(Zero) Points", &lines);
1182
+ ASSERT_NUM_EQUALS(result, RC_INVALID_MEMORY_OPERAND);
1183
+ ASSERT_NUM_EQUALS(lines, 5);
1184
+ }
1185
+
1186
+ static void test_macro_mathematic_chain() {
1187
+ int lines;
1188
+ int result = rc_richpresence_size_lines("Format:Points\nFormatType=VALUE\n\nDisplay:\n@Points(0xH1234 + 5) Points", &lines);
1189
+ ASSERT_NUM_EQUALS(result, RC_INVALID_OPERATOR);
1190
+ ASSERT_NUM_EQUALS(lines, 5);
1191
+ }
1192
+
1193
+ static void test_builtin_macro(const char* macro, const char* expected) {
1194
+ uint8_t ram[] = { 0x39, 0x30 };
1195
+ memory_t memory;
1196
+ rc_richpresence_t* richpresence;
1197
+ char script[128];
1198
+ char buffer[256];
1199
+
1200
+ memory.ram = ram;
1201
+ memory.size = sizeof(ram);
1202
+
1203
+ snprintf(script, sizeof(script), "Display:\n@%s(0x 0)", macro);
1204
+
1205
+ assert_parse_richpresence(&richpresence, buffer, script);
1206
+ assert_richpresence_output(richpresence, &memory, expected);
1207
+ }
1208
+
1209
+ static void test_builtin_macro_float(const char* macro, const char* expected) {
1210
+ uint8_t ram[] = { 0x92, 0x44, 0x9A, 0x42 }; /* 77.133926 */
1211
+ memory_t memory;
1212
+ rc_richpresence_t* richpresence;
1213
+ char script[128];
1214
+ char buffer[512];
1215
+
1216
+ memory.ram = ram;
1217
+ memory.size = sizeof(ram);
1218
+
1219
+ snprintf(script, sizeof(script), "Display:\n@%s(fF0000)", macro);
1220
+
1221
+ assert_parse_richpresence(&richpresence, buffer, script);
1222
+ assert_richpresence_output(richpresence, &memory, expected);
1223
+ }
1224
+
1225
+ static void test_builtin_macro_unsigned_large() {
1226
+ uint8_t ram[] = { 0x85, 0xE2, 0x59, 0xC7 };
1227
+ memory_t memory;
1228
+ rc_richpresence_t* richpresence;
1229
+ char buffer[256];
1230
+
1231
+ memory.ram = ram;
1232
+ memory.size = sizeof(ram);
1233
+
1234
+ assert_parse_richpresence(&richpresence, buffer, "Display:\n@Unsigned(0xX0)");
1235
+ assert_richpresence_output(richpresence, &memory, "3,344,556,677");
1236
+ }
1237
+
1238
+ static void test_builtin_macro_override() {
1239
+ uint8_t ram[] = { 0x39, 0x30 };
1240
+ memory_t memory;
1241
+ rc_richpresence_t* richpresence;
1242
+ char buffer[512];
1243
+
1244
+ memory.ram = ram;
1245
+ memory.size = sizeof(ram);
1246
+
1247
+ assert_parse_richpresence(&richpresence, buffer, "Format:Number\nFormatType=SECS\n\nDisplay:\n@Number(0x 0)");
1248
+ assert_richpresence_output(richpresence, &memory, "3h25:45");
1249
+ }
1250
+
1251
+ static void test_unformatted_legacy() {
1252
+ uint8_t ram[] = { 0x39, 0x30 };
1253
+ memory_t memory;
1254
+ rc_richpresence_t* richpresence;
1255
+ char buffer[512];
1256
+
1257
+ memory.ram = ram;
1258
+ memory.size = sizeof(ram);
1259
+
1260
+ assert_parse_richpresence(&richpresence, buffer, "Format:Unformatted\nFormatType=VALUE\n\nDisplay:\n@Unformatted(0x 0)");
1261
+ assert_richpresence_output(richpresence, &memory, "12345");
1262
+ }
1263
+
1264
+ static void test_asciichar() {
1265
+ uint8_t ram[] = { 'K', 'e', 'n', '\0', 'V', 'e', 'g', 'a', 1 };
1266
+ memory_t memory;
1267
+ rc_richpresence_t* richpresence;
1268
+ char buffer[1024];
1269
+
1270
+ memory.ram = ram;
1271
+ memory.size = sizeof(ram);
1272
+
1273
+ assert_parse_richpresence(&richpresence, buffer, "Lookup:Round\n0= (Round 1)\n1= (Round 2)\n\n"
1274
+ "Display:\n@ASCIIChar(0xH0)@ASCIIChar(0xH1)@ASCIIChar(0xH2)@ASCIIChar(0xH3) vs @ASCIIChar(0xH4)@ASCIIChar(0xH5)@ASCIIChar(0xH6)@ASCIIChar(0xH7)@Round(0xH8)");
1275
+ assert_richpresence_output(richpresence, &memory, "Ken vs Vega (Round 2)");
1276
+
1277
+ ram[0] = 'R'; ram[1] = 'o'; ram[2] = 's'; ram[3] = 'e';
1278
+ ram[4] = 'K'; ram[5] = 'e'; ram[6] = 'n'; ram[7] = '\0';
1279
+ ram[8] = 0;
1280
+ assert_richpresence_output(richpresence, &memory, "Rose vs Ken (Round 1)");
1281
+ }
1282
+
1283
+ static void test_ascii8(unsigned char c1, unsigned char c2, unsigned char c3, unsigned char c4,
1284
+ unsigned char c5, unsigned char c6, unsigned char c7, unsigned char c8, char* expected) {
1285
+ uint8_t ram[9];
1286
+ memory_t memory;
1287
+ rc_richpresence_t* richpresence;
1288
+ char buffer[1024];
1289
+
1290
+ memory.ram = ram;
1291
+ memory.size = sizeof(ram);
1292
+
1293
+ ram[0] = c1; ram[1] = c2; ram[2] = c3; ram[3] = c4;
1294
+ ram[4] = c5; ram[5] = c6; ram[6] = c7; ram[7] = c8;
1295
+ ram[8] = '~';
1296
+
1297
+ assert_parse_richpresence(&richpresence, buffer, "Display:\n@ASCIIChar(0xH0)@ASCIIChar(0xH1)@ASCIIChar(0xH2)@ASCIIChar(0xH3)@ASCIIChar(0xH4)@ASCIIChar(0xH5)@ASCIIChar(0xH6)@ASCIIChar(0xH7)");
1298
+ assert_richpresence_output(richpresence, &memory, expected);
1299
+ }
1300
+
1301
+ static void test_unicode4(unsigned short c1, unsigned short c2, unsigned short c3, unsigned short c4, char* expected) {
1302
+ uint8_t ram[10];
1303
+ memory_t memory;
1304
+ rc_richpresence_t* richpresence;
1305
+ char buffer[1024];
1306
+
1307
+ memory.ram = ram;
1308
+ memory.size = sizeof(ram);
1309
+
1310
+ ram[0] = c1 & 0xFF; ram[1] = (c1 >> 8) & 0xFF;
1311
+ ram[2] = c2 & 0xFF; ram[3] = (c2 >> 8) & 0xFF;
1312
+ ram[4] = c3 & 0xFF; ram[5] = (c3 >> 8) & 0xFF;
1313
+ ram[6] = c4 & 0xFF; ram[7] = (c4 >> 8) & 0xFF;
1314
+ ram[8] = '~'; ram[9] = '\0';
1315
+
1316
+ assert_parse_richpresence(&richpresence, buffer, "Display:\n@UnicodeChar(0x 0)@UnicodeChar(0x 2)@UnicodeChar(0x 4)@UnicodeChar(0x 6)");
1317
+ assert_richpresence_output(richpresence, &memory, expected);
1318
+ }
1319
+
1320
+ static void test_random_text_between_sections() {
1321
+ uint8_t ram[] = { 0x00, 0x12, 0x34, 0xAB, 0x56 };
1322
+ memory_t memory;
1323
+ rc_richpresence_t* richpresence;
1324
+ char buffer[1024];
1325
+
1326
+ memory.ram = ram;
1327
+ memory.size = sizeof(ram);
1328
+
1329
+ assert_parse_richpresence(&richpresence, buffer, "Locations are fun!\nLookup:Location\n0=Zero\n1=One\n\nDisplay goes here\nDisplay:\nAt @Location(0xH0000)\n\nWritten by User3");
1330
+ assert_richpresence_output(richpresence, &memory, "At Zero");
1331
+
1332
+ ram[0] = 1;
1333
+ assert_richpresence_output(richpresence, &memory, "At One");
1334
+
1335
+ /* no entry - default to empty string */
1336
+ ram[0] = 2;
1337
+ assert_richpresence_output(richpresence, &memory, "At ");
1338
+ }
1339
+
1340
+ static void test_comments() {
1341
+ uint8_t ram[] = { 0x00, 0x12, 0x34, 0xAB, 0x56 };
1342
+ memory_t memory;
1343
+ rc_richpresence_t* richpresence;
1344
+ char buffer[1024];
1345
+
1346
+ memory.ram = ram;
1347
+ memory.size = sizeof(ram);
1348
+
1349
+ assert_parse_richpresence(&richpresence, buffer, "// Locations are fun!\nLookup:Location // lookup\n0=Zero // 0\n1=One // 1\n\n//Display goes here\nDisplay: // display\nAt @Location(0xH0000) // text\n\n//Written by User3");
1350
+ assert_richpresence_output(richpresence, &memory, "At Zero");
1351
+
1352
+ ram[0] = 1;
1353
+ assert_richpresence_output(richpresence, &memory, "At One");
1354
+
1355
+ /* no entry - default to empty string */
1356
+ ram[0] = 2;
1357
+ assert_richpresence_output(richpresence, &memory, "At ");
1358
+ }
1359
+
1360
+ static void test_comments_between_lines() {
1361
+ uint8_t ram[] = { 0x00, 0x12, 0x34, 0xAB, 0x56 };
1362
+ memory_t memory;
1363
+ rc_richpresence_t* richpresence;
1364
+ char buffer[1024];
1365
+
1366
+ memory.ram = ram;
1367
+ memory.size = sizeof(ram);
1368
+
1369
+ assert_parse_richpresence(&richpresence, buffer, "// Locations are fun!\nLookup:Location\n// lookup\n0=Zero\n// 0\n1=One\n// 1\n\n//Display goes here\nDisplay:\n// display\nAt @Location(0xH0000)\n// text\n\n//Written by User3");
1370
+ assert_richpresence_output(richpresence, &memory, "At Zero");
1371
+
1372
+ ram[0] = 1;
1373
+ assert_richpresence_output(richpresence, &memory, "At One");
1374
+
1375
+ /* no entry - default to empty string */
1376
+ ram[0] = 2;
1377
+ assert_richpresence_output(richpresence, &memory, "At ");
1378
+ }
1379
+
1380
+ static void test_display_string_comment_only() {
1381
+ int lines;
1382
+ int result = rc_richpresence_size_lines("Display:\n// This is a comment\n// And another\n// And some whitespace", &lines);
1383
+ ASSERT_NUM_EQUALS(result, RC_MISSING_DISPLAY_STRING);
1384
+ ASSERT_NUM_EQUALS(lines, 5); /* end of file reached */
1385
+ }
1386
+
1387
+ static void test_display_string_comment_with_blank_line() {
1388
+ int lines;
1389
+ int result = rc_richpresence_size_lines("Display:\n// This is a comment\n// And another\n\n// And some whitespace", &lines);
1390
+ ASSERT_NUM_EQUALS(result, RC_MISSING_DISPLAY_STRING);
1391
+ ASSERT_NUM_EQUALS(lines, 4); /* line 4 was blank */
1392
+ }
1393
+
1394
+ void test_richpresence(void) {
1395
+ TEST_SUITE_BEGIN();
1396
+
1397
+ TEST(test_empty_script);
1398
+
1399
+ /* static display string */
1400
+ TEST_PARAMS2(test_simple_richpresence, "Display:\nHello, world!", "Hello, world!");
1401
+
1402
+ /* static display string with trailing whitespace */
1403
+ TEST_PARAMS2(test_simple_richpresence, "Display:\nWhat ", "What ");
1404
+
1405
+ /* static display string whitespace only*/
1406
+ TEST_PARAMS2(test_simple_richpresence, "Display:\n ", " ");
1407
+
1408
+ /* static display string with comment (trailing whitespace will be trimmed) */
1409
+ TEST_PARAMS2(test_simple_richpresence, "Display:\nWhat // Where", "What");
1410
+
1411
+ /* static display string with escaped comment */
1412
+ TEST_PARAMS2(test_simple_richpresence, "Display:\nWhat \\// Where", "What // Where");
1413
+
1414
+ /* static display string with escaped backslash */
1415
+ TEST_PARAMS2(test_simple_richpresence, "Display:\nWhat \\\\ Where", "What \\ Where");
1416
+
1417
+ /* static display string with partially escaped comment */
1418
+ TEST_PARAMS2(test_simple_richpresence, "Display:\nWhat \\/// Where", "What /");
1419
+
1420
+ /* static display string with trailing backslash (backslash will be ignored) */
1421
+ TEST_PARAMS2(test_simple_richpresence, "Display:\nWhat \\", "What ");
1422
+
1423
+ /* static display string with trailing text */
1424
+ TEST_PARAMS2(test_simple_richpresence, "Display:\nWhat\n\nWhere", "What");
1425
+
1426
+ /* buffer boundary */
1427
+ test_buffer_boundary();
1428
+
1429
+ /* conditional display */
1430
+ TEST(test_conditional_display_simple);
1431
+ TEST(test_conditional_display_after_default);
1432
+ TEST(test_conditional_display_no_default);
1433
+ TEST(test_conditional_display_common_condition);
1434
+ TEST(test_conditional_display_duplicated_condition);
1435
+ TEST(test_conditional_display_invalid_condition_logic);
1436
+ TEST(test_conditional_display_shared_lookup);
1437
+ TEST(test_conditional_display_whitespace_text);
1438
+ TEST(test_conditional_display_indirect);
1439
+ TEST(test_conditional_display_unnecessary_measured);
1440
+ TEST(test_conditional_display_unnecessary_measured_indirect);
1441
+ TEST(test_conditional_display_invalid);
1442
+ TEST(test_conditional_display_training_addaddress);
1443
+
1444
+ /* value macros */
1445
+ TEST(test_macro_value);
1446
+ TEST(test_macro_value_nibble);
1447
+ TEST(test_macro_value_bcd);
1448
+ TEST(test_macro_value_bitcount);
1449
+ TEST(test_macro_value_adjusted_negative);
1450
+ TEST(test_macro_value_from_formula);
1451
+ TEST(test_macro_value_from_hits);
1452
+ TEST(test_macro_value_from_indirect);
1453
+ TEST(test_macro_value_divide_by_zero);
1454
+ TEST(test_macro_value_divide_by_self);
1455
+ TEST(test_macro_value_remember_recall);
1456
+ TEST(test_macro_value_invalid);
1457
+ TEST(test_macro_value_measured_if);
1458
+ TEST(test_multiple_macros);
1459
+
1460
+ /* hundreds macro */
1461
+ TEST(test_macro_hundreds);
1462
+
1463
+ /* frames macros */
1464
+ TEST(test_macro_frames);
1465
+
1466
+ /* float macros */
1467
+ TEST_PARAMS3(test_macro_float, "VALUE", 0x429A4492, "77"); /* 77.133926 */
1468
+ TEST_PARAMS3(test_macro_float, "FLOAT1", 0x429A4492, "77.1");
1469
+ TEST_PARAMS3(test_macro_float, "FLOAT2", 0x429A4492, "77.13");
1470
+ TEST_PARAMS3(test_macro_float, "FLOAT3", 0x429A4492, "77.134"); /* rounded up */
1471
+ TEST_PARAMS3(test_macro_float, "FLOAT4", 0x429A4492, "77.1339");
1472
+ TEST_PARAMS3(test_macro_float, "FLOAT5", 0x429A4492, "77.13393"); /* rounded up */
1473
+ TEST_PARAMS3(test_macro_float, "FLOAT6", 0x429A4492, "77.133926");
1474
+ TEST_PARAMS3(test_macro_float, "VALUE", 0xC0000000, "-2"); /* -2.0 */
1475
+ TEST_PARAMS3(test_macro_float, "FLOAT1", 0xC0000000, "-2.0");
1476
+ TEST_PARAMS3(test_macro_float, "FLOAT6", 0xC0000000, "-2.000000");
1477
+ TEST_PARAMS3(test_macro_float, "SECS", 0x429A4492, "1:17"); /* 77.133926 */
1478
+
1479
+ /* lookup macros */
1480
+ TEST(test_macro_lookup_simple);
1481
+ TEST(test_macro_lookup_with_inline_comment);
1482
+ TEST(test_macro_lookup_hex_keys);
1483
+ TEST(test_macro_lookup_default);
1484
+ TEST(test_macro_lookup_crlf);
1485
+ TEST(test_macro_lookup_after_display);
1486
+ TEST(test_macro_lookup_from_formula);
1487
+ TEST(test_macro_lookup_from_indirect);
1488
+ TEST(test_macro_lookup_repeated);
1489
+ TEST(test_macro_lookup_shared);
1490
+ TEST(test_macro_lookup_multiple);
1491
+ TEST(test_macro_lookup_and_value);
1492
+ TEST(test_macro_lookup_negative_value);
1493
+ TEST(test_macro_lookup_value_with_whitespace);
1494
+ TEST(test_macro_lookup_mapping_repeated);
1495
+ TEST(test_macro_lookup_mapping_repeated_csv);
1496
+ TEST(test_macro_lookup_mapping_merged);
1497
+ TEST(test_macro_lookup_mapping_range);
1498
+ TEST(test_macro_lookup_mapping_range_overlap);
1499
+ TEST(test_macro_lookup_invalid);
1500
+
1501
+ /* escaped macro */
1502
+ TEST(test_macro_escaped);
1503
+
1504
+ /* macro errors */
1505
+ TEST(test_macro_undefined);
1506
+ TEST(test_macro_undefined_at_end_of_line);
1507
+ TEST(test_macro_unterminated);
1508
+ TEST(test_macro_without_parameter);
1509
+ TEST(test_macro_without_parameter_conditional_display);
1510
+ TEST(test_macro_non_numeric_parameter);
1511
+ TEST(test_macro_mathematic_chain);
1512
+
1513
+ /* builtin macros */
1514
+ TEST_PARAMS2(test_builtin_macro, "Number", "12,345");
1515
+ TEST_PARAMS2(test_builtin_macro, "Score", "012345");
1516
+ TEST_PARAMS2(test_builtin_macro, "Centiseconds", "2:03.45");
1517
+ TEST_PARAMS2(test_builtin_macro, "Seconds", "3h25:45");
1518
+ TEST_PARAMS2(test_builtin_macro, "Minutes", "205h45");
1519
+ TEST_PARAMS2(test_builtin_macro, "SecondsAsMinutes", "3h25");
1520
+ TEST_PARAMS2(test_builtin_macro, "ASCIIChar", "?"); /* 0x3039 is not a single ASCII char */
1521
+ TEST_PARAMS2(test_builtin_macro, "UnicodeChar", "\xe3\x80\xb9");
1522
+ TEST_PARAMS2(test_builtin_macro_float, "Float1", "77.1");
1523
+ TEST_PARAMS2(test_builtin_macro_float, "Float2", "77.13");
1524
+ TEST_PARAMS2(test_builtin_macro_float, "Float3", "77.134");
1525
+ TEST_PARAMS2(test_builtin_macro_float, "Float4", "77.1339");
1526
+ TEST_PARAMS2(test_builtin_macro_float, "Float5", "77.13393");
1527
+ TEST_PARAMS2(test_builtin_macro_float, "Float6", "77.133926");
1528
+ TEST_PARAMS2(test_builtin_macro, "Fixed1", "1,234.5");
1529
+ TEST_PARAMS2(test_builtin_macro, "Fixed2", "123.45");
1530
+ TEST_PARAMS2(test_builtin_macro, "Fixed3", "12.345");
1531
+ TEST_PARAMS2(test_builtin_macro, "Unsigned", "12,345");
1532
+ TEST_PARAMS2(test_builtin_macro, "Unformatted", "12345");
1533
+ TEST(test_builtin_macro_unsigned_large);
1534
+ TEST(test_builtin_macro_override);
1535
+ TEST(test_unformatted_legacy);
1536
+
1537
+ /* asciichar */
1538
+ TEST(test_asciichar);
1539
+ TEST_PARAMS9(test_ascii8, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, "");
1540
+ TEST_PARAMS9(test_ascii8, 0x41, 0x42, 0x43, 0x44, 0x45, 0x46, 0x47, 0x48, "ABCDEFGH");
1541
+ TEST_PARAMS9(test_ascii8, 0x54, 0x65, 0x73, 0x74, 0x00, 0x00, 0x00, 0x00, "Test");
1542
+ TEST_PARAMS9(test_ascii8, 0x54, 0x65, 0x73, 0x74, 0x00, 0x46, 0x6F, 0x6F, "Test");
1543
+ TEST_PARAMS9(test_ascii8, 0x00, 0x54, 0x65, 0x73, 0x74, 0x00, 0x00, 0x00, "");
1544
+ TEST_PARAMS9(test_ascii8, 0x31, 0x7E, 0x32, 0x7F, 0x33, 0x20, 0x34, 0x5E, "1~2?3 4^"); /* 7F out of range */
1545
+ TEST_PARAMS9(test_ascii8, 0x54, 0x61, 0x62, 0x09, 0x31, 0x0D, 0x0E, 0x00, "Tab?1??"); /* control characters */
1546
+
1547
+ /* unicodechar */
1548
+ TEST_PARAMS5(test_unicode4, 0x0000, 0x0000, 0x0000, 0x0000, "");
1549
+ TEST_PARAMS5(test_unicode4, 0x0054, 0x0065, 0x0073, 0x0074, "Test");
1550
+ TEST_PARAMS5(test_unicode4, 0x0000, 0x0065, 0x0073, 0x0074, "");
1551
+ TEST_PARAMS5(test_unicode4, 0x00A9, 0x0031, 0x0032, 0x0033, "\xc2\xa9\x31\x32\x33"); /* two-byte unicode char */
1552
+ TEST_PARAMS5(test_unicode4, 0x2260, 0x0020, 0x0040, 0x0040, "\xe2\x89\xa0 @@"); /* three-byte unicode char */
1553
+ TEST_PARAMS5(test_unicode4, 0xD83D, 0xDEB6, 0x005F, 0x007A, "\xef\xbf\xbd\xef\xbf\xbd_z"); /* four-byte unicode pair */
1554
+ TEST_PARAMS5(test_unicode4, 0x0009, 0x003E, 0x000D, 0x000A, "\xef\xbf\xbd>\xef\xbf\xbd\xef\xbf\xbd"); /* control characters */
1555
+
1556
+ /* comments */
1557
+ TEST(test_random_text_between_sections); /* before official comments extra text was ignored, so was occassionally used to comment */
1558
+ TEST(test_comments);
1559
+ TEST(test_comments_between_lines);
1560
+ TEST(test_display_string_comment_only);
1561
+ TEST(test_display_string_comment_with_blank_line);
1562
+
1563
+ TEST_SUITE_END();
1564
+ }