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,607 @@
1
+ #include "rc_internal.h"
2
+
3
+ #include <stdlib.h>
4
+ #include <ctype.h>
5
+ #include <math.h>
6
+ #include <string.h>
7
+
8
+ static int rc_parse_operand_func_call(rc_operand_t* self, const char** memaddr) {
9
+ const char* aux = *memaddr;
10
+
11
+ if (*aux++ != '@') {
12
+ return RC_INVALID_FUNC_OPERAND;
13
+ }
14
+
15
+ if (!isalpha((unsigned char)*aux)) {
16
+ return RC_INVALID_FUNC_OPERAND;
17
+ }
18
+
19
+ while (isalnum((unsigned char)*aux) || *aux == '_') {
20
+ aux++;
21
+ }
22
+
23
+ self->type = RC_OPERAND_FUNC;
24
+ self->size = RC_MEMSIZE_32_BITS;
25
+ self->memref_access_type = RC_OPERAND_ADDRESS;
26
+ *memaddr = aux;
27
+ return RC_OK;
28
+ }
29
+
30
+ static int rc_parse_operand_variable(rc_operand_t* self, const char** memaddr, rc_parse_state_t* parse) {
31
+ const char* aux = *memaddr;
32
+ size_t i;
33
+ char varName[RC_VALUE_MAX_NAME_LENGTH + 1] = { 0 };
34
+
35
+ for (i = 0; i < RC_VALUE_MAX_NAME_LENGTH && *aux != '}'; i++) {
36
+ if (!rc_is_valid_variable_character(*aux, i == 0))
37
+ return RC_INVALID_VARIABLE_NAME;
38
+
39
+ varName[i] = *aux++;
40
+ }
41
+
42
+ if (i == 0)
43
+ return RC_INVALID_VARIABLE_NAME;
44
+
45
+ if (*aux != '}')
46
+ return RC_INVALID_VARIABLE_NAME;
47
+
48
+ ++aux;
49
+
50
+ if (strcmp(varName, "recall") == 0) {
51
+ if (parse->remember.type == RC_OPERAND_NONE) {
52
+ self->value.memref = NULL;
53
+ self->size = RC_MEMSIZE_32_BITS;
54
+ self->memref_access_type = RC_OPERAND_ADDRESS;
55
+ }
56
+ else {
57
+ memcpy(self, &parse->remember, sizeof(*self));
58
+ self->is_combining = 0;
59
+ self->memref_access_type = self->type;
60
+ }
61
+ self->type = RC_OPERAND_RECALL;
62
+ }
63
+ else { /* process named variable when feature is available.*/
64
+ return RC_UNKNOWN_VARIABLE_NAME;
65
+ }
66
+
67
+ *memaddr = aux;
68
+ return RC_OK;
69
+ }
70
+
71
+ static int rc_parse_operand_memory(rc_operand_t* self, const char** memaddr, rc_parse_state_t* parse) {
72
+ const char* aux = *memaddr;
73
+ uint32_t address;
74
+ uint8_t size;
75
+ int ret;
76
+
77
+ switch (*aux) {
78
+ case 'd': case 'D':
79
+ self->type = RC_OPERAND_DELTA;
80
+ ++aux;
81
+ break;
82
+
83
+ case 'p': case 'P':
84
+ self->type = RC_OPERAND_PRIOR;
85
+ ++aux;
86
+ break;
87
+
88
+ case 'b': case 'B':
89
+ self->type = RC_OPERAND_BCD;
90
+ ++aux;
91
+ break;
92
+
93
+ case '~':
94
+ self->type = RC_OPERAND_INVERTED;
95
+ ++aux;
96
+ break;
97
+
98
+ default:
99
+ self->type = RC_OPERAND_ADDRESS;
100
+ break;
101
+ }
102
+
103
+ self->memref_access_type = self->type;
104
+
105
+ ret = rc_parse_memref(&aux, &self->size, &address);
106
+ if (ret != RC_OK)
107
+ return ret;
108
+
109
+ size = rc_memref_shared_size(self->size);
110
+ if (size != self->size && self->type == RC_OPERAND_PRIOR) {
111
+ /* if the shared size differs from the requested size and it's a prior operation, we
112
+ * have to check to make sure both sizes use the same mask, or the prior value may be
113
+ * updated when bits outside the mask are modified, which would make it look like the
114
+ * current value once the mask is applied. if the mask differs, create a new
115
+ * non-shared record for tracking the prior data. */
116
+ if (rc_memref_mask(size) != rc_memref_mask(self->size))
117
+ size = self->size;
118
+ }
119
+
120
+ if (parse->indirect_parent.type != RC_OPERAND_NONE) {
121
+ rc_operand_t offset;
122
+ rc_operand_set_const(&offset, address);
123
+
124
+ self->value.memref = (rc_memref_t*)rc_alloc_modified_memref(parse,
125
+ size, &parse->indirect_parent, RC_OPERATOR_INDIRECT_READ, &offset);
126
+ }
127
+ else {
128
+ self->value.memref = rc_alloc_memref(parse, address, size);
129
+ }
130
+
131
+ if (parse->offset < 0)
132
+ return parse->offset;
133
+
134
+ *memaddr = aux;
135
+ return RC_OK;
136
+ }
137
+
138
+ int rc_parse_operand(rc_operand_t* self, const char** memaddr, rc_parse_state_t* parse) {
139
+ const char* aux = *memaddr;
140
+ char* end;
141
+ int ret;
142
+ unsigned long value;
143
+ int negative;
144
+ int allow_decimal = 0;
145
+
146
+ self->is_combining = 0;
147
+
148
+ switch (*aux) {
149
+ case 'h': case 'H': /* hex constant */
150
+ if (aux[2] == 'x' || aux[2] == 'X') {
151
+ /* H0x1234 is a typo - either H1234 or 0xH1234 was probably meant */
152
+ return RC_INVALID_CONST_OPERAND;
153
+ }
154
+
155
+ value = strtoul(++aux, &end, 16);
156
+ if (end == aux)
157
+ return RC_INVALID_CONST_OPERAND;
158
+
159
+ if (value > 0xffffffffU)
160
+ value = 0xffffffffU;
161
+
162
+ rc_operand_set_const(self, (unsigned)value);
163
+
164
+ aux = end;
165
+ break;
166
+
167
+ case 'f': case 'F': /* floating point constant */
168
+ if (isalpha((unsigned char)aux[1])) {
169
+ ret = rc_parse_operand_memory(self, &aux, parse);
170
+
171
+ if (ret < 0)
172
+ return ret;
173
+
174
+ break;
175
+ }
176
+ allow_decimal = 1;
177
+ /* fall through */
178
+ case 'v': case 'V': /* signed integer constant */
179
+ ++aux;
180
+ /* fall through */
181
+ case '+': case '-': /* signed integer constant */
182
+ negative = 0;
183
+ if (*aux == '-') {
184
+ negative = 1;
185
+ ++aux;
186
+ }
187
+ else if (*aux == '+') {
188
+ ++aux;
189
+ }
190
+
191
+ value = strtoul(aux, &end, 10);
192
+
193
+ if (*end == '.' && allow_decimal) {
194
+ /* custom parser for decimal values to ignore locale */
195
+ unsigned long shift = 1;
196
+ unsigned long fraction = 0;
197
+ double dbl_val;
198
+
199
+ aux = end + 1;
200
+ if (*aux < '0' || *aux > '9')
201
+ return RC_INVALID_FP_OPERAND;
202
+
203
+ do {
204
+ /* only keep as many digits as will fit in a 32-bit value to prevent overflow.
205
+ * float only has around 7 digits of precision anyway. */
206
+ if (shift < 1000000000) {
207
+ fraction *= 10;
208
+ fraction += (*aux - '0');
209
+ shift *= 10;
210
+ }
211
+ ++aux;
212
+ } while (*aux >= '0' && *aux <= '9');
213
+
214
+ if (fraction != 0) {
215
+ /* non-zero fractional part, convert to double and merge in integer portion */
216
+ const double dbl_fraction = ((double)fraction) / ((double)shift);
217
+ if (negative)
218
+ dbl_val = ((double)(-((long)value))) - dbl_fraction;
219
+ else
220
+ dbl_val = (double)value + dbl_fraction;
221
+ }
222
+ else {
223
+ /* fractional part is 0, just convert the integer portion */
224
+ if (negative)
225
+ dbl_val = (double)(-((long)value));
226
+ else
227
+ dbl_val = (double)value;
228
+ }
229
+
230
+ rc_operand_set_float_const(self, dbl_val);
231
+ }
232
+ else {
233
+ /* not a floating point value, make sure something was read and advance the read pointer */
234
+ if (end == aux)
235
+ return allow_decimal ? RC_INVALID_FP_OPERAND : RC_INVALID_CONST_OPERAND;
236
+
237
+ aux = end;
238
+
239
+ if (value > 0x7fffffffU)
240
+ value = 0x7fffffffU;
241
+
242
+ if (negative)
243
+ rc_operand_set_const(self, (unsigned)(-((long)value)));
244
+ else
245
+ rc_operand_set_const(self, (unsigned)value);
246
+ }
247
+ break;
248
+ case '{': /* variable */
249
+ ++aux;
250
+ ret = rc_parse_operand_variable(self, &aux, parse);
251
+ if (ret < 0)
252
+ return ret;
253
+
254
+ break;
255
+
256
+ case '0':
257
+ if (aux[1] == 'x' || aux[1] == 'X') { /* hex integer constant */
258
+ /* fallthrough */ /* to default */
259
+ default:
260
+ ret = rc_parse_operand_memory(self, &aux, parse);
261
+
262
+ if (ret < 0)
263
+ return ret;
264
+
265
+ break;
266
+ }
267
+ /* fallthrough */ /* to case '1' for case '0' where not '0x' */
268
+ case '1': case '2': case '3': case '4': case '5': /* unsigned integer constant */
269
+ case '6': case '7': case '8': case '9':
270
+ value = strtoul(aux, &end, 10);
271
+ if (end == aux)
272
+ return RC_INVALID_CONST_OPERAND;
273
+
274
+ if (value > 0xffffffffU)
275
+ value = 0xffffffffU;
276
+
277
+ rc_operand_set_const(self, (unsigned)value);
278
+
279
+ aux = end;
280
+ break;
281
+
282
+ case '@':
283
+ ret = rc_parse_operand_func_call(self, &aux);
284
+
285
+ if (ret < 0)
286
+ return ret;
287
+
288
+ break;
289
+ }
290
+
291
+ *memaddr = aux;
292
+ return RC_OK;
293
+ }
294
+
295
+ void rc_operand_set_const(rc_operand_t* self, uint32_t value) {
296
+ self->size = RC_MEMSIZE_32_BITS;
297
+ self->type = RC_OPERAND_CONST;
298
+ self->memref_access_type = RC_OPERAND_NONE;
299
+ self->value.num = value;
300
+ }
301
+
302
+ void rc_operand_set_float_const(rc_operand_t* self, double value) {
303
+ self->size = RC_MEMSIZE_FLOAT;
304
+ self->type = RC_OPERAND_FP;
305
+ self->memref_access_type = RC_OPERAND_NONE;
306
+ self->value.dbl = value;
307
+ }
308
+
309
+ int rc_operands_are_equal(const rc_operand_t* left, const rc_operand_t* right) {
310
+ if (left == right)
311
+ return 1;
312
+
313
+ if (left->type != right->type)
314
+ return 0;
315
+
316
+ switch (left->type) {
317
+ case RC_OPERAND_CONST:
318
+ return (left->value.num == right->value.num);
319
+ case RC_OPERAND_FP:
320
+ return (left->value.dbl == right->value.dbl);
321
+ case RC_OPERAND_RECALL:
322
+ return (left->value.memref == right->value.memref);
323
+ default:
324
+ break;
325
+ }
326
+
327
+ /* comparing two memrefs - look for exact matches on type and size */
328
+ if (left->size != right->size || left->value.memref->value.memref_type != right->value.memref->value.memref_type)
329
+ return 0;
330
+
331
+ switch (left->value.memref->value.memref_type) {
332
+ case RC_MEMREF_TYPE_MODIFIED_MEMREF:
333
+ {
334
+ const rc_modified_memref_t* left_memref = (const rc_modified_memref_t*)left->value.memref;
335
+ const rc_modified_memref_t* right_memref = (const rc_modified_memref_t*)right->value.memref;
336
+ return (left_memref->modifier_type == right_memref->modifier_type &&
337
+ left_memref->depth == right_memref->depth &&
338
+ rc_operands_are_equal(&left_memref->modifier, &right_memref->modifier) &&
339
+ rc_operands_are_equal(&left_memref->parent, &right_memref->parent) &&
340
+ 1 == 1
341
+ );
342
+ }
343
+
344
+ default:
345
+ return (left->value.memref->address == right->value.memref->address &&
346
+ left->value.memref->value.size == right->value.memref->value.size);
347
+ }
348
+ }
349
+
350
+ int rc_operator_is_modifying(int oper) {
351
+ switch (oper) {
352
+ case RC_OPERATOR_AND:
353
+ case RC_OPERATOR_XOR:
354
+ case RC_OPERATOR_DIV:
355
+ case RC_OPERATOR_MULT:
356
+ case RC_OPERATOR_MOD:
357
+ case RC_OPERATOR_ADD:
358
+ case RC_OPERATOR_SUB:
359
+ case RC_OPERATOR_NONE: /* NONE operator implies "* 1" */
360
+ return 1;
361
+
362
+ default:
363
+ return 0;
364
+ }
365
+ }
366
+
367
+ int rc_memsize_is_float(uint8_t size) {
368
+ switch (size) {
369
+ case RC_MEMSIZE_FLOAT:
370
+ case RC_MEMSIZE_FLOAT_BE:
371
+ case RC_MEMSIZE_DOUBLE32:
372
+ case RC_MEMSIZE_DOUBLE32_BE:
373
+ case RC_MEMSIZE_MBF32:
374
+ case RC_MEMSIZE_MBF32_LE:
375
+ return 1;
376
+
377
+ default:
378
+ return 0;
379
+ }
380
+ }
381
+
382
+ int rc_operand_is_float_memref(const rc_operand_t* self) {
383
+ if (!rc_operand_is_memref(self))
384
+ return 0;
385
+
386
+ if (self->value.memref->value.memref_type == RC_MEMREF_TYPE_MODIFIED_MEMREF) {
387
+ const rc_modified_memref_t* memref = (const rc_modified_memref_t*)self->value.memref;
388
+ if (memref->modifier_type != RC_OPERATOR_INDIRECT_READ)
389
+ return rc_memsize_is_float(self->value.memref->value.size);
390
+ }
391
+
392
+ return rc_memsize_is_float(self->size);
393
+ }
394
+
395
+ int rc_operand_type_is_memref(uint8_t type) {
396
+ switch (type) {
397
+ case RC_OPERAND_CONST:
398
+ case RC_OPERAND_FP:
399
+ case RC_OPERAND_FUNC:
400
+ case RC_OPERAND_RECALL:
401
+ return 0;
402
+
403
+ default:
404
+ return 1;
405
+ }
406
+ }
407
+
408
+ int rc_operand_type_is_transform(uint8_t type) {
409
+ switch (type) {
410
+ case RC_OPERAND_BCD:
411
+ case RC_OPERAND_INVERTED:
412
+ return 1;
413
+
414
+ default:
415
+ return 0;
416
+ }
417
+ }
418
+
419
+ int rc_operand_is_memref(const rc_operand_t* self) {
420
+ return rc_operand_type_is_memref(self->type);
421
+ }
422
+
423
+ int rc_operand_is_recall(const rc_operand_t* self) {
424
+ switch (self->type) {
425
+ case RC_OPERAND_RECALL:
426
+ return 1;
427
+
428
+ default:
429
+ return 0;
430
+ }
431
+ }
432
+
433
+ int rc_operand_is_float(const rc_operand_t* self) {
434
+ if (self->type == RC_OPERAND_FP)
435
+ return 1;
436
+
437
+ if (self->type == RC_OPERAND_RECALL)
438
+ return rc_memsize_is_float(self->size);
439
+
440
+ return rc_operand_is_float_memref(self);
441
+ }
442
+
443
+ static uint32_t rc_transform_operand_value(uint32_t value, const rc_operand_t* self) {
444
+ switch (self->type)
445
+ {
446
+ case RC_OPERAND_BCD:
447
+ switch (self->size)
448
+ {
449
+ case RC_MEMSIZE_8_BITS:
450
+ value = ((value >> 4) & 0x0f) * 10
451
+ + ((value ) & 0x0f);
452
+ break;
453
+
454
+ case RC_MEMSIZE_16_BITS:
455
+ case RC_MEMSIZE_16_BITS_BE:
456
+ value = ((value >> 12) & 0x0f) * 1000
457
+ + ((value >> 8) & 0x0f) * 100
458
+ + ((value >> 4) & 0x0f) * 10
459
+ + ((value ) & 0x0f);
460
+ break;
461
+
462
+ case RC_MEMSIZE_24_BITS:
463
+ case RC_MEMSIZE_24_BITS_BE:
464
+ value = ((value >> 20) & 0x0f) * 100000
465
+ + ((value >> 16) & 0x0f) * 10000
466
+ + ((value >> 12) & 0x0f) * 1000
467
+ + ((value >> 8) & 0x0f) * 100
468
+ + ((value >> 4) & 0x0f) * 10
469
+ + ((value ) & 0x0f);
470
+ break;
471
+
472
+ case RC_MEMSIZE_32_BITS:
473
+ case RC_MEMSIZE_32_BITS_BE:
474
+ case RC_MEMSIZE_VARIABLE:
475
+ value = ((value >> 28) & 0x0f) * 10000000
476
+ + ((value >> 24) & 0x0f) * 1000000
477
+ + ((value >> 20) & 0x0f) * 100000
478
+ + ((value >> 16) & 0x0f) * 10000
479
+ + ((value >> 12) & 0x0f) * 1000
480
+ + ((value >> 8) & 0x0f) * 100
481
+ + ((value >> 4) & 0x0f) * 10
482
+ + ((value ) & 0x0f);
483
+ break;
484
+
485
+ default:
486
+ break;
487
+ }
488
+ break;
489
+
490
+ case RC_OPERAND_INVERTED:
491
+ switch (self->size)
492
+ {
493
+ case RC_MEMSIZE_LOW:
494
+ case RC_MEMSIZE_HIGH:
495
+ value ^= 0x0f;
496
+ break;
497
+
498
+ case RC_MEMSIZE_8_BITS:
499
+ value ^= 0xff;
500
+ break;
501
+
502
+ case RC_MEMSIZE_16_BITS:
503
+ case RC_MEMSIZE_16_BITS_BE:
504
+ value ^= 0xffff;
505
+ break;
506
+
507
+ case RC_MEMSIZE_24_BITS:
508
+ case RC_MEMSIZE_24_BITS_BE:
509
+ value ^= 0xffffff;
510
+ break;
511
+
512
+ case RC_MEMSIZE_32_BITS:
513
+ case RC_MEMSIZE_32_BITS_BE:
514
+ case RC_MEMSIZE_VARIABLE:
515
+ value ^= 0xffffffff;
516
+ break;
517
+
518
+ default:
519
+ value ^= 0x01;
520
+ break;
521
+ }
522
+ break;
523
+
524
+ default:
525
+ break;
526
+ }
527
+
528
+ return value;
529
+ }
530
+
531
+ void rc_operand_addsource(rc_operand_t* self, rc_parse_state_t* parse, uint8_t new_size) {
532
+ rc_modified_memref_t* modified_memref;
533
+
534
+ if ((self->type == RC_OPERAND_DELTA || self->type == RC_OPERAND_PRIOR) &&
535
+ self->type == parse->addsource_parent.type) {
536
+ /* if adding prev(x) and prev(y), just add x and y and take the prev of that.
537
+ * same for adding prior(x) and prior(y). */
538
+ rc_operand_t modifier;
539
+ memcpy(&modifier, self, sizeof(modifier));
540
+ modifier.type = parse->addsource_parent.type = RC_OPERAND_ADDRESS;
541
+
542
+ modified_memref = rc_alloc_modified_memref(parse,
543
+ new_size, &parse->addsource_parent, parse->addsource_oper, &modifier);
544
+ }
545
+ else {
546
+ modified_memref = rc_alloc_modified_memref(parse,
547
+ new_size, &parse->addsource_parent, parse->addsource_oper, self);
548
+
549
+ /* the modified memref will contain the combination of modified values, take the current value from that */
550
+ self->type = self->memref_access_type = RC_OPERAND_ADDRESS;
551
+ }
552
+
553
+ self->value.memref = (rc_memref_t*)modified_memref;
554
+
555
+ /* result of an AddSource operation is always a 32-bit integer (even if parent or modifier is a float) */
556
+ self->size = RC_MEMSIZE_32_BITS;
557
+ }
558
+
559
+ void rc_evaluate_operand(rc_typed_value_t* result, const rc_operand_t* self, rc_eval_state_t* eval_state) {
560
+ /* step 1: read memory */
561
+ switch (self->type) {
562
+ case RC_OPERAND_CONST:
563
+ result->type = RC_VALUE_TYPE_UNSIGNED;
564
+ result->value.u32 = self->value.num;
565
+ return;
566
+
567
+ case RC_OPERAND_FP:
568
+ result->type = RC_VALUE_TYPE_FLOAT;
569
+ result->value.f32 = (float)self->value.dbl;
570
+ return;
571
+
572
+ case RC_OPERAND_FUNC:
573
+ /* this feature was never actualized */
574
+ result->type = RC_VALUE_TYPE_UNSIGNED;
575
+ result->value.u32 = 0;
576
+ return;
577
+
578
+ case RC_OPERAND_RECALL:
579
+ if (!rc_operand_type_is_memref(self->memref_access_type)) {
580
+ rc_operand_t recall;
581
+ memcpy(&recall, self, sizeof(recall));
582
+ recall.type = self->memref_access_type;
583
+ rc_evaluate_operand(result, &recall, eval_state);
584
+ return;
585
+ }
586
+
587
+ if (!self->value.memref) {
588
+ result->type = RC_VALUE_TYPE_UNSIGNED;
589
+ result->value.u32 = 0;
590
+ return;
591
+ }
592
+
593
+ rc_get_memref_value(result, self->value.memref, self->memref_access_type);
594
+ break;
595
+
596
+ default:
597
+ rc_get_memref_value(result, self->value.memref, self->type);
598
+ break;
599
+ }
600
+
601
+ /* step 2: convert read memory to desired format */
602
+ rc_transform_memref_value(result, self->size);
603
+
604
+ /* step 3: apply logic (BCD/invert) */
605
+ if (result->type == RC_VALUE_TYPE_UNSIGNED)
606
+ result->value.u32 = rc_transform_operand_value(result->value.u32, self);
607
+ }