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,98 @@
|
|
|
1
|
+
#ifndef RC_LIBRETRO_H
|
|
2
|
+
#define RC_LIBRETRO_H
|
|
3
|
+
|
|
4
|
+
#include "rc_export.h"
|
|
5
|
+
|
|
6
|
+
#include "rc_hash.h"
|
|
7
|
+
|
|
8
|
+
/* this file comes from the libretro repository, which is not an explicit submodule.
|
|
9
|
+
* the integration must set up paths appropriately to find it. */
|
|
10
|
+
#include <libretro.h>
|
|
11
|
+
|
|
12
|
+
#include <stddef.h>
|
|
13
|
+
#include <stdint.h>
|
|
14
|
+
|
|
15
|
+
RC_BEGIN_C_DECLS
|
|
16
|
+
|
|
17
|
+
/*****************************************************************************\
|
|
18
|
+
| Disallowed Settings |
|
|
19
|
+
\*****************************************************************************/
|
|
20
|
+
|
|
21
|
+
typedef struct rc_disallowed_setting_t
|
|
22
|
+
{
|
|
23
|
+
const char* setting;
|
|
24
|
+
const char* value;
|
|
25
|
+
} rc_disallowed_setting_t;
|
|
26
|
+
|
|
27
|
+
RC_EXPORT const rc_disallowed_setting_t* RC_CCONV rc_libretro_get_disallowed_settings(const char* library_name);
|
|
28
|
+
RC_EXPORT int RC_CCONV rc_libretro_is_setting_allowed(const rc_disallowed_setting_t* disallowed_settings, const char* setting, const char* value);
|
|
29
|
+
RC_EXPORT int RC_CCONV rc_libretro_is_system_allowed(const char* library_name, uint32_t console_id);
|
|
30
|
+
|
|
31
|
+
/*****************************************************************************\
|
|
32
|
+
| Memory Mapping |
|
|
33
|
+
\*****************************************************************************/
|
|
34
|
+
|
|
35
|
+
/* specifies a function to call for verbose logging */
|
|
36
|
+
typedef void (RC_CCONV *rc_libretro_message_callback)(const char*);
|
|
37
|
+
RC_EXPORT void RC_CCONV rc_libretro_init_verbose_message_callback(rc_libretro_message_callback callback);
|
|
38
|
+
|
|
39
|
+
#define RC_LIBRETRO_MAX_MEMORY_REGIONS 32
|
|
40
|
+
typedef struct rc_libretro_memory_regions_t
|
|
41
|
+
{
|
|
42
|
+
uint8_t* data[RC_LIBRETRO_MAX_MEMORY_REGIONS];
|
|
43
|
+
size_t size[RC_LIBRETRO_MAX_MEMORY_REGIONS];
|
|
44
|
+
size_t total_size;
|
|
45
|
+
uint32_t count;
|
|
46
|
+
} rc_libretro_memory_regions_t;
|
|
47
|
+
|
|
48
|
+
typedef struct rc_libretro_core_memory_info_t
|
|
49
|
+
{
|
|
50
|
+
uint8_t* data;
|
|
51
|
+
size_t size;
|
|
52
|
+
} rc_libretro_core_memory_info_t;
|
|
53
|
+
|
|
54
|
+
typedef void (RC_CCONV *rc_libretro_get_core_memory_info_func)(uint32_t id, rc_libretro_core_memory_info_t* info);
|
|
55
|
+
|
|
56
|
+
RC_EXPORT int RC_CCONV rc_libretro_memory_init(rc_libretro_memory_regions_t* regions, const struct retro_memory_map* mmap,
|
|
57
|
+
rc_libretro_get_core_memory_info_func get_core_memory_info, uint32_t console_id);
|
|
58
|
+
RC_EXPORT void RC_CCONV rc_libretro_memory_destroy(rc_libretro_memory_regions_t* regions);
|
|
59
|
+
|
|
60
|
+
RC_EXPORT uint8_t* RC_CCONV rc_libretro_memory_find(const rc_libretro_memory_regions_t* regions, uint32_t address);
|
|
61
|
+
RC_EXPORT uint8_t* RC_CCONV rc_libretro_memory_find_avail(const rc_libretro_memory_regions_t* regions, uint32_t address, uint32_t* avail);
|
|
62
|
+
RC_EXPORT uint32_t RC_CCONV rc_libretro_memory_read(const rc_libretro_memory_regions_t* regions, uint32_t address, uint8_t* buffer, uint32_t num_bytes);
|
|
63
|
+
|
|
64
|
+
/*****************************************************************************\
|
|
65
|
+
| Disk Identification |
|
|
66
|
+
\*****************************************************************************/
|
|
67
|
+
|
|
68
|
+
typedef struct rc_libretro_hash_entry_t
|
|
69
|
+
{
|
|
70
|
+
uint32_t path_djb2;
|
|
71
|
+
uint32_t game_id;
|
|
72
|
+
char hash[33];
|
|
73
|
+
} rc_libretro_hash_entry_t;
|
|
74
|
+
|
|
75
|
+
typedef struct rc_libretro_hash_set_t
|
|
76
|
+
{
|
|
77
|
+
struct rc_libretro_hash_entry_t* entries;
|
|
78
|
+
uint16_t entries_count;
|
|
79
|
+
uint16_t entries_size;
|
|
80
|
+
|
|
81
|
+
rc_hash_callbacks_t callbacks;
|
|
82
|
+
} rc_libretro_hash_set_t;
|
|
83
|
+
|
|
84
|
+
typedef int (RC_CCONV *rc_libretro_get_image_path_func)(uint32_t index, char* buffer, size_t buffer_size);
|
|
85
|
+
|
|
86
|
+
RC_EXPORT void RC_CCONV rc_libretro_hash_set_init(struct rc_libretro_hash_set_t* hash_set,
|
|
87
|
+
const char* m3u_path, rc_libretro_get_image_path_func get_image_path,
|
|
88
|
+
const rc_hash_filereader_t* file_reader);
|
|
89
|
+
RC_EXPORT void RC_CCONV rc_libretro_hash_set_destroy(struct rc_libretro_hash_set_t* hash_set);
|
|
90
|
+
|
|
91
|
+
RC_EXPORT void RC_CCONV rc_libretro_hash_set_add(struct rc_libretro_hash_set_t* hash_set,
|
|
92
|
+
const char* path, uint32_t game_id, const char hash[33]);
|
|
93
|
+
RC_EXPORT const char* RC_CCONV rc_libretro_hash_set_get_hash(const struct rc_libretro_hash_set_t* hash_set, const char* path);
|
|
94
|
+
RC_EXPORT int RC_CCONV rc_libretro_hash_set_get_game_id(const struct rc_libretro_hash_set_t* hash_set, const char* hash);
|
|
95
|
+
|
|
96
|
+
RC_END_C_DECLS
|
|
97
|
+
|
|
98
|
+
#endif /* RC_LIBRETRO_H */
|
|
@@ -0,0 +1,199 @@
|
|
|
1
|
+
#include "rc_util.h"
|
|
2
|
+
|
|
3
|
+
#include "rc_compat.h"
|
|
4
|
+
#include "rc_error.h"
|
|
5
|
+
|
|
6
|
+
#include <stdlib.h>
|
|
7
|
+
#include <string.h>
|
|
8
|
+
|
|
9
|
+
#undef DEBUG_BUFFERS
|
|
10
|
+
|
|
11
|
+
/* --- rc_buffer --- */
|
|
12
|
+
|
|
13
|
+
void rc_buffer_init(rc_buffer_t* buffer)
|
|
14
|
+
{
|
|
15
|
+
buffer->chunk.write = buffer->chunk.start = &buffer->data[0];
|
|
16
|
+
buffer->chunk.end = &buffer->data[sizeof(buffer->data)];
|
|
17
|
+
buffer->chunk.next = NULL;
|
|
18
|
+
/* leave buffer->data uninitialized */
|
|
19
|
+
}
|
|
20
|
+
|
|
21
|
+
void rc_buffer_destroy(rc_buffer_t* buffer)
|
|
22
|
+
{
|
|
23
|
+
rc_buffer_chunk_t* chunk;
|
|
24
|
+
#ifdef DEBUG_BUFFERS
|
|
25
|
+
int count = 0;
|
|
26
|
+
int wasted = 0;
|
|
27
|
+
int total = 0;
|
|
28
|
+
#endif
|
|
29
|
+
|
|
30
|
+
/* first chunk is not allocated. skip it. */
|
|
31
|
+
chunk = buffer->chunk.next;
|
|
32
|
+
|
|
33
|
+
/* deallocate any additional buffers */
|
|
34
|
+
while (chunk)
|
|
35
|
+
{
|
|
36
|
+
rc_buffer_chunk_t* next = chunk->next;
|
|
37
|
+
#ifdef DEBUG_BUFFERS
|
|
38
|
+
total += (int)(chunk->end - chunk->start);
|
|
39
|
+
wasted += (int)(chunk->end - chunk->write);
|
|
40
|
+
++count;
|
|
41
|
+
#endif
|
|
42
|
+
#ifdef DEBUG_BUFFERS
|
|
43
|
+
printf("< free %p.%p\n", (void*)buffer, (void*)chunk);
|
|
44
|
+
#endif
|
|
45
|
+
free(chunk);
|
|
46
|
+
chunk = next;
|
|
47
|
+
}
|
|
48
|
+
|
|
49
|
+
#ifdef DEBUG_BUFFERS
|
|
50
|
+
printf("-- %d allocated buffers (%d/%d used, %d wasted, %0.2f%% efficiency)\n", count,
|
|
51
|
+
total - wasted, total, wasted, (float)(100.0 - (wasted * 100.0) / total));
|
|
52
|
+
#endif
|
|
53
|
+
}
|
|
54
|
+
|
|
55
|
+
uint8_t* rc_buffer_reserve(rc_buffer_t* buffer, size_t amount)
|
|
56
|
+
{
|
|
57
|
+
rc_buffer_chunk_t* chunk = &buffer->chunk;
|
|
58
|
+
size_t remaining;
|
|
59
|
+
while (chunk)
|
|
60
|
+
{
|
|
61
|
+
remaining = chunk->end - chunk->write;
|
|
62
|
+
if (remaining >= amount)
|
|
63
|
+
return chunk->write;
|
|
64
|
+
|
|
65
|
+
if (!chunk->next)
|
|
66
|
+
{
|
|
67
|
+
/* allocate a chunk of memory that is a multiple of 256-bytes. the first 32 bytes will be associated
|
|
68
|
+
* to the chunk header, and the remaining will be used for data.
|
|
69
|
+
*/
|
|
70
|
+
const size_t chunk_header_size = sizeof(rc_buffer_chunk_t);
|
|
71
|
+
const size_t alloc_size = (chunk_header_size + amount + 0xFF) & ~0xFF;
|
|
72
|
+
chunk->next = (rc_buffer_chunk_t*)malloc(alloc_size);
|
|
73
|
+
if (!chunk->next)
|
|
74
|
+
break;
|
|
75
|
+
|
|
76
|
+
#ifdef DEBUG_BUFFERS
|
|
77
|
+
printf("> alloc %p.%p\n", (void*)buffer, (void*)chunk->next);
|
|
78
|
+
#endif
|
|
79
|
+
|
|
80
|
+
chunk->next->start = (uint8_t*)chunk->next + chunk_header_size;
|
|
81
|
+
chunk->next->write = chunk->next->start;
|
|
82
|
+
chunk->next->end = (uint8_t*)chunk->next + alloc_size;
|
|
83
|
+
chunk->next->next = NULL;
|
|
84
|
+
}
|
|
85
|
+
|
|
86
|
+
chunk = chunk->next;
|
|
87
|
+
}
|
|
88
|
+
|
|
89
|
+
return NULL;
|
|
90
|
+
}
|
|
91
|
+
|
|
92
|
+
void rc_buffer_consume(rc_buffer_t* buffer, const uint8_t* start, uint8_t* end)
|
|
93
|
+
{
|
|
94
|
+
rc_buffer_chunk_t* chunk = &buffer->chunk;
|
|
95
|
+
do
|
|
96
|
+
{
|
|
97
|
+
if (chunk->write == start)
|
|
98
|
+
{
|
|
99
|
+
size_t offset = (end - chunk->start);
|
|
100
|
+
offset = (offset + 7) & ~7;
|
|
101
|
+
chunk->write = &chunk->start[offset];
|
|
102
|
+
|
|
103
|
+
if (chunk->write > chunk->end)
|
|
104
|
+
chunk->write = chunk->end;
|
|
105
|
+
break;
|
|
106
|
+
}
|
|
107
|
+
|
|
108
|
+
chunk = chunk->next;
|
|
109
|
+
} while (chunk);
|
|
110
|
+
}
|
|
111
|
+
|
|
112
|
+
void* rc_buffer_alloc(rc_buffer_t* buffer, size_t amount)
|
|
113
|
+
{
|
|
114
|
+
uint8_t* ptr = rc_buffer_reserve(buffer, amount);
|
|
115
|
+
rc_buffer_consume(buffer, ptr, ptr + amount);
|
|
116
|
+
return (void*)ptr;
|
|
117
|
+
}
|
|
118
|
+
|
|
119
|
+
char* rc_buffer_strncpy(rc_buffer_t* buffer, const char* src, size_t len)
|
|
120
|
+
{
|
|
121
|
+
uint8_t* dst = rc_buffer_reserve(buffer, len + 1);
|
|
122
|
+
memcpy(dst, src, len);
|
|
123
|
+
dst[len] = '\0';
|
|
124
|
+
rc_buffer_consume(buffer, dst, dst + len + 2);
|
|
125
|
+
return (char*)dst;
|
|
126
|
+
}
|
|
127
|
+
|
|
128
|
+
char* rc_buffer_strcpy(rc_buffer_t* buffer, const char* src)
|
|
129
|
+
{
|
|
130
|
+
return rc_buffer_strncpy(buffer, src, strlen(src));
|
|
131
|
+
}
|
|
132
|
+
|
|
133
|
+
/* --- other --- */
|
|
134
|
+
|
|
135
|
+
void rc_format_md5(char checksum[33], const uint8_t digest[16])
|
|
136
|
+
{
|
|
137
|
+
snprintf(checksum, 33, "%02x%02x%02x%02x%02x%02x%02x%02x%02x%02x%02x%02x%02x%02x%02x%02x",
|
|
138
|
+
digest[0], digest[1], digest[2], digest[3], digest[4], digest[5], digest[6], digest[7],
|
|
139
|
+
digest[8], digest[9], digest[10], digest[11], digest[12], digest[13], digest[14], digest[15]
|
|
140
|
+
);
|
|
141
|
+
}
|
|
142
|
+
|
|
143
|
+
uint32_t rc_djb2(const char* input)
|
|
144
|
+
{
|
|
145
|
+
uint32_t result = 5381;
|
|
146
|
+
char c;
|
|
147
|
+
|
|
148
|
+
while ((c = *input++) != '\0')
|
|
149
|
+
result = ((result << 5) + result) + c; /* result = result * 33 + c */
|
|
150
|
+
|
|
151
|
+
return result;
|
|
152
|
+
}
|
|
153
|
+
|
|
154
|
+
const char* rc_error_str(int ret)
|
|
155
|
+
{
|
|
156
|
+
switch (ret) {
|
|
157
|
+
case RC_OK: return "OK";
|
|
158
|
+
case RC_INVALID_FUNC_OPERAND: return "Invalid function operand";
|
|
159
|
+
case RC_INVALID_MEMORY_OPERAND: return "Invalid memory operand";
|
|
160
|
+
case RC_INVALID_CONST_OPERAND: return "Invalid constant operand";
|
|
161
|
+
case RC_INVALID_FP_OPERAND: return "Invalid floating-point operand";
|
|
162
|
+
case RC_INVALID_CONDITION_TYPE: return "Invalid condition type";
|
|
163
|
+
case RC_INVALID_OPERATOR: return "Invalid operator";
|
|
164
|
+
case RC_INVALID_REQUIRED_HITS: return "Invalid required hits";
|
|
165
|
+
case RC_DUPLICATED_START: return "Duplicated start condition";
|
|
166
|
+
case RC_DUPLICATED_CANCEL: return "Duplicated cancel condition";
|
|
167
|
+
case RC_DUPLICATED_SUBMIT: return "Duplicated submit condition";
|
|
168
|
+
case RC_DUPLICATED_VALUE: return "Duplicated value expression";
|
|
169
|
+
case RC_DUPLICATED_PROGRESS: return "Duplicated progress expression";
|
|
170
|
+
case RC_MISSING_START: return "Missing start condition";
|
|
171
|
+
case RC_MISSING_CANCEL: return "Missing cancel condition";
|
|
172
|
+
case RC_MISSING_SUBMIT: return "Missing submit condition";
|
|
173
|
+
case RC_MISSING_VALUE: return "Missing value expression";
|
|
174
|
+
case RC_INVALID_LBOARD_FIELD: return "Invalid field in leaderboard";
|
|
175
|
+
case RC_MISSING_DISPLAY_STRING: return "Missing display string";
|
|
176
|
+
case RC_OUT_OF_MEMORY: return "Out of memory";
|
|
177
|
+
case RC_INVALID_VALUE_FLAG: return "Invalid flag in value expression";
|
|
178
|
+
case RC_MISSING_VALUE_MEASURED: return "Missing measured flag in value expression";
|
|
179
|
+
case RC_MULTIPLE_MEASURED: return "Multiple measured targets";
|
|
180
|
+
case RC_INVALID_MEASURED_TARGET: return "Invalid measured target";
|
|
181
|
+
case RC_INVALID_COMPARISON: return "Invalid comparison";
|
|
182
|
+
case RC_INVALID_STATE: return "Invalid state";
|
|
183
|
+
case RC_INVALID_JSON: return "Invalid JSON";
|
|
184
|
+
case RC_API_FAILURE: return "API call failed";
|
|
185
|
+
case RC_LOGIN_REQUIRED: return "Login required";
|
|
186
|
+
case RC_NO_GAME_LOADED: return "No game loaded";
|
|
187
|
+
case RC_HARDCORE_DISABLED: return "Hardcore disabled";
|
|
188
|
+
case RC_ABORTED: return "Aborted";
|
|
189
|
+
case RC_NO_RESPONSE: return "No response";
|
|
190
|
+
case RC_ACCESS_DENIED: return "Access denied";
|
|
191
|
+
case RC_INVALID_CREDENTIALS: return "Invalid credentials";
|
|
192
|
+
case RC_EXPIRED_TOKEN: return "Expired token";
|
|
193
|
+
case RC_INSUFFICIENT_BUFFER: return "Buffer not large enough";
|
|
194
|
+
case RC_INVALID_VARIABLE_NAME: return "Invalid variable name";
|
|
195
|
+
case RC_UNKNOWN_VARIABLE_NAME: return "Unknown variable name";
|
|
196
|
+
case RC_NOT_FOUND: return "Not found";
|
|
197
|
+
default: return "Unknown error";
|
|
198
|
+
}
|
|
199
|
+
}
|
|
@@ -0,0 +1,32 @@
|
|
|
1
|
+
#ifndef RC_VERSION_H
|
|
2
|
+
#define RC_VERSION_H
|
|
3
|
+
|
|
4
|
+
#include "rc_export.h"
|
|
5
|
+
|
|
6
|
+
#include <stdint.h>
|
|
7
|
+
|
|
8
|
+
RC_BEGIN_C_DECLS
|
|
9
|
+
|
|
10
|
+
#define RCHEEVOS_VERSION_MAJOR 12
|
|
11
|
+
#define RCHEEVOS_VERSION_MINOR 3
|
|
12
|
+
#define RCHEEVOS_VERSION_PATCH 0
|
|
13
|
+
|
|
14
|
+
#define RCHEEVOS_MAKE_VERSION(major, minor, patch) (major * 1000000 + minor * 1000 + patch)
|
|
15
|
+
#define RCHEEVOS_VERSION RCHEEVOS_MAKE_VERSION(RCHEEVOS_VERSION_MAJOR, RCHEEVOS_VERSION_MINOR, RCHEEVOS_VERSION_PATCH)
|
|
16
|
+
|
|
17
|
+
#define RCHEEVOS_MAKE_STRING(num) #num
|
|
18
|
+
#define RCHEEVOS_MAKE_VERSION_STRING(major, minor, patch) RCHEEVOS_MAKE_STRING(major) "." RCHEEVOS_MAKE_STRING(minor) "." RCHEEVOS_MAKE_STRING(patch)
|
|
19
|
+
#define RCHEEVOS_MAKE_VERSION_STRING_SHORT(major, minor) RCHEEVOS_MAKE_STRING(major) "." RCHEEVOS_MAKE_STRING(minor)
|
|
20
|
+
|
|
21
|
+
#if RCHEEVOS_VERSION_PATCH > 0
|
|
22
|
+
#define RCHEEVOS_VERSION_STRING RCHEEVOS_MAKE_VERSION_STRING(RCHEEVOS_VERSION_MAJOR, RCHEEVOS_VERSION_MINOR, RCHEEVOS_VERSION_PATCH)
|
|
23
|
+
#else
|
|
24
|
+
#define RCHEEVOS_VERSION_STRING RCHEEVOS_MAKE_VERSION_STRING_SHORT(RCHEEVOS_VERSION_MAJOR, RCHEEVOS_VERSION_MINOR)
|
|
25
|
+
#endif
|
|
26
|
+
|
|
27
|
+
RC_EXPORT uint32_t rc_version(void);
|
|
28
|
+
RC_EXPORT const char* rc_version_string(void);
|
|
29
|
+
|
|
30
|
+
RC_END_C_DECLS
|
|
31
|
+
|
|
32
|
+
#endif /* RC_VERSION_H */
|
|
@@ -0,0 +1,312 @@
|
|
|
1
|
+
#include "rc_internal.h"
|
|
2
|
+
|
|
3
|
+
#include <stdlib.h>
|
|
4
|
+
#include <string.h>
|
|
5
|
+
|
|
6
|
+
void* rc_alloc_scratch(void* pointer, int32_t* offset, uint32_t size, uint32_t alignment, rc_scratch_t* scratch, uint32_t scratch_object_pointer_offset)
|
|
7
|
+
{
|
|
8
|
+
void* data;
|
|
9
|
+
|
|
10
|
+
/* if we have a real buffer, then allocate the data there */
|
|
11
|
+
if (pointer)
|
|
12
|
+
return rc_alloc(pointer, offset, size, alignment, NULL, scratch_object_pointer_offset);
|
|
13
|
+
|
|
14
|
+
/* update how much space will be required in the real buffer */
|
|
15
|
+
{
|
|
16
|
+
const int32_t aligned_offset = (*offset + alignment - 1) & ~(alignment - 1);
|
|
17
|
+
*offset += (aligned_offset - *offset);
|
|
18
|
+
*offset += size;
|
|
19
|
+
}
|
|
20
|
+
|
|
21
|
+
/* find a scratch buffer to hold the temporary data */
|
|
22
|
+
data = rc_buffer_alloc(&scratch->buffer, size);
|
|
23
|
+
if (!data) {
|
|
24
|
+
*offset = RC_OUT_OF_MEMORY;
|
|
25
|
+
return NULL;
|
|
26
|
+
}
|
|
27
|
+
|
|
28
|
+
return data;
|
|
29
|
+
}
|
|
30
|
+
|
|
31
|
+
void* rc_alloc(void* pointer, int32_t* offset, uint32_t size, uint32_t alignment, rc_scratch_t* scratch, uint32_t scratch_object_pointer_offset) {
|
|
32
|
+
void* ptr;
|
|
33
|
+
|
|
34
|
+
*offset = (*offset + alignment - 1) & ~(alignment - 1);
|
|
35
|
+
|
|
36
|
+
if (pointer != 0) {
|
|
37
|
+
/* valid buffer, grab the next chunk */
|
|
38
|
+
ptr = (void*)((uint8_t*)pointer + *offset);
|
|
39
|
+
}
|
|
40
|
+
else if (scratch != 0 && scratch_object_pointer_offset < sizeof(scratch->objs)) {
|
|
41
|
+
/* only allocate one instance of each object type (indentified by scratch_object_pointer_offset) */
|
|
42
|
+
void** scratch_object_pointer = (void**)((uint8_t*)&scratch->objs + scratch_object_pointer_offset);
|
|
43
|
+
ptr = *scratch_object_pointer;
|
|
44
|
+
if (!ptr) {
|
|
45
|
+
int32_t used;
|
|
46
|
+
ptr = *scratch_object_pointer = rc_alloc_scratch(NULL, &used, size, alignment, scratch, -1);
|
|
47
|
+
}
|
|
48
|
+
}
|
|
49
|
+
else {
|
|
50
|
+
/* nowhere to get memory from, return NULL */
|
|
51
|
+
ptr = NULL;
|
|
52
|
+
}
|
|
53
|
+
|
|
54
|
+
*offset += size;
|
|
55
|
+
return ptr;
|
|
56
|
+
}
|
|
57
|
+
|
|
58
|
+
char* rc_alloc_str(rc_parse_state_t* parse, const char* text, size_t length) {
|
|
59
|
+
int32_t used = 0;
|
|
60
|
+
char* ptr;
|
|
61
|
+
|
|
62
|
+
rc_scratch_string_t** next = &parse->scratch.strings;
|
|
63
|
+
while (*next) {
|
|
64
|
+
int diff = strncmp(text, (*next)->value, length);
|
|
65
|
+
if (diff == 0) {
|
|
66
|
+
diff = (*next)->value[length];
|
|
67
|
+
if (diff == 0)
|
|
68
|
+
return (*next)->value;
|
|
69
|
+
}
|
|
70
|
+
|
|
71
|
+
if (diff < 0)
|
|
72
|
+
next = &(*next)->left;
|
|
73
|
+
else
|
|
74
|
+
next = &(*next)->right;
|
|
75
|
+
}
|
|
76
|
+
|
|
77
|
+
*next = (rc_scratch_string_t*)rc_alloc_scratch(NULL, &used, sizeof(rc_scratch_string_t), RC_ALIGNOF(rc_scratch_string_t), &parse->scratch, RC_OFFSETOF(parse->scratch.objs, __rc_scratch_string_t));
|
|
78
|
+
ptr = (char*)rc_alloc_scratch(parse->buffer, &parse->offset, (uint32_t)length + 1, RC_ALIGNOF(char), &parse->scratch, -1);
|
|
79
|
+
|
|
80
|
+
if (!ptr || !*next) {
|
|
81
|
+
if (parse->offset >= 0)
|
|
82
|
+
parse->offset = RC_OUT_OF_MEMORY;
|
|
83
|
+
|
|
84
|
+
return NULL;
|
|
85
|
+
}
|
|
86
|
+
|
|
87
|
+
memcpy(ptr, text, length);
|
|
88
|
+
ptr[length] = '\0';
|
|
89
|
+
|
|
90
|
+
(*next)->left = NULL;
|
|
91
|
+
(*next)->right = NULL;
|
|
92
|
+
(*next)->value = ptr;
|
|
93
|
+
|
|
94
|
+
return ptr;
|
|
95
|
+
}
|
|
96
|
+
|
|
97
|
+
void rc_init_preparse_state(rc_preparse_state_t* preparse)
|
|
98
|
+
{
|
|
99
|
+
rc_init_parse_state(&preparse->parse, NULL);
|
|
100
|
+
rc_init_parse_state_memrefs(&preparse->parse, &preparse->memrefs);
|
|
101
|
+
}
|
|
102
|
+
|
|
103
|
+
void rc_destroy_preparse_state(rc_preparse_state_t* preparse)
|
|
104
|
+
{
|
|
105
|
+
rc_destroy_parse_state(&preparse->parse);
|
|
106
|
+
}
|
|
107
|
+
|
|
108
|
+
void rc_preparse_alloc_memrefs(rc_memrefs_t* memrefs, rc_preparse_state_t* preparse)
|
|
109
|
+
{
|
|
110
|
+
const uint32_t num_memrefs = rc_memrefs_count_memrefs(&preparse->memrefs);
|
|
111
|
+
const uint32_t num_modified_memrefs = rc_memrefs_count_modified_memrefs(&preparse->memrefs);
|
|
112
|
+
|
|
113
|
+
if (preparse->parse.offset < 0)
|
|
114
|
+
return;
|
|
115
|
+
|
|
116
|
+
if (memrefs) {
|
|
117
|
+
memset(memrefs, 0, sizeof(*memrefs));
|
|
118
|
+
preparse->parse.memrefs = memrefs;
|
|
119
|
+
}
|
|
120
|
+
|
|
121
|
+
if (num_memrefs) {
|
|
122
|
+
rc_memref_t* memref_items = RC_ALLOC_ARRAY(rc_memref_t, num_memrefs, &preparse->parse);
|
|
123
|
+
|
|
124
|
+
if (memrefs) {
|
|
125
|
+
memrefs->memrefs.capacity = num_memrefs;
|
|
126
|
+
memrefs->memrefs.items = memref_items;
|
|
127
|
+
}
|
|
128
|
+
}
|
|
129
|
+
|
|
130
|
+
if (num_modified_memrefs) {
|
|
131
|
+
rc_modified_memref_t* modified_memref_items =
|
|
132
|
+
RC_ALLOC_ARRAY(rc_modified_memref_t, num_modified_memrefs, &preparse->parse);
|
|
133
|
+
|
|
134
|
+
if (memrefs) {
|
|
135
|
+
memrefs->modified_memrefs.capacity = num_modified_memrefs;
|
|
136
|
+
memrefs->modified_memrefs.items = modified_memref_items;
|
|
137
|
+
}
|
|
138
|
+
}
|
|
139
|
+
|
|
140
|
+
/* when preparsing, this structure will be allocated at the end. when it's allocated earlier
|
|
141
|
+
* in the buffer, it could be followed by something aligned at 8 bytes. force the offset to
|
|
142
|
+
* an 8-byte boundary */
|
|
143
|
+
if (!memrefs) {
|
|
144
|
+
rc_alloc(preparse->parse.buffer, &preparse->parse.offset, 0, 8, &preparse->parse.scratch, 0);
|
|
145
|
+
}
|
|
146
|
+
}
|
|
147
|
+
|
|
148
|
+
static uint32_t rc_preparse_array_size(uint32_t needed, uint32_t minimum)
|
|
149
|
+
{
|
|
150
|
+
while (minimum < needed)
|
|
151
|
+
minimum <<= 1;
|
|
152
|
+
|
|
153
|
+
return minimum;
|
|
154
|
+
}
|
|
155
|
+
|
|
156
|
+
void rc_preparse_reserve_memrefs(rc_preparse_state_t* preparse, rc_memrefs_t* memrefs)
|
|
157
|
+
{
|
|
158
|
+
uint32_t num_memrefs = rc_memrefs_count_memrefs(&preparse->memrefs);
|
|
159
|
+
uint32_t num_modified_memrefs = rc_memrefs_count_modified_memrefs(&preparse->memrefs);
|
|
160
|
+
uint32_t available;
|
|
161
|
+
|
|
162
|
+
if (preparse->parse.offset < 0)
|
|
163
|
+
return;
|
|
164
|
+
|
|
165
|
+
if (num_memrefs) {
|
|
166
|
+
rc_memref_list_t* memref_list = &memrefs->memrefs;
|
|
167
|
+
while (memref_list->count == memref_list->capacity) {
|
|
168
|
+
if (!memref_list->next)
|
|
169
|
+
break;
|
|
170
|
+
|
|
171
|
+
memref_list = memref_list->next;
|
|
172
|
+
}
|
|
173
|
+
|
|
174
|
+
available = memref_list->capacity - memref_list->count;
|
|
175
|
+
if (available < num_memrefs) {
|
|
176
|
+
rc_memref_list_t* new_memref_list = (rc_memref_list_t*)calloc(1, sizeof(rc_memref_list_t));
|
|
177
|
+
if (!new_memref_list)
|
|
178
|
+
return;
|
|
179
|
+
|
|
180
|
+
new_memref_list->capacity = rc_preparse_array_size(num_memrefs - available, 16);
|
|
181
|
+
new_memref_list->items = (rc_memref_t*)malloc(new_memref_list->capacity * sizeof(rc_memref_t));
|
|
182
|
+
new_memref_list->allocated = 1;
|
|
183
|
+
memref_list->next = new_memref_list;
|
|
184
|
+
}
|
|
185
|
+
}
|
|
186
|
+
|
|
187
|
+
if (num_modified_memrefs) {
|
|
188
|
+
rc_modified_memref_list_t* modified_memref_list = &memrefs->modified_memrefs;
|
|
189
|
+
while (modified_memref_list->count == modified_memref_list->capacity) {
|
|
190
|
+
if (!modified_memref_list->next)
|
|
191
|
+
break;
|
|
192
|
+
|
|
193
|
+
modified_memref_list = modified_memref_list->next;
|
|
194
|
+
}
|
|
195
|
+
|
|
196
|
+
available = modified_memref_list->capacity - modified_memref_list->count;
|
|
197
|
+
if (available < num_modified_memrefs) {
|
|
198
|
+
rc_modified_memref_list_t* new_modified_memref_list = (rc_modified_memref_list_t*)calloc(1, sizeof(rc_modified_memref_list_t));
|
|
199
|
+
if (!new_modified_memref_list)
|
|
200
|
+
return;
|
|
201
|
+
|
|
202
|
+
new_modified_memref_list->capacity = rc_preparse_array_size(num_modified_memrefs - available, 8);
|
|
203
|
+
new_modified_memref_list->items = (rc_modified_memref_t*)malloc(new_modified_memref_list->capacity * sizeof(rc_modified_memref_t));
|
|
204
|
+
new_modified_memref_list->allocated = 1;
|
|
205
|
+
modified_memref_list->next = new_modified_memref_list;
|
|
206
|
+
}
|
|
207
|
+
}
|
|
208
|
+
|
|
209
|
+
preparse->parse.memrefs = memrefs;
|
|
210
|
+
}
|
|
211
|
+
|
|
212
|
+
static void rc_preparse_sync_operand(rc_operand_t* operand, rc_parse_state_t* parse, const rc_memrefs_t* memrefs)
|
|
213
|
+
{
|
|
214
|
+
if (rc_operand_is_memref(operand) || rc_operand_is_recall(operand)) {
|
|
215
|
+
const rc_memref_t* src_memref = operand->value.memref;
|
|
216
|
+
|
|
217
|
+
if (src_memref->value.memref_type == RC_MEMREF_TYPE_MODIFIED_MEMREF) {
|
|
218
|
+
const rc_modified_memref_list_t* modified_memref_list = &memrefs->modified_memrefs;
|
|
219
|
+
for (; modified_memref_list; modified_memref_list = modified_memref_list->next) {
|
|
220
|
+
const rc_modified_memref_t* modified_memref = modified_memref_list->items;
|
|
221
|
+
const rc_modified_memref_t* modified_memref_end = modified_memref + modified_memref_list->count;
|
|
222
|
+
|
|
223
|
+
for (; modified_memref < modified_memref_end; ++modified_memref) {
|
|
224
|
+
if ((const rc_modified_memref_t*)src_memref == modified_memref) {
|
|
225
|
+
rc_modified_memref_t* dst_modified_memref = rc_alloc_modified_memref(parse, modified_memref->memref.value.size,
|
|
226
|
+
&modified_memref->parent, modified_memref->modifier_type, &modified_memref->modifier);
|
|
227
|
+
|
|
228
|
+
operand->value.memref = &dst_modified_memref->memref;
|
|
229
|
+
return;
|
|
230
|
+
}
|
|
231
|
+
}
|
|
232
|
+
}
|
|
233
|
+
}
|
|
234
|
+
else {
|
|
235
|
+
const rc_memref_list_t* memref_list = &memrefs->memrefs;
|
|
236
|
+
for (; memref_list; memref_list = memref_list->next) {
|
|
237
|
+
const rc_memref_t* memref = memref_list->items;
|
|
238
|
+
const rc_memref_t* memref_end = memref + memref_list->count;
|
|
239
|
+
|
|
240
|
+
for (; memref < memref_end; ++memref) {
|
|
241
|
+
if (src_memref == memref) {
|
|
242
|
+
operand->value.memref = rc_alloc_memref(parse, memref->address, memref->value.size);
|
|
243
|
+
return;
|
|
244
|
+
}
|
|
245
|
+
}
|
|
246
|
+
}
|
|
247
|
+
}
|
|
248
|
+
}
|
|
249
|
+
}
|
|
250
|
+
|
|
251
|
+
void rc_preparse_copy_memrefs(rc_parse_state_t* parse, rc_memrefs_t* memrefs)
|
|
252
|
+
{
|
|
253
|
+
const rc_memref_list_t* memref_list = &memrefs->memrefs;
|
|
254
|
+
const rc_modified_memref_list_t* modified_memref_list = &memrefs->modified_memrefs;
|
|
255
|
+
|
|
256
|
+
for (; memref_list; memref_list = memref_list->next) {
|
|
257
|
+
const rc_memref_t* memref = memref_list->items;
|
|
258
|
+
const rc_memref_t* memref_end = memref + memref_list->count;
|
|
259
|
+
|
|
260
|
+
for (; memref < memref_end; ++memref)
|
|
261
|
+
rc_alloc_memref(parse, memref->address, memref->value.size);
|
|
262
|
+
}
|
|
263
|
+
|
|
264
|
+
for (; modified_memref_list; modified_memref_list = modified_memref_list->next) {
|
|
265
|
+
rc_modified_memref_t* modified_memref = modified_memref_list->items;
|
|
266
|
+
const rc_modified_memref_t* modified_memref_end = modified_memref + modified_memref_list->count;
|
|
267
|
+
|
|
268
|
+
for (; modified_memref < modified_memref_end; ++modified_memref) {
|
|
269
|
+
rc_preparse_sync_operand(&modified_memref->parent, parse, memrefs);
|
|
270
|
+
rc_preparse_sync_operand(&modified_memref->modifier, parse, memrefs);
|
|
271
|
+
|
|
272
|
+
rc_alloc_modified_memref(parse, modified_memref->memref.value.size,
|
|
273
|
+
&modified_memref->parent, modified_memref->modifier_type, &modified_memref->modifier);
|
|
274
|
+
}
|
|
275
|
+
}
|
|
276
|
+
}
|
|
277
|
+
|
|
278
|
+
void rc_reset_parse_state(rc_parse_state_t* parse, void* buffer)
|
|
279
|
+
{
|
|
280
|
+
parse->buffer = buffer;
|
|
281
|
+
|
|
282
|
+
parse->offset = 0;
|
|
283
|
+
parse->memrefs = NULL;
|
|
284
|
+
parse->existing_memrefs = NULL;
|
|
285
|
+
parse->variables = NULL;
|
|
286
|
+
parse->measured_target = 0;
|
|
287
|
+
parse->lines_read = 0;
|
|
288
|
+
parse->addsource_oper = RC_OPERATOR_NONE;
|
|
289
|
+
parse->addsource_parent.type = RC_OPERAND_NONE;
|
|
290
|
+
parse->indirect_parent.type = RC_OPERAND_NONE;
|
|
291
|
+
parse->remember.type = RC_OPERAND_NONE;
|
|
292
|
+
parse->is_value = 0;
|
|
293
|
+
parse->has_required_hits = 0;
|
|
294
|
+
parse->measured_as_percent = 0;
|
|
295
|
+
parse->ignore_non_parse_errors = 0;
|
|
296
|
+
|
|
297
|
+
parse->scratch.strings = NULL;
|
|
298
|
+
}
|
|
299
|
+
|
|
300
|
+
void rc_init_parse_state(rc_parse_state_t* parse, void* buffer)
|
|
301
|
+
{
|
|
302
|
+
/* could use memset here, but rc_parse_state_t contains a 512 byte buffer that doesn't need to be initialized */
|
|
303
|
+
rc_buffer_init(&parse->scratch.buffer);
|
|
304
|
+
memset(&parse->scratch.objs, 0, sizeof(parse->scratch.objs));
|
|
305
|
+
|
|
306
|
+
rc_reset_parse_state(parse, buffer);
|
|
307
|
+
}
|
|
308
|
+
|
|
309
|
+
void rc_destroy_parse_state(rc_parse_state_t* parse)
|
|
310
|
+
{
|
|
311
|
+
rc_buffer_destroy(&parse->scratch.buffer);
|
|
312
|
+
}
|