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.
- checksums.yaml +4 -4
- data/THIRD_PARTY_NOTICES +37 -2
- data/assets/placeholder_boxart.png +0 -0
- data/bin/gemba +2 -2
- data/ext/gemba/extconf.rb +23 -1
- data/ext/gemba/gemba_ext.c +436 -2
- data/ext/gemba/gemba_ext.h +2 -0
- data/gemba.gemspec +5 -3
- data/lib/gemba/achievements/achievement.rb +23 -0
- data/lib/gemba/achievements/backend.rb +186 -0
- data/lib/gemba/achievements/cache.rb +70 -0
- data/lib/gemba/achievements/credentials_presenter.rb +142 -0
- data/lib/gemba/achievements/fake_backend.rb +205 -0
- data/lib/gemba/achievements/null_backend.rb +11 -0
- data/lib/gemba/achievements/offline_backend.rb +168 -0
- data/lib/gemba/achievements/retro_achievements/backend.rb +453 -0
- data/lib/gemba/achievements/retro_achievements/cli_sync_requester.rb +64 -0
- data/lib/gemba/achievements/retro_achievements/ping_worker.rb +27 -0
- data/lib/gemba/achievements.rb +19 -0
- data/lib/gemba/achievements_window.rb +556 -0
- data/lib/gemba/app_controller.rb +1015 -0
- data/lib/gemba/bios.rb +54 -0
- data/lib/gemba/boxart_fetcher/libretro_backend.rb +39 -0
- data/lib/gemba/boxart_fetcher/null_backend.rb +12 -0
- data/lib/gemba/boxart_fetcher.rb +79 -0
- data/lib/gemba/bus_emitter.rb +13 -0
- data/lib/gemba/child_window.rb +24 -1
- data/lib/gemba/cli/commands/config_cmd.rb +83 -0
- data/lib/gemba/cli/commands/decode.rb +154 -0
- data/lib/gemba/cli/commands/patch.rb +78 -0
- data/lib/gemba/cli/commands/play.rb +78 -0
- data/lib/gemba/cli/commands/record.rb +114 -0
- data/lib/gemba/cli/commands/replay.rb +161 -0
- data/lib/gemba/cli/commands/retro_achievements.rb +213 -0
- data/lib/gemba/cli/commands/version.rb +22 -0
- data/lib/gemba/cli.rb +52 -364
- data/lib/gemba/config.rb +134 -1
- data/lib/gemba/data/gb_games.json +1 -0
- data/lib/gemba/data/gb_md5.json +1 -0
- data/lib/gemba/data/gba_games.json +1 -0
- data/lib/gemba/data/gba_md5.json +1 -0
- data/lib/gemba/data/gbc_games.json +1 -0
- data/lib/gemba/data/gbc_md5.json +1 -0
- data/lib/gemba/emulator_frame.rb +1060 -0
- data/lib/gemba/event_bus.rb +48 -0
- data/lib/gemba/frame_stack.rb +60 -0
- data/lib/gemba/game_index.rb +84 -0
- data/lib/gemba/game_picker_frame.rb +268 -0
- data/lib/gemba/gamepad_map.rb +103 -0
- data/lib/gemba/headless.rb +6 -5
- data/lib/gemba/headless_player.rb +33 -3
- data/lib/gemba/help_window.rb +61 -0
- data/lib/gemba/hotkey_map.rb +3 -1
- data/lib/gemba/input_recorder.rb +107 -0
- data/lib/gemba/input_replayer.rb +119 -0
- data/lib/gemba/keyboard_map.rb +90 -0
- data/lib/gemba/locales/en.yml +97 -5
- data/lib/gemba/locales/ja.yml +97 -5
- data/lib/gemba/main_window.rb +56 -0
- data/lib/gemba/modal_stack.rb +81 -0
- data/lib/gemba/patcher_window.rb +223 -0
- data/lib/gemba/platform/gb.rb +21 -0
- data/lib/gemba/platform/gba.rb +21 -0
- data/lib/gemba/platform/gbc.rb +23 -0
- data/lib/gemba/platform.rb +20 -0
- data/lib/gemba/platform_open.rb +19 -0
- data/lib/gemba/recorder.rb +4 -3
- data/lib/gemba/replay_player.rb +691 -0
- data/lib/gemba/rom_info.rb +57 -0
- data/lib/gemba/rom_info_window.rb +16 -3
- data/lib/gemba/rom_library.rb +106 -0
- data/lib/gemba/rom_overrides.rb +47 -0
- data/lib/gemba/rom_patcher/bps.rb +161 -0
- data/lib/gemba/rom_patcher/ips.rb +101 -0
- data/lib/gemba/rom_patcher/ups.rb +118 -0
- data/lib/gemba/rom_patcher.rb +109 -0
- data/lib/gemba/{rom_loader.rb → rom_resolver.rb} +7 -6
- data/lib/gemba/runtime.rb +59 -26
- data/lib/gemba/save_state_manager.rb +4 -7
- data/lib/gemba/save_state_picker.rb +17 -4
- data/lib/gemba/session_logger.rb +64 -0
- data/lib/gemba/settings/audio_tab.rb +77 -0
- data/lib/gemba/settings/gamepad_tab.rb +351 -0
- data/lib/gemba/settings/hotkeys_tab.rb +259 -0
- data/lib/gemba/settings/paths.rb +11 -0
- data/lib/gemba/settings/recording_tab.rb +83 -0
- data/lib/gemba/settings/save_states_tab.rb +91 -0
- data/lib/gemba/settings/system_tab.rb +362 -0
- data/lib/gemba/settings/video_tab.rb +318 -0
- data/lib/gemba/settings_window.rb +162 -1036
- data/lib/gemba/version.rb +1 -1
- data/lib/gemba/virtual_keyboard.rb +19 -0
- data/lib/gemba.rb +2 -12
- data/test/achievements_window/test_bulk_sync.rb +218 -0
- data/test/achievements_window/test_bus_events.rb +125 -0
- data/test/achievements_window/test_close_confirmation.rb +201 -0
- data/test/achievements_window/test_initial_state.rb +164 -0
- data/test/achievements_window/test_sorting.rb +227 -0
- data/test/achievements_window/test_tree_rendering.rb +133 -0
- data/test/fixtures/fake_bios.bin +0 -0
- data/test/fixtures/pong.gba +0 -0
- data/test/fixtures/test.gb +0 -0
- data/test/fixtures/test.gbc +0 -0
- data/test/fixtures/test_quicksave.ss +0 -0
- data/test/screenshots/no_focus.png +0 -0
- data/test/shared/teek_test_worker.rb +17 -1
- data/test/shared/tk_test_helper.rb +91 -4
- data/test/support/achievements_window_helpers.rb +18 -0
- data/test/support/fake_core.rb +25 -0
- data/test/support/fake_ra_runtime.rb +74 -0
- data/test/support/fake_requester.rb +68 -0
- data/test/support/player_helpers.rb +20 -5
- data/test/test_achievement.rb +32 -0
- data/test/{test_player.rb → test_app_controller.rb} +353 -85
- data/test/test_bios.rb +123 -0
- data/test/test_boxart_fetcher.rb +150 -0
- data/test/test_cli.rb +17 -265
- data/test/test_cli_config.rb +64 -0
- data/test/test_cli_decode.rb +97 -0
- data/test/test_cli_patch.rb +58 -0
- data/test/test_cli_play.rb +213 -0
- data/test/test_cli_ra.rb +175 -0
- data/test/test_cli_record.rb +69 -0
- data/test/test_cli_replay.rb +72 -0
- data/test/test_cli_sync_requester.rb +152 -0
- data/test/test_cli_version.rb +27 -0
- data/test/test_config.rb +2 -3
- data/test/test_config_ra.rb +69 -0
- data/test/test_core.rb +62 -1
- data/test/test_credentials_presenter.rb +192 -0
- data/test/test_event_bus.rb +100 -0
- data/test/test_fake_backend_achievements.rb +130 -0
- data/test/test_fake_backend_auth.rb +68 -0
- data/test/test_game_index.rb +77 -0
- data/test/test_game_picker_frame.rb +310 -0
- data/test/test_gamepad_map.rb +1 -3
- data/test/test_headless_player.rb +17 -3
- data/test/test_help_window.rb +82 -0
- data/test/test_hotkey_map.rb +22 -1
- data/test/test_input_recorder.rb +179 -0
- data/test/test_input_replay_determinism.rb +113 -0
- data/test/test_input_replayer.rb +162 -0
- data/test/test_keyboard_map.rb +1 -3
- data/test/test_libretro_backend.rb +41 -0
- data/test/test_locale.rb +1 -1
- data/test/test_logging.rb +123 -0
- data/test/test_null_backend.rb +42 -0
- data/test/test_offline_backend.rb +116 -0
- data/test/test_overlay_renderer.rb +1 -1
- data/test/test_platform.rb +149 -0
- data/test/test_ra_backend.rb +313 -0
- data/test/test_ra_backend_unlock_gate.rb +56 -0
- data/test/test_recorder.rb +0 -3
- data/test/test_replay_player.rb +316 -0
- data/test/test_rom_info.rb +149 -0
- data/test/test_rom_overrides.rb +86 -0
- data/test/test_rom_patcher.rb +382 -0
- data/test/{test_rom_loader.rb → test_rom_resolver.rb} +25 -26
- data/test/test_save_state_manager.rb +2 -4
- data/test/test_settings_audio.rb +107 -0
- data/test/test_settings_hotkeys.rb +83 -66
- data/test/test_settings_recording.rb +49 -0
- data/test/test_settings_save_states.rb +97 -0
- data/test/test_settings_system.rb +133 -0
- data/test/test_settings_video.rb +450 -0
- data/test/test_settings_window.rb +76 -507
- data/test/test_tip_service.rb +6 -6
- data/test/test_toast_overlay.rb +1 -1
- data/test/test_virtual_events.rb +156 -0
- data/test/test_virtual_keyboard.rb +1 -1
- data/vendor/rcheevos/CHANGELOG.md +495 -0
- data/vendor/rcheevos/LICENSE +21 -0
- data/vendor/rcheevos/Package.swift +33 -0
- data/vendor/rcheevos/README.md +67 -0
- data/vendor/rcheevos/include/module.modulemap +70 -0
- data/vendor/rcheevos/include/rc_api_editor.h +296 -0
- data/vendor/rcheevos/include/rc_api_info.h +280 -0
- data/vendor/rcheevos/include/rc_api_request.h +77 -0
- data/vendor/rcheevos/include/rc_api_runtime.h +417 -0
- data/vendor/rcheevos/include/rc_api_user.h +262 -0
- data/vendor/rcheevos/include/rc_client.h +877 -0
- data/vendor/rcheevos/include/rc_client_raintegration.h +101 -0
- data/vendor/rcheevos/include/rc_consoles.h +138 -0
- data/vendor/rcheevos/include/rc_error.h +59 -0
- data/vendor/rcheevos/include/rc_export.h +100 -0
- data/vendor/rcheevos/include/rc_hash.h +200 -0
- data/vendor/rcheevos/include/rc_runtime.h +148 -0
- data/vendor/rcheevos/include/rc_runtime_types.h +452 -0
- data/vendor/rcheevos/include/rc_util.h +51 -0
- data/vendor/rcheevos/include/rcheevos.h +8 -0
- data/vendor/rcheevos/src/rapi/rc_api_common.c +1379 -0
- data/vendor/rcheevos/src/rapi/rc_api_common.h +88 -0
- data/vendor/rcheevos/src/rapi/rc_api_editor.c +625 -0
- data/vendor/rcheevos/src/rapi/rc_api_info.c +587 -0
- data/vendor/rcheevos/src/rapi/rc_api_runtime.c +901 -0
- data/vendor/rcheevos/src/rapi/rc_api_user.c +483 -0
- data/vendor/rcheevos/src/rc_client.c +6941 -0
- data/vendor/rcheevos/src/rc_client_external.c +281 -0
- data/vendor/rcheevos/src/rc_client_external.h +177 -0
- data/vendor/rcheevos/src/rc_client_external_versions.h +171 -0
- data/vendor/rcheevos/src/rc_client_internal.h +409 -0
- data/vendor/rcheevos/src/rc_client_raintegration.c +566 -0
- data/vendor/rcheevos/src/rc_client_raintegration_internal.h +61 -0
- data/vendor/rcheevos/src/rc_client_types.natvis +396 -0
- data/vendor/rcheevos/src/rc_compat.c +251 -0
- data/vendor/rcheevos/src/rc_compat.h +121 -0
- data/vendor/rcheevos/src/rc_libretro.c +915 -0
- data/vendor/rcheevos/src/rc_libretro.h +98 -0
- data/vendor/rcheevos/src/rc_util.c +199 -0
- data/vendor/rcheevos/src/rc_version.c +11 -0
- data/vendor/rcheevos/src/rc_version.h +32 -0
- data/vendor/rcheevos/src/rcheevos/alloc.c +312 -0
- data/vendor/rcheevos/src/rcheevos/condition.c +754 -0
- data/vendor/rcheevos/src/rcheevos/condset.c +777 -0
- data/vendor/rcheevos/src/rcheevos/consoleinfo.c +1215 -0
- data/vendor/rcheevos/src/rcheevos/format.c +330 -0
- data/vendor/rcheevos/src/rcheevos/lboard.c +287 -0
- data/vendor/rcheevos/src/rcheevos/memref.c +805 -0
- data/vendor/rcheevos/src/rcheevos/operand.c +607 -0
- data/vendor/rcheevos/src/rcheevos/rc_internal.h +390 -0
- data/vendor/rcheevos/src/rcheevos/rc_runtime_types.natvis +541 -0
- data/vendor/rcheevos/src/rcheevos/rc_validate.c +1406 -0
- data/vendor/rcheevos/src/rcheevos/rc_validate.h +18 -0
- data/vendor/rcheevos/src/rcheevos/richpresence.c +922 -0
- data/vendor/rcheevos/src/rcheevos/runtime.c +852 -0
- data/vendor/rcheevos/src/rcheevos/runtime_progress.c +1073 -0
- data/vendor/rcheevos/src/rcheevos/trigger.c +344 -0
- data/vendor/rcheevos/src/rcheevos/value.c +935 -0
- data/vendor/rcheevos/src/rhash/aes.c +480 -0
- data/vendor/rcheevos/src/rhash/aes.h +49 -0
- data/vendor/rcheevos/src/rhash/cdreader.c +838 -0
- data/vendor/rcheevos/src/rhash/hash.c +1402 -0
- data/vendor/rcheevos/src/rhash/hash_disc.c +1340 -0
- data/vendor/rcheevos/src/rhash/hash_encrypted.c +566 -0
- data/vendor/rcheevos/src/rhash/hash_rom.c +426 -0
- data/vendor/rcheevos/src/rhash/hash_zip.c +460 -0
- data/vendor/rcheevos/src/rhash/md5.c +382 -0
- data/vendor/rcheevos/src/rhash/md5.h +91 -0
- data/vendor/rcheevos/src/rhash/rc_hash_internal.h +116 -0
- data/vendor/rcheevos/test/libretro.h +205 -0
- data/vendor/rcheevos/test/rapi/test_rc_api_common.c +941 -0
- data/vendor/rcheevos/test/rapi/test_rc_api_editor.c +931 -0
- data/vendor/rcheevos/test/rapi/test_rc_api_info.c +545 -0
- data/vendor/rcheevos/test/rapi/test_rc_api_runtime.c +2213 -0
- data/vendor/rcheevos/test/rapi/test_rc_api_user.c +998 -0
- data/vendor/rcheevos/test/rcheevos/mock_memory.h +32 -0
- data/vendor/rcheevos/test/rcheevos/test_condition.c +570 -0
- data/vendor/rcheevos/test/rcheevos/test_condset.c +5170 -0
- data/vendor/rcheevos/test/rcheevos/test_consoleinfo.c +203 -0
- data/vendor/rcheevos/test/rcheevos/test_format.c +112 -0
- data/vendor/rcheevos/test/rcheevos/test_lboard.c +746 -0
- data/vendor/rcheevos/test/rcheevos/test_memref.c +520 -0
- data/vendor/rcheevos/test/rcheevos/test_operand.c +692 -0
- data/vendor/rcheevos/test/rcheevos/test_rc_validate.c +502 -0
- data/vendor/rcheevos/test/rcheevos/test_richpresence.c +1564 -0
- data/vendor/rcheevos/test/rcheevos/test_runtime.c +1667 -0
- data/vendor/rcheevos/test/rcheevos/test_runtime_progress.c +1821 -0
- data/vendor/rcheevos/test/rcheevos/test_timing.c +166 -0
- data/vendor/rcheevos/test/rcheevos/test_trigger.c +2521 -0
- data/vendor/rcheevos/test/rcheevos/test_value.c +870 -0
- data/vendor/rcheevos/test/rcheevos-test.sln +46 -0
- data/vendor/rcheevos/test/rcheevos-test.vcxproj +239 -0
- data/vendor/rcheevos/test/rcheevos-test.vcxproj.filters +335 -0
- data/vendor/rcheevos/test/rhash/data.c +657 -0
- data/vendor/rcheevos/test/rhash/data.h +32 -0
- data/vendor/rcheevos/test/rhash/mock_filereader.c +236 -0
- data/vendor/rcheevos/test/rhash/mock_filereader.h +31 -0
- data/vendor/rcheevos/test/rhash/test_cdreader.c +920 -0
- data/vendor/rcheevos/test/rhash/test_hash.c +310 -0
- data/vendor/rcheevos/test/rhash/test_hash_disc.c +1450 -0
- data/vendor/rcheevos/test/rhash/test_hash_rom.c +899 -0
- data/vendor/rcheevos/test/rhash/test_hash_zip.c +551 -0
- data/vendor/rcheevos/test/test.c +113 -0
- data/vendor/rcheevos/test/test_framework.h +205 -0
- data/vendor/rcheevos/test/test_rc_client.c +10509 -0
- data/vendor/rcheevos/test/test_rc_client_external.c +2197 -0
- data/vendor/rcheevos/test/test_rc_client_raintegration.c +441 -0
- data/vendor/rcheevos/test/test_rc_libretro.c +952 -0
- data/vendor/rcheevos/test/test_types.natvis +9 -0
- data/vendor/rcheevos/validator/validator.c +658 -0
- data/vendor/rcheevos/validator/validator.vcxproj +152 -0
- data/vendor/rcheevos/validator/validator.vcxproj.filters +82 -0
- metadata +274 -11
- data/lib/gemba/input_mappings.rb +0 -214
- 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
|
+
}
|