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,344 @@
|
|
|
1
|
+
#include "rc_internal.h"
|
|
2
|
+
|
|
3
|
+
#include <stddef.h>
|
|
4
|
+
#include <string.h> /* memset */
|
|
5
|
+
|
|
6
|
+
void rc_parse_trigger_internal(rc_trigger_t* self, const char** memaddr, rc_parse_state_t* parse) {
|
|
7
|
+
rc_condset_t** next;
|
|
8
|
+
const char* aux;
|
|
9
|
+
|
|
10
|
+
aux = *memaddr;
|
|
11
|
+
next = &self->alternative;
|
|
12
|
+
|
|
13
|
+
/* reset in case multiple triggers are parsed by the same parse_state */
|
|
14
|
+
parse->measured_target = 0;
|
|
15
|
+
parse->has_required_hits = 0;
|
|
16
|
+
parse->measured_as_percent = 0;
|
|
17
|
+
|
|
18
|
+
if (*aux == 's' || *aux == 'S') {
|
|
19
|
+
self->requirement = NULL;
|
|
20
|
+
}
|
|
21
|
+
else {
|
|
22
|
+
self->requirement = rc_parse_condset(&aux, parse);
|
|
23
|
+
|
|
24
|
+
if (parse->offset < 0)
|
|
25
|
+
return;
|
|
26
|
+
|
|
27
|
+
self->requirement->next = NULL;
|
|
28
|
+
}
|
|
29
|
+
|
|
30
|
+
while (*aux == 's' || *aux == 'S') {
|
|
31
|
+
aux++;
|
|
32
|
+
*next = rc_parse_condset(&aux, parse);
|
|
33
|
+
|
|
34
|
+
if (parse->offset < 0) {
|
|
35
|
+
return;
|
|
36
|
+
}
|
|
37
|
+
|
|
38
|
+
next = &(*next)->next;
|
|
39
|
+
}
|
|
40
|
+
|
|
41
|
+
*next = NULL;
|
|
42
|
+
*memaddr = aux;
|
|
43
|
+
|
|
44
|
+
self->measured_target = parse->measured_target;
|
|
45
|
+
self->measured_value = parse->measured_target ? RC_MEASURED_UNKNOWN : 0;
|
|
46
|
+
self->measured_as_percent = parse->measured_as_percent;
|
|
47
|
+
self->state = RC_TRIGGER_STATE_WAITING;
|
|
48
|
+
self->has_hits = 0;
|
|
49
|
+
self->has_memrefs = 0;
|
|
50
|
+
}
|
|
51
|
+
|
|
52
|
+
int rc_trigger_size(const char* memaddr) {
|
|
53
|
+
rc_trigger_with_memrefs_t* trigger;
|
|
54
|
+
rc_preparse_state_t preparse;
|
|
55
|
+
rc_init_preparse_state(&preparse);
|
|
56
|
+
|
|
57
|
+
trigger = RC_ALLOC(rc_trigger_with_memrefs_t, &preparse.parse);
|
|
58
|
+
rc_parse_trigger_internal(&trigger->trigger, &memaddr, &preparse.parse);
|
|
59
|
+
rc_preparse_alloc_memrefs(NULL, &preparse);
|
|
60
|
+
|
|
61
|
+
rc_destroy_preparse_state(&preparse);
|
|
62
|
+
return preparse.parse.offset;
|
|
63
|
+
}
|
|
64
|
+
|
|
65
|
+
rc_trigger_t* rc_parse_trigger(void* buffer, const char* memaddr, void* unused_L, int unused_funcs_idx) {
|
|
66
|
+
rc_trigger_with_memrefs_t* trigger;
|
|
67
|
+
rc_preparse_state_t preparse;
|
|
68
|
+
const char* preparse_memaddr = memaddr;
|
|
69
|
+
|
|
70
|
+
(void)unused_L;
|
|
71
|
+
(void)unused_funcs_idx;
|
|
72
|
+
|
|
73
|
+
if (!buffer || !memaddr)
|
|
74
|
+
return NULL;
|
|
75
|
+
|
|
76
|
+
/* first pass : determine how many memrefs are needed */
|
|
77
|
+
rc_init_preparse_state(&preparse);
|
|
78
|
+
trigger = RC_ALLOC(rc_trigger_with_memrefs_t, &preparse.parse);
|
|
79
|
+
rc_parse_trigger_internal(&trigger->trigger, &preparse_memaddr, &preparse.parse);
|
|
80
|
+
|
|
81
|
+
/* allocate the trigger and memrefs */
|
|
82
|
+
rc_reset_parse_state(&preparse.parse, buffer);
|
|
83
|
+
trigger = RC_ALLOC(rc_trigger_with_memrefs_t, &preparse.parse);
|
|
84
|
+
rc_preparse_alloc_memrefs(&trigger->memrefs, &preparse);
|
|
85
|
+
|
|
86
|
+
/* parse the trigger */
|
|
87
|
+
rc_parse_trigger_internal(&trigger->trigger, &memaddr, &preparse.parse);
|
|
88
|
+
trigger->trigger.has_memrefs = 1;
|
|
89
|
+
|
|
90
|
+
rc_destroy_preparse_state(&preparse);
|
|
91
|
+
return (preparse.parse.offset >= 0) ? &trigger->trigger : NULL;
|
|
92
|
+
}
|
|
93
|
+
|
|
94
|
+
int rc_trigger_state_active(int state)
|
|
95
|
+
{
|
|
96
|
+
switch (state)
|
|
97
|
+
{
|
|
98
|
+
case RC_TRIGGER_STATE_DISABLED:
|
|
99
|
+
case RC_TRIGGER_STATE_INACTIVE:
|
|
100
|
+
case RC_TRIGGER_STATE_TRIGGERED:
|
|
101
|
+
return 0;
|
|
102
|
+
|
|
103
|
+
default:
|
|
104
|
+
return 1;
|
|
105
|
+
}
|
|
106
|
+
}
|
|
107
|
+
|
|
108
|
+
static int rc_condset_is_measured_from_hitcount(const rc_condset_t* condset, uint32_t measured_value)
|
|
109
|
+
{
|
|
110
|
+
const rc_condition_t* condition;
|
|
111
|
+
for (condition = condset->conditions; condition; condition = condition->next) {
|
|
112
|
+
if (condition->type == RC_CONDITION_MEASURED && condition->required_hits &&
|
|
113
|
+
condition->current_hits == measured_value) {
|
|
114
|
+
return 1;
|
|
115
|
+
}
|
|
116
|
+
}
|
|
117
|
+
|
|
118
|
+
return 0;
|
|
119
|
+
}
|
|
120
|
+
|
|
121
|
+
static void rc_reset_trigger_hitcounts(rc_trigger_t* self) {
|
|
122
|
+
rc_condset_t* condset;
|
|
123
|
+
|
|
124
|
+
if (self->requirement) {
|
|
125
|
+
rc_reset_condset(self->requirement);
|
|
126
|
+
}
|
|
127
|
+
|
|
128
|
+
condset = self->alternative;
|
|
129
|
+
|
|
130
|
+
while (condset) {
|
|
131
|
+
rc_reset_condset(condset);
|
|
132
|
+
condset = condset->next;
|
|
133
|
+
}
|
|
134
|
+
}
|
|
135
|
+
|
|
136
|
+
static void rc_update_trigger_memrefs(rc_trigger_t* self, rc_peek_t peek, void* ud) {
|
|
137
|
+
if (self->has_memrefs) {
|
|
138
|
+
rc_trigger_with_memrefs_t* trigger = (rc_trigger_with_memrefs_t*)self;
|
|
139
|
+
rc_update_memref_values(&trigger->memrefs, peek, ud);
|
|
140
|
+
}
|
|
141
|
+
}
|
|
142
|
+
|
|
143
|
+
rc_memrefs_t* rc_trigger_get_memrefs(rc_trigger_t* self) {
|
|
144
|
+
if (self->has_memrefs) {
|
|
145
|
+
rc_trigger_with_memrefs_t* trigger = (rc_trigger_with_memrefs_t*)self;
|
|
146
|
+
return &trigger->memrefs;
|
|
147
|
+
}
|
|
148
|
+
|
|
149
|
+
return NULL;
|
|
150
|
+
}
|
|
151
|
+
|
|
152
|
+
int rc_evaluate_trigger(rc_trigger_t* self, rc_peek_t peek, void* ud, void* unused_L) {
|
|
153
|
+
rc_eval_state_t eval_state;
|
|
154
|
+
rc_condset_t* condset;
|
|
155
|
+
rc_typed_value_t measured_value;
|
|
156
|
+
int measured_from_hits = 0;
|
|
157
|
+
int ret;
|
|
158
|
+
char is_paused;
|
|
159
|
+
char is_primed;
|
|
160
|
+
|
|
161
|
+
(void)unused_L;
|
|
162
|
+
|
|
163
|
+
switch (self->state)
|
|
164
|
+
{
|
|
165
|
+
case RC_TRIGGER_STATE_TRIGGERED:
|
|
166
|
+
/* previously triggered. do nothing - return INACTIVE so caller doesn't think it triggered again */
|
|
167
|
+
return RC_TRIGGER_STATE_INACTIVE;
|
|
168
|
+
|
|
169
|
+
case RC_TRIGGER_STATE_DISABLED:
|
|
170
|
+
/* unsupported. do nothing - return INACTIVE */
|
|
171
|
+
return RC_TRIGGER_STATE_INACTIVE;
|
|
172
|
+
|
|
173
|
+
case RC_TRIGGER_STATE_INACTIVE:
|
|
174
|
+
/* not yet active. update the memrefs so deltas are correct when it becomes active, then return INACTIVE */
|
|
175
|
+
rc_update_trigger_memrefs(self, peek, ud);
|
|
176
|
+
return RC_TRIGGER_STATE_INACTIVE;
|
|
177
|
+
|
|
178
|
+
default:
|
|
179
|
+
break;
|
|
180
|
+
}
|
|
181
|
+
|
|
182
|
+
/* update the memory references */
|
|
183
|
+
rc_update_trigger_memrefs(self, peek, ud);
|
|
184
|
+
|
|
185
|
+
/* process the trigger */
|
|
186
|
+
memset(&eval_state, 0, sizeof(eval_state));
|
|
187
|
+
eval_state.peek = peek;
|
|
188
|
+
eval_state.peek_userdata = ud;
|
|
189
|
+
|
|
190
|
+
measured_value.type = RC_VALUE_TYPE_NONE;
|
|
191
|
+
|
|
192
|
+
if (self->requirement != NULL) {
|
|
193
|
+
ret = rc_test_condset(self->requirement, &eval_state);
|
|
194
|
+
is_paused = eval_state.is_paused;
|
|
195
|
+
is_primed = eval_state.is_primed;
|
|
196
|
+
|
|
197
|
+
if (eval_state.measured_value.type != RC_VALUE_TYPE_NONE) {
|
|
198
|
+
memcpy(&measured_value, &eval_state.measured_value, sizeof(measured_value));
|
|
199
|
+
measured_from_hits = eval_state.measured_from_hits;
|
|
200
|
+
}
|
|
201
|
+
} else {
|
|
202
|
+
ret = 1;
|
|
203
|
+
is_paused = 0;
|
|
204
|
+
is_primed = 1;
|
|
205
|
+
}
|
|
206
|
+
|
|
207
|
+
condset = self->alternative;
|
|
208
|
+
if (condset) {
|
|
209
|
+
int sub = 0;
|
|
210
|
+
char sub_paused = 1;
|
|
211
|
+
char sub_primed = 0;
|
|
212
|
+
|
|
213
|
+
do {
|
|
214
|
+
sub |= rc_test_condset(condset, &eval_state);
|
|
215
|
+
sub_paused &= eval_state.is_paused;
|
|
216
|
+
sub_primed |= eval_state.is_primed;
|
|
217
|
+
|
|
218
|
+
if (eval_state.measured_value.type != RC_VALUE_TYPE_NONE) {
|
|
219
|
+
/* if no previous Measured value was captured, or the new one is greater, keep the new one */
|
|
220
|
+
if (measured_value.type == RC_VALUE_TYPE_NONE ||
|
|
221
|
+
rc_typed_value_compare(&eval_state.measured_value, &measured_value, RC_OPERATOR_GT)) {
|
|
222
|
+
memcpy(&measured_value, &eval_state.measured_value, sizeof(measured_value));
|
|
223
|
+
measured_from_hits = eval_state.measured_from_hits;
|
|
224
|
+
}
|
|
225
|
+
}
|
|
226
|
+
|
|
227
|
+
condset = condset->next;
|
|
228
|
+
} while (condset);
|
|
229
|
+
|
|
230
|
+
/* to trigger, the core must be true and at least one alt must be true */
|
|
231
|
+
ret &= sub;
|
|
232
|
+
is_primed &= sub_primed;
|
|
233
|
+
|
|
234
|
+
/* if the core is not paused, all alts must be paused to count as a paused trigger */
|
|
235
|
+
is_paused |= sub_paused;
|
|
236
|
+
}
|
|
237
|
+
|
|
238
|
+
if (is_paused) {
|
|
239
|
+
/* if the trigger is fully paused, ignore any updates to the measured value */
|
|
240
|
+
}
|
|
241
|
+
else if (measured_value.type == RC_VALUE_TYPE_NONE) {
|
|
242
|
+
/* if a measured value was not captured, keep the old value (it's possible to pause
|
|
243
|
+
* an alt that is generating the measured value without fully pausing the trigger) */
|
|
244
|
+
}
|
|
245
|
+
else {
|
|
246
|
+
rc_typed_value_convert(&measured_value, RC_VALUE_TYPE_UNSIGNED);
|
|
247
|
+
self->measured_value = measured_value.value.u32;
|
|
248
|
+
}
|
|
249
|
+
|
|
250
|
+
/* if any ResetIf condition was true, reset the hit counts */
|
|
251
|
+
if (eval_state.was_reset) {
|
|
252
|
+
/* if the measured value came from a hit count, reset it. do this before calling
|
|
253
|
+
* rc_reset_trigger_hitcounts in case we need to call rc_condset_is_measured_from_hitcount */
|
|
254
|
+
if (measured_from_hits) {
|
|
255
|
+
self->measured_value = 0;
|
|
256
|
+
}
|
|
257
|
+
else if (is_paused && self->measured_value) {
|
|
258
|
+
/* if the measured value is in a paused group, measured_from_hits won't have been set.
|
|
259
|
+
* attempt to determine if it should have been */
|
|
260
|
+
if (self->requirement && self->requirement->is_paused &&
|
|
261
|
+
rc_condset_is_measured_from_hitcount(self->requirement, self->measured_value)) {
|
|
262
|
+
self->measured_value = 0;
|
|
263
|
+
}
|
|
264
|
+
else {
|
|
265
|
+
for (condset = self->alternative; condset; condset = condset->next) {
|
|
266
|
+
if (condset->is_paused && rc_condset_is_measured_from_hitcount(condset, self->measured_value)) {
|
|
267
|
+
self->measured_value = 0;
|
|
268
|
+
break;
|
|
269
|
+
}
|
|
270
|
+
}
|
|
271
|
+
}
|
|
272
|
+
}
|
|
273
|
+
|
|
274
|
+
rc_reset_trigger_hitcounts(self);
|
|
275
|
+
|
|
276
|
+
/* if there were hit counts to clear, return RESET, but don't change the state */
|
|
277
|
+
if (self->has_hits) {
|
|
278
|
+
self->has_hits = 0;
|
|
279
|
+
|
|
280
|
+
/* cannot be PRIMED while ResetIf is true */
|
|
281
|
+
if (self->state == RC_TRIGGER_STATE_PRIMED)
|
|
282
|
+
self->state = RC_TRIGGER_STATE_ACTIVE;
|
|
283
|
+
|
|
284
|
+
return RC_TRIGGER_STATE_RESET;
|
|
285
|
+
}
|
|
286
|
+
|
|
287
|
+
/* any hits that were tallied were just reset */
|
|
288
|
+
eval_state.has_hits = 0;
|
|
289
|
+
is_primed = 0;
|
|
290
|
+
}
|
|
291
|
+
else if (ret) {
|
|
292
|
+
/* if the state is WAITING and the trigger is ready to fire, ignore it and reset the hit counts */
|
|
293
|
+
if (self->state == RC_TRIGGER_STATE_WAITING) {
|
|
294
|
+
rc_reset_trigger(self);
|
|
295
|
+
self->has_hits = 0;
|
|
296
|
+
return RC_TRIGGER_STATE_WAITING;
|
|
297
|
+
}
|
|
298
|
+
|
|
299
|
+
/* trigger was triggered */
|
|
300
|
+
self->state = RC_TRIGGER_STATE_TRIGGERED;
|
|
301
|
+
return RC_TRIGGER_STATE_TRIGGERED;
|
|
302
|
+
}
|
|
303
|
+
|
|
304
|
+
/* did not trigger this frame - update the information we'll need for next time */
|
|
305
|
+
self->has_hits = eval_state.has_hits;
|
|
306
|
+
|
|
307
|
+
if (is_paused) {
|
|
308
|
+
self->state = RC_TRIGGER_STATE_PAUSED;
|
|
309
|
+
}
|
|
310
|
+
else if (is_primed) {
|
|
311
|
+
self->state = RC_TRIGGER_STATE_PRIMED;
|
|
312
|
+
}
|
|
313
|
+
else {
|
|
314
|
+
self->state = RC_TRIGGER_STATE_ACTIVE;
|
|
315
|
+
}
|
|
316
|
+
|
|
317
|
+
/* if an individual condition was reset, notify the caller */
|
|
318
|
+
if (eval_state.was_cond_reset)
|
|
319
|
+
return RC_TRIGGER_STATE_RESET;
|
|
320
|
+
|
|
321
|
+
/* otherwise, just return the current state */
|
|
322
|
+
return self->state;
|
|
323
|
+
}
|
|
324
|
+
|
|
325
|
+
int rc_test_trigger(rc_trigger_t* self, rc_peek_t peek, void* ud, void* unused_L) {
|
|
326
|
+
/* for backwards compatibilty, rc_test_trigger always assumes the achievement is active */
|
|
327
|
+
self->state = RC_TRIGGER_STATE_ACTIVE;
|
|
328
|
+
|
|
329
|
+
return (rc_evaluate_trigger(self, peek, ud, unused_L) == RC_TRIGGER_STATE_TRIGGERED);
|
|
330
|
+
}
|
|
331
|
+
|
|
332
|
+
void rc_reset_trigger(rc_trigger_t* self) {
|
|
333
|
+
if (!self)
|
|
334
|
+
return;
|
|
335
|
+
|
|
336
|
+
rc_reset_trigger_hitcounts(self);
|
|
337
|
+
|
|
338
|
+
self->state = RC_TRIGGER_STATE_WAITING;
|
|
339
|
+
|
|
340
|
+
if (self->measured_target)
|
|
341
|
+
self->measured_value = RC_MEASURED_UNKNOWN;
|
|
342
|
+
|
|
343
|
+
self->has_hits = 0;
|
|
344
|
+
}
|