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,330 @@
|
|
|
1
|
+
#include "rc_internal.h"
|
|
2
|
+
|
|
3
|
+
#include "../rc_compat.h"
|
|
4
|
+
|
|
5
|
+
#include <string.h>
|
|
6
|
+
#include <stdio.h>
|
|
7
|
+
#include <ctype.h>
|
|
8
|
+
|
|
9
|
+
int rc_parse_format(const char* format_str) {
|
|
10
|
+
switch (*format_str++) {
|
|
11
|
+
case 'F':
|
|
12
|
+
if (!strcmp(format_str, "RAMES")) {
|
|
13
|
+
return RC_FORMAT_FRAMES;
|
|
14
|
+
}
|
|
15
|
+
if (!strncmp(format_str, "LOAT", 4) && format_str[4] >= '1' && format_str[4] <= '6' && format_str[5] == '\0') {
|
|
16
|
+
return RC_FORMAT_FLOAT1 + (format_str[4] - '1');
|
|
17
|
+
}
|
|
18
|
+
if (!strncmp(format_str, "IXED", 4) && format_str[4] >= '1' && format_str[4] <= '3' && format_str[5] == '\0') {
|
|
19
|
+
return RC_FORMAT_FIXED1 + (format_str[4] - '1');
|
|
20
|
+
}
|
|
21
|
+
|
|
22
|
+
break;
|
|
23
|
+
|
|
24
|
+
case 'T':
|
|
25
|
+
if (!strcmp(format_str, "IME")) {
|
|
26
|
+
return RC_FORMAT_FRAMES;
|
|
27
|
+
}
|
|
28
|
+
if (!strcmp(format_str, "IMESECS")) {
|
|
29
|
+
return RC_FORMAT_SECONDS;
|
|
30
|
+
}
|
|
31
|
+
if (!strcmp(format_str, "HOUSANDS")) {
|
|
32
|
+
return RC_FORMAT_THOUSANDS;
|
|
33
|
+
}
|
|
34
|
+
if (!strcmp(format_str, "ENS")) {
|
|
35
|
+
return RC_FORMAT_TENS;
|
|
36
|
+
}
|
|
37
|
+
|
|
38
|
+
break;
|
|
39
|
+
|
|
40
|
+
case 'S':
|
|
41
|
+
if (!strcmp(format_str, "ECS")) {
|
|
42
|
+
return RC_FORMAT_SECONDS;
|
|
43
|
+
}
|
|
44
|
+
if (!strcmp(format_str, "CORE")) {
|
|
45
|
+
return RC_FORMAT_SCORE;
|
|
46
|
+
}
|
|
47
|
+
if (!strcmp(format_str, "ECS_AS_MINS")) {
|
|
48
|
+
return RC_FORMAT_SECONDS_AS_MINUTES;
|
|
49
|
+
}
|
|
50
|
+
|
|
51
|
+
break;
|
|
52
|
+
|
|
53
|
+
case 'M':
|
|
54
|
+
if (!strcmp(format_str, "ILLISECS")) {
|
|
55
|
+
return RC_FORMAT_CENTISECS;
|
|
56
|
+
}
|
|
57
|
+
if (!strcmp(format_str, "INUTES")) {
|
|
58
|
+
return RC_FORMAT_MINUTES;
|
|
59
|
+
}
|
|
60
|
+
|
|
61
|
+
break;
|
|
62
|
+
|
|
63
|
+
case 'P':
|
|
64
|
+
if (!strcmp(format_str, "OINTS")) {
|
|
65
|
+
return RC_FORMAT_SCORE;
|
|
66
|
+
}
|
|
67
|
+
|
|
68
|
+
break;
|
|
69
|
+
|
|
70
|
+
case 'V':
|
|
71
|
+
if (!strcmp(format_str, "ALUE")) {
|
|
72
|
+
return RC_FORMAT_VALUE;
|
|
73
|
+
}
|
|
74
|
+
|
|
75
|
+
break;
|
|
76
|
+
|
|
77
|
+
case 'U':
|
|
78
|
+
if (!strcmp(format_str, "NSIGNED")) {
|
|
79
|
+
return RC_FORMAT_UNSIGNED_VALUE;
|
|
80
|
+
}
|
|
81
|
+
|
|
82
|
+
break;
|
|
83
|
+
|
|
84
|
+
case 'O':
|
|
85
|
+
if (!strcmp(format_str, "THER")) {
|
|
86
|
+
return RC_FORMAT_SCORE;
|
|
87
|
+
}
|
|
88
|
+
|
|
89
|
+
break;
|
|
90
|
+
|
|
91
|
+
case 'H':
|
|
92
|
+
if (!strcmp(format_str, "UNDREDS")) {
|
|
93
|
+
return RC_FORMAT_HUNDREDS;
|
|
94
|
+
}
|
|
95
|
+
|
|
96
|
+
break;
|
|
97
|
+
}
|
|
98
|
+
|
|
99
|
+
return RC_FORMAT_VALUE;
|
|
100
|
+
}
|
|
101
|
+
|
|
102
|
+
static int rc_format_value_minutes(char* buffer, size_t size, uint32_t minutes) {
|
|
103
|
+
uint32_t hours;
|
|
104
|
+
|
|
105
|
+
hours = minutes / 60;
|
|
106
|
+
minutes -= hours * 60;
|
|
107
|
+
return snprintf(buffer, size, "%uh%02u", hours, minutes);
|
|
108
|
+
}
|
|
109
|
+
|
|
110
|
+
static int rc_format_value_seconds(char* buffer, size_t size, uint32_t seconds) {
|
|
111
|
+
uint32_t hours, minutes;
|
|
112
|
+
|
|
113
|
+
/* apply modulus math to split the seconds into hours/minutes/seconds */
|
|
114
|
+
minutes = seconds / 60;
|
|
115
|
+
seconds -= minutes * 60;
|
|
116
|
+
if (minutes < 60) {
|
|
117
|
+
return snprintf(buffer, size, "%u:%02u", minutes, seconds);
|
|
118
|
+
}
|
|
119
|
+
|
|
120
|
+
hours = minutes / 60;
|
|
121
|
+
minutes -= hours * 60;
|
|
122
|
+
return snprintf(buffer, size, "%uh%02u:%02u", hours, minutes, seconds);
|
|
123
|
+
}
|
|
124
|
+
|
|
125
|
+
static int rc_format_value_centiseconds(char* buffer, size_t size, uint32_t centiseconds) {
|
|
126
|
+
uint32_t seconds;
|
|
127
|
+
int chars, chars2;
|
|
128
|
+
|
|
129
|
+
/* modulus off the centiseconds */
|
|
130
|
+
seconds = centiseconds / 100;
|
|
131
|
+
centiseconds -= seconds * 100;
|
|
132
|
+
|
|
133
|
+
chars = rc_format_value_seconds(buffer, size, seconds);
|
|
134
|
+
if (chars > 0) {
|
|
135
|
+
chars2 = snprintf(buffer + chars, size - chars, ".%02u", centiseconds);
|
|
136
|
+
if (chars2 > 0) {
|
|
137
|
+
chars += chars2;
|
|
138
|
+
} else {
|
|
139
|
+
chars = chars2;
|
|
140
|
+
}
|
|
141
|
+
}
|
|
142
|
+
|
|
143
|
+
return chars;
|
|
144
|
+
}
|
|
145
|
+
|
|
146
|
+
static int rc_format_value_fixed(char* buffer, size_t size, const char* format, int32_t value, int32_t factor)
|
|
147
|
+
{
|
|
148
|
+
if (value >= 0)
|
|
149
|
+
return snprintf(buffer, size, format, value / factor, value % factor);
|
|
150
|
+
|
|
151
|
+
return snprintf(buffer, size, format, value / factor, (-value) % factor);
|
|
152
|
+
}
|
|
153
|
+
|
|
154
|
+
static int rc_format_value_padded(char* buffer, size_t size, const char* format, int32_t value)
|
|
155
|
+
{
|
|
156
|
+
if (value == 0)
|
|
157
|
+
return snprintf(buffer, size, "0");
|
|
158
|
+
|
|
159
|
+
return snprintf(buffer, size, format, value);
|
|
160
|
+
}
|
|
161
|
+
|
|
162
|
+
static int rc_format_insert_commas(int chars, char* buffer, size_t size)
|
|
163
|
+
{
|
|
164
|
+
int to_insert;
|
|
165
|
+
char* src = buffer;
|
|
166
|
+
char* ptr;
|
|
167
|
+
char* dst = &buffer[chars];
|
|
168
|
+
if (chars == 0)
|
|
169
|
+
return 0;
|
|
170
|
+
|
|
171
|
+
/* ignore leading negative sign */
|
|
172
|
+
if (*src == '-')
|
|
173
|
+
src++;
|
|
174
|
+
|
|
175
|
+
/* determine how many digits are present in the leading number */
|
|
176
|
+
ptr = src;
|
|
177
|
+
while (ptr < dst && isdigit((int)*ptr))
|
|
178
|
+
++ptr;
|
|
179
|
+
|
|
180
|
+
/* determine how many commas are needed */
|
|
181
|
+
to_insert = (int)((ptr - src - 1) / 3);
|
|
182
|
+
if (to_insert == 0) /* no commas needed */
|
|
183
|
+
return chars;
|
|
184
|
+
|
|
185
|
+
/* if there's not enough room to insert the commas, leave string as-is, but return wanted space */
|
|
186
|
+
chars += to_insert;
|
|
187
|
+
if (chars >= (int)size)
|
|
188
|
+
return chars;
|
|
189
|
+
|
|
190
|
+
/* move the trailing part of the string */
|
|
191
|
+
memmove(ptr + to_insert, ptr, dst - ptr + 1);
|
|
192
|
+
|
|
193
|
+
/* shift blocks of three digits at a time, inserting commas in front of them */
|
|
194
|
+
src = ptr - 1;
|
|
195
|
+
dst = src + to_insert;
|
|
196
|
+
while (to_insert > 0) {
|
|
197
|
+
*dst-- = *src--;
|
|
198
|
+
*dst-- = *src--;
|
|
199
|
+
*dst-- = *src--;
|
|
200
|
+
*dst-- = ',';
|
|
201
|
+
|
|
202
|
+
--to_insert;
|
|
203
|
+
}
|
|
204
|
+
|
|
205
|
+
return chars;
|
|
206
|
+
}
|
|
207
|
+
|
|
208
|
+
int rc_format_typed_value(char* buffer, size_t size, const rc_typed_value_t* value, int format) {
|
|
209
|
+
int chars;
|
|
210
|
+
rc_typed_value_t converted_value;
|
|
211
|
+
|
|
212
|
+
memcpy(&converted_value, value, sizeof(converted_value));
|
|
213
|
+
|
|
214
|
+
switch (format) {
|
|
215
|
+
default:
|
|
216
|
+
case RC_FORMAT_VALUE:
|
|
217
|
+
rc_typed_value_convert(&converted_value, RC_VALUE_TYPE_SIGNED);
|
|
218
|
+
chars = snprintf(buffer, size, "%d", converted_value.value.i32);
|
|
219
|
+
break;
|
|
220
|
+
|
|
221
|
+
case RC_FORMAT_FRAMES:
|
|
222
|
+
/* 60 frames per second = 100 centiseconds / 60 frames; multiply frames by 100 / 60 */
|
|
223
|
+
rc_typed_value_convert(&converted_value, RC_VALUE_TYPE_UNSIGNED);
|
|
224
|
+
chars = rc_format_value_centiseconds(buffer, size, converted_value.value.u32 * 10 / 6);
|
|
225
|
+
break;
|
|
226
|
+
|
|
227
|
+
case RC_FORMAT_CENTISECS:
|
|
228
|
+
rc_typed_value_convert(&converted_value, RC_VALUE_TYPE_UNSIGNED);
|
|
229
|
+
chars = rc_format_value_centiseconds(buffer, size, converted_value.value.u32);
|
|
230
|
+
break;
|
|
231
|
+
|
|
232
|
+
case RC_FORMAT_SECONDS:
|
|
233
|
+
rc_typed_value_convert(&converted_value, RC_VALUE_TYPE_UNSIGNED);
|
|
234
|
+
chars = rc_format_value_seconds(buffer, size, converted_value.value.u32);
|
|
235
|
+
break;
|
|
236
|
+
|
|
237
|
+
case RC_FORMAT_SECONDS_AS_MINUTES:
|
|
238
|
+
rc_typed_value_convert(&converted_value, RC_VALUE_TYPE_UNSIGNED);
|
|
239
|
+
chars = rc_format_value_minutes(buffer, size, converted_value.value.u32 / 60);
|
|
240
|
+
break;
|
|
241
|
+
|
|
242
|
+
case RC_FORMAT_MINUTES:
|
|
243
|
+
rc_typed_value_convert(&converted_value, RC_VALUE_TYPE_UNSIGNED);
|
|
244
|
+
chars = rc_format_value_minutes(buffer, size, converted_value.value.u32);
|
|
245
|
+
break;
|
|
246
|
+
|
|
247
|
+
case RC_FORMAT_SCORE:
|
|
248
|
+
rc_typed_value_convert(&converted_value, RC_VALUE_TYPE_SIGNED);
|
|
249
|
+
return snprintf(buffer, size, "%06d", converted_value.value.i32);
|
|
250
|
+
|
|
251
|
+
case RC_FORMAT_FLOAT1:
|
|
252
|
+
rc_typed_value_convert(&converted_value, RC_VALUE_TYPE_FLOAT);
|
|
253
|
+
chars = snprintf(buffer, size, "%.1f", converted_value.value.f32);
|
|
254
|
+
break;
|
|
255
|
+
|
|
256
|
+
case RC_FORMAT_FLOAT2:
|
|
257
|
+
rc_typed_value_convert(&converted_value, RC_VALUE_TYPE_FLOAT);
|
|
258
|
+
chars = snprintf(buffer, size, "%.2f", converted_value.value.f32);
|
|
259
|
+
break;
|
|
260
|
+
|
|
261
|
+
case RC_FORMAT_FLOAT3:
|
|
262
|
+
rc_typed_value_convert(&converted_value, RC_VALUE_TYPE_FLOAT);
|
|
263
|
+
chars = snprintf(buffer, size, "%.3f", converted_value.value.f32);
|
|
264
|
+
break;
|
|
265
|
+
|
|
266
|
+
case RC_FORMAT_FLOAT4:
|
|
267
|
+
rc_typed_value_convert(&converted_value, RC_VALUE_TYPE_FLOAT);
|
|
268
|
+
chars = snprintf(buffer, size, "%.4f", converted_value.value.f32);
|
|
269
|
+
break;
|
|
270
|
+
|
|
271
|
+
case RC_FORMAT_FLOAT5:
|
|
272
|
+
rc_typed_value_convert(&converted_value, RC_VALUE_TYPE_FLOAT);
|
|
273
|
+
chars = snprintf(buffer, size, "%.5f", converted_value.value.f32);
|
|
274
|
+
break;
|
|
275
|
+
|
|
276
|
+
case RC_FORMAT_FLOAT6:
|
|
277
|
+
rc_typed_value_convert(&converted_value, RC_VALUE_TYPE_FLOAT);
|
|
278
|
+
chars = snprintf(buffer, size, "%.6f", converted_value.value.f32);
|
|
279
|
+
break;
|
|
280
|
+
|
|
281
|
+
case RC_FORMAT_FIXED1:
|
|
282
|
+
rc_typed_value_convert(&converted_value, RC_VALUE_TYPE_SIGNED);
|
|
283
|
+
chars = rc_format_value_fixed(buffer, size, "%d.%u", converted_value.value.i32, 10);
|
|
284
|
+
break;
|
|
285
|
+
|
|
286
|
+
case RC_FORMAT_FIXED2:
|
|
287
|
+
rc_typed_value_convert(&converted_value, RC_VALUE_TYPE_SIGNED);
|
|
288
|
+
chars = rc_format_value_fixed(buffer, size, "%d.%02u", converted_value.value.i32, 100);
|
|
289
|
+
break;
|
|
290
|
+
|
|
291
|
+
case RC_FORMAT_FIXED3:
|
|
292
|
+
rc_typed_value_convert(&converted_value, RC_VALUE_TYPE_SIGNED);
|
|
293
|
+
chars = rc_format_value_fixed(buffer, size, "%d.%03u", converted_value.value.i32, 1000);
|
|
294
|
+
break;
|
|
295
|
+
|
|
296
|
+
case RC_FORMAT_TENS:
|
|
297
|
+
rc_typed_value_convert(&converted_value, RC_VALUE_TYPE_SIGNED);
|
|
298
|
+
chars = rc_format_value_padded(buffer, size, "%d0", converted_value.value.i32);
|
|
299
|
+
break;
|
|
300
|
+
|
|
301
|
+
case RC_FORMAT_HUNDREDS:
|
|
302
|
+
rc_typed_value_convert(&converted_value, RC_VALUE_TYPE_SIGNED);
|
|
303
|
+
chars = rc_format_value_padded(buffer, size, "%d00", converted_value.value.i32);
|
|
304
|
+
break;
|
|
305
|
+
|
|
306
|
+
case RC_FORMAT_THOUSANDS:
|
|
307
|
+
rc_typed_value_convert(&converted_value, RC_VALUE_TYPE_SIGNED);
|
|
308
|
+
chars = rc_format_value_padded(buffer, size, "%d000", converted_value.value.i32);
|
|
309
|
+
break;
|
|
310
|
+
|
|
311
|
+
case RC_FORMAT_UNSIGNED_VALUE:
|
|
312
|
+
rc_typed_value_convert(&converted_value, RC_VALUE_TYPE_UNSIGNED);
|
|
313
|
+
chars = snprintf(buffer, size, "%u", converted_value.value.u32);
|
|
314
|
+
break;
|
|
315
|
+
|
|
316
|
+
case RC_FORMAT_UNFORMATTED:
|
|
317
|
+
rc_typed_value_convert(&converted_value, RC_VALUE_TYPE_UNSIGNED);
|
|
318
|
+
return snprintf(buffer, size, "%u", converted_value.value.u32);
|
|
319
|
+
}
|
|
320
|
+
|
|
321
|
+
return rc_format_insert_commas(chars, buffer, size);
|
|
322
|
+
}
|
|
323
|
+
|
|
324
|
+
int rc_format_value(char* buffer, int size, int32_t value, int format) {
|
|
325
|
+
rc_typed_value_t typed_value;
|
|
326
|
+
|
|
327
|
+
typed_value.value.i32 = value;
|
|
328
|
+
typed_value.type = RC_VALUE_TYPE_SIGNED;
|
|
329
|
+
return rc_format_typed_value(buffer, size, &typed_value, format);
|
|
330
|
+
}
|
|
@@ -0,0 +1,287 @@
|
|
|
1
|
+
#include "rc_internal.h"
|
|
2
|
+
|
|
3
|
+
enum {
|
|
4
|
+
RC_LBOARD_START = 1 << 0,
|
|
5
|
+
RC_LBOARD_CANCEL = 1 << 1,
|
|
6
|
+
RC_LBOARD_SUBMIT = 1 << 2,
|
|
7
|
+
RC_LBOARD_VALUE = 1 << 3,
|
|
8
|
+
RC_LBOARD_PROGRESS = 1 << 4,
|
|
9
|
+
RC_LBOARD_COMPLETE = RC_LBOARD_START | RC_LBOARD_CANCEL | RC_LBOARD_SUBMIT | RC_LBOARD_VALUE
|
|
10
|
+
};
|
|
11
|
+
|
|
12
|
+
void rc_parse_lboard_internal(rc_lboard_t* self, const char* memaddr, rc_parse_state_t* parse) {
|
|
13
|
+
int found;
|
|
14
|
+
|
|
15
|
+
self->progress = 0;
|
|
16
|
+
found = 0;
|
|
17
|
+
|
|
18
|
+
for (;;)
|
|
19
|
+
{
|
|
20
|
+
if ((memaddr[0] == 's' || memaddr[0] == 'S') &&
|
|
21
|
+
(memaddr[1] == 't' || memaddr[1] == 'T') &&
|
|
22
|
+
(memaddr[2] == 'a' || memaddr[2] == 'A') && memaddr[3] == ':') {
|
|
23
|
+
if ((found & RC_LBOARD_START) != 0) {
|
|
24
|
+
parse->offset = RC_DUPLICATED_START;
|
|
25
|
+
return;
|
|
26
|
+
}
|
|
27
|
+
|
|
28
|
+
memaddr += 4;
|
|
29
|
+
if (*memaddr && *memaddr != ':') {
|
|
30
|
+
found |= RC_LBOARD_START;
|
|
31
|
+
rc_parse_trigger_internal(&self->start, &memaddr, parse);
|
|
32
|
+
}
|
|
33
|
+
}
|
|
34
|
+
else if ((memaddr[0] == 'c' || memaddr[0] == 'C') &&
|
|
35
|
+
(memaddr[1] == 'a' || memaddr[1] == 'A') &&
|
|
36
|
+
(memaddr[2] == 'n' || memaddr[2] == 'N') && memaddr[3] == ':') {
|
|
37
|
+
if ((found & RC_LBOARD_CANCEL) != 0) {
|
|
38
|
+
parse->offset = RC_DUPLICATED_CANCEL;
|
|
39
|
+
return;
|
|
40
|
+
}
|
|
41
|
+
|
|
42
|
+
memaddr += 4;
|
|
43
|
+
if (*memaddr && *memaddr != ':') {
|
|
44
|
+
found |= RC_LBOARD_CANCEL;
|
|
45
|
+
rc_parse_trigger_internal(&self->cancel, &memaddr, parse);
|
|
46
|
+
}
|
|
47
|
+
}
|
|
48
|
+
else if ((memaddr[0] == 's' || memaddr[0] == 'S') &&
|
|
49
|
+
(memaddr[1] == 'u' || memaddr[1] == 'U') &&
|
|
50
|
+
(memaddr[2] == 'b' || memaddr[2] == 'B') && memaddr[3] == ':') {
|
|
51
|
+
if ((found & RC_LBOARD_SUBMIT) != 0) {
|
|
52
|
+
parse->offset = RC_DUPLICATED_SUBMIT;
|
|
53
|
+
return;
|
|
54
|
+
}
|
|
55
|
+
|
|
56
|
+
memaddr += 4;
|
|
57
|
+
if (*memaddr && *memaddr != ':') {
|
|
58
|
+
found |= RC_LBOARD_SUBMIT;
|
|
59
|
+
rc_parse_trigger_internal(&self->submit, &memaddr, parse);
|
|
60
|
+
}
|
|
61
|
+
}
|
|
62
|
+
else if ((memaddr[0] == 'v' || memaddr[0] == 'V') &&
|
|
63
|
+
(memaddr[1] == 'a' || memaddr[1] == 'A') &&
|
|
64
|
+
(memaddr[2] == 'l' || memaddr[2] == 'L') && memaddr[3] == ':') {
|
|
65
|
+
if ((found & RC_LBOARD_VALUE) != 0) {
|
|
66
|
+
parse->offset = RC_DUPLICATED_VALUE;
|
|
67
|
+
return;
|
|
68
|
+
}
|
|
69
|
+
|
|
70
|
+
memaddr += 4;
|
|
71
|
+
if (*memaddr && *memaddr != ':') {
|
|
72
|
+
found |= RC_LBOARD_VALUE;
|
|
73
|
+
rc_parse_value_internal(&self->value, &memaddr, parse);
|
|
74
|
+
}
|
|
75
|
+
}
|
|
76
|
+
else if ((memaddr[0] == 'p' || memaddr[0] == 'P') &&
|
|
77
|
+
(memaddr[1] == 'r' || memaddr[1] == 'R') &&
|
|
78
|
+
(memaddr[2] == 'o' || memaddr[2] == 'O') && memaddr[3] == ':') {
|
|
79
|
+
if ((found & RC_LBOARD_PROGRESS) != 0) {
|
|
80
|
+
parse->offset = RC_DUPLICATED_PROGRESS;
|
|
81
|
+
return;
|
|
82
|
+
}
|
|
83
|
+
|
|
84
|
+
memaddr += 4;
|
|
85
|
+
if (*memaddr && *memaddr != ':') {
|
|
86
|
+
found |= RC_LBOARD_PROGRESS;
|
|
87
|
+
|
|
88
|
+
self->progress = RC_ALLOC(rc_value_t, parse);
|
|
89
|
+
rc_parse_value_internal(self->progress, &memaddr, parse);
|
|
90
|
+
}
|
|
91
|
+
}
|
|
92
|
+
|
|
93
|
+
/* encountered an error parsing one of the parts */
|
|
94
|
+
if (parse->offset < 0)
|
|
95
|
+
return;
|
|
96
|
+
|
|
97
|
+
/* end of string, or end of quoted string - stop processing */
|
|
98
|
+
if (memaddr[0] == '\0' || memaddr[0] == '\"')
|
|
99
|
+
break;
|
|
100
|
+
|
|
101
|
+
/* expect two colons between fields */
|
|
102
|
+
if (memaddr[0] != ':' || memaddr[1] != ':') {
|
|
103
|
+
parse->offset = RC_INVALID_LBOARD_FIELD;
|
|
104
|
+
return;
|
|
105
|
+
}
|
|
106
|
+
|
|
107
|
+
memaddr += 2;
|
|
108
|
+
}
|
|
109
|
+
|
|
110
|
+
if ((found & RC_LBOARD_COMPLETE) != RC_LBOARD_COMPLETE) {
|
|
111
|
+
if ((found & RC_LBOARD_START) == 0) {
|
|
112
|
+
parse->offset = RC_MISSING_START;
|
|
113
|
+
}
|
|
114
|
+
else if ((found & RC_LBOARD_CANCEL) == 0) {
|
|
115
|
+
parse->offset = RC_MISSING_CANCEL;
|
|
116
|
+
}
|
|
117
|
+
else if ((found & RC_LBOARD_SUBMIT) == 0) {
|
|
118
|
+
parse->offset = RC_MISSING_SUBMIT;
|
|
119
|
+
}
|
|
120
|
+
else if ((found & RC_LBOARD_VALUE) == 0) {
|
|
121
|
+
parse->offset = RC_MISSING_VALUE;
|
|
122
|
+
}
|
|
123
|
+
|
|
124
|
+
return;
|
|
125
|
+
}
|
|
126
|
+
|
|
127
|
+
self->state = RC_LBOARD_STATE_WAITING;
|
|
128
|
+
self->has_memrefs = 0;
|
|
129
|
+
}
|
|
130
|
+
|
|
131
|
+
int rc_lboard_size(const char* memaddr) {
|
|
132
|
+
rc_lboard_with_memrefs_t* lboard;
|
|
133
|
+
rc_preparse_state_t preparse;
|
|
134
|
+
rc_init_preparse_state(&preparse);
|
|
135
|
+
|
|
136
|
+
lboard = RC_ALLOC(rc_lboard_with_memrefs_t, &preparse.parse);
|
|
137
|
+
rc_parse_lboard_internal(&lboard->lboard, memaddr, &preparse.parse);
|
|
138
|
+
rc_preparse_alloc_memrefs(NULL, &preparse);
|
|
139
|
+
|
|
140
|
+
rc_destroy_preparse_state(&preparse);
|
|
141
|
+
return preparse.parse.offset;
|
|
142
|
+
}
|
|
143
|
+
|
|
144
|
+
rc_lboard_t* rc_parse_lboard(void* buffer, const char* memaddr, void* unused_L, int unused_funcs_idx) {
|
|
145
|
+
rc_lboard_with_memrefs_t* lboard;
|
|
146
|
+
rc_preparse_state_t preparse;
|
|
147
|
+
|
|
148
|
+
(void)unused_L;
|
|
149
|
+
(void)unused_funcs_idx;
|
|
150
|
+
|
|
151
|
+
if (!buffer || !memaddr)
|
|
152
|
+
return 0;
|
|
153
|
+
|
|
154
|
+
rc_init_preparse_state(&preparse);
|
|
155
|
+
lboard = RC_ALLOC(rc_lboard_with_memrefs_t, &preparse.parse);
|
|
156
|
+
rc_parse_lboard_internal(&lboard->lboard, memaddr, &preparse.parse);
|
|
157
|
+
|
|
158
|
+
rc_reset_parse_state(&preparse.parse, buffer);
|
|
159
|
+
lboard = RC_ALLOC(rc_lboard_with_memrefs_t, &preparse.parse);
|
|
160
|
+
rc_preparse_alloc_memrefs(&lboard->memrefs, &preparse);
|
|
161
|
+
|
|
162
|
+
rc_parse_lboard_internal(&lboard->lboard, memaddr, &preparse.parse);
|
|
163
|
+
lboard->lboard.has_memrefs = 1;
|
|
164
|
+
|
|
165
|
+
rc_destroy_preparse_state(&preparse);
|
|
166
|
+
return (preparse.parse.offset >= 0) ? &lboard->lboard : NULL;
|
|
167
|
+
}
|
|
168
|
+
|
|
169
|
+
static void rc_update_lboard_memrefs(rc_lboard_t* self, rc_peek_t peek, void* ud) {
|
|
170
|
+
if (self->has_memrefs) {
|
|
171
|
+
rc_lboard_with_memrefs_t* lboard = (rc_lboard_with_memrefs_t*)self;
|
|
172
|
+
rc_update_memref_values(&lboard->memrefs, peek, ud);
|
|
173
|
+
}
|
|
174
|
+
}
|
|
175
|
+
|
|
176
|
+
int rc_evaluate_lboard(rc_lboard_t* self, int32_t* value, rc_peek_t peek, void* peek_ud, void* unused_L) {
|
|
177
|
+
int start_ok, cancel_ok, submit_ok;
|
|
178
|
+
|
|
179
|
+
rc_update_lboard_memrefs(self, peek, peek_ud);
|
|
180
|
+
|
|
181
|
+
if (self->state == RC_LBOARD_STATE_INACTIVE || self->state == RC_LBOARD_STATE_DISABLED)
|
|
182
|
+
return RC_LBOARD_STATE_INACTIVE;
|
|
183
|
+
|
|
184
|
+
/* these are always tested once every frame, to ensure hit counts work properly */
|
|
185
|
+
start_ok = rc_test_trigger(&self->start, peek, peek_ud, unused_L);
|
|
186
|
+
cancel_ok = rc_test_trigger(&self->cancel, peek, peek_ud, unused_L);
|
|
187
|
+
submit_ok = rc_test_trigger(&self->submit, peek, peek_ud, unused_L);
|
|
188
|
+
|
|
189
|
+
switch (self->state)
|
|
190
|
+
{
|
|
191
|
+
case RC_LBOARD_STATE_WAITING:
|
|
192
|
+
case RC_LBOARD_STATE_TRIGGERED:
|
|
193
|
+
case RC_LBOARD_STATE_CANCELED:
|
|
194
|
+
/* don't activate/reactivate until the start condition becomes false */
|
|
195
|
+
if (start_ok) {
|
|
196
|
+
*value = 0;
|
|
197
|
+
return RC_LBOARD_STATE_INACTIVE; /* just return inactive for all of these */
|
|
198
|
+
}
|
|
199
|
+
|
|
200
|
+
/* start condition is false, allow the leaderboard to start on future frames */
|
|
201
|
+
self->state = RC_LBOARD_STATE_ACTIVE;
|
|
202
|
+
break;
|
|
203
|
+
|
|
204
|
+
case RC_LBOARD_STATE_ACTIVE:
|
|
205
|
+
/* leaderboard attempt is not in progress. if the start condition is true and the cancel condition is not, start the attempt */
|
|
206
|
+
if (start_ok && !cancel_ok) {
|
|
207
|
+
if (submit_ok) {
|
|
208
|
+
/* start and submit are both true in the same frame, just submit without announcing the leaderboard is available */
|
|
209
|
+
self->state = RC_LBOARD_STATE_TRIGGERED;
|
|
210
|
+
}
|
|
211
|
+
else if (!self->start.requirement && !self->start.alternative) {
|
|
212
|
+
/* start trigger is empty. assume the leaderboard is in development and ignore */
|
|
213
|
+
}
|
|
214
|
+
else {
|
|
215
|
+
/* start the leaderboard attempt */
|
|
216
|
+
self->state = RC_LBOARD_STATE_STARTED;
|
|
217
|
+
}
|
|
218
|
+
|
|
219
|
+
/* reset any hit counts in the value */
|
|
220
|
+
if (self->progress)
|
|
221
|
+
rc_reset_value(self->progress);
|
|
222
|
+
|
|
223
|
+
rc_reset_value(&self->value);
|
|
224
|
+
}
|
|
225
|
+
break;
|
|
226
|
+
|
|
227
|
+
case RC_LBOARD_STATE_STARTED:
|
|
228
|
+
/* leaderboard attempt in progress */
|
|
229
|
+
if (cancel_ok) {
|
|
230
|
+
/* cancel condition is true, abort the attempt */
|
|
231
|
+
self->state = RC_LBOARD_STATE_CANCELED;
|
|
232
|
+
}
|
|
233
|
+
else if (submit_ok) {
|
|
234
|
+
/* submit condition is true, submit the current value */
|
|
235
|
+
self->state = RC_LBOARD_STATE_TRIGGERED;
|
|
236
|
+
}
|
|
237
|
+
break;
|
|
238
|
+
}
|
|
239
|
+
|
|
240
|
+
/* Calculate the value */
|
|
241
|
+
switch (self->state) {
|
|
242
|
+
case RC_LBOARD_STATE_STARTED:
|
|
243
|
+
if (self->progress) {
|
|
244
|
+
*value = rc_evaluate_value(self->progress, peek, peek_ud, unused_L);
|
|
245
|
+
break;
|
|
246
|
+
}
|
|
247
|
+
/* fallthrough */ /* to RC_LBOARD_STATE_TRIGGERED */
|
|
248
|
+
|
|
249
|
+
case RC_LBOARD_STATE_TRIGGERED:
|
|
250
|
+
*value = rc_evaluate_value(&self->value, peek, peek_ud, unused_L);
|
|
251
|
+
break;
|
|
252
|
+
|
|
253
|
+
default:
|
|
254
|
+
*value = 0;
|
|
255
|
+
break;
|
|
256
|
+
}
|
|
257
|
+
|
|
258
|
+
return self->state;
|
|
259
|
+
}
|
|
260
|
+
|
|
261
|
+
int rc_lboard_state_active(int state) {
|
|
262
|
+
switch (state)
|
|
263
|
+
{
|
|
264
|
+
case RC_LBOARD_STATE_DISABLED:
|
|
265
|
+
case RC_LBOARD_STATE_INACTIVE:
|
|
266
|
+
return 0;
|
|
267
|
+
|
|
268
|
+
default:
|
|
269
|
+
return 1;
|
|
270
|
+
}
|
|
271
|
+
}
|
|
272
|
+
|
|
273
|
+
void rc_reset_lboard(rc_lboard_t* self) {
|
|
274
|
+
if (!self)
|
|
275
|
+
return;
|
|
276
|
+
|
|
277
|
+
self->state = RC_LBOARD_STATE_WAITING;
|
|
278
|
+
|
|
279
|
+
rc_reset_trigger(&self->start);
|
|
280
|
+
rc_reset_trigger(&self->submit);
|
|
281
|
+
rc_reset_trigger(&self->cancel);
|
|
282
|
+
|
|
283
|
+
if (self->progress)
|
|
284
|
+
rc_reset_value(self->progress);
|
|
285
|
+
|
|
286
|
+
rc_reset_value(&self->value);
|
|
287
|
+
}
|