gemba 0.1.1 → 0.2.1
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 +190 -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 +511 -0
- data/lib/gemba/achievements/retro_achievements/cli_sync_requester.rb +64 -0
- data/lib/gemba/achievements/retro_achievements/ping_worker.rb +28 -0
- data/lib/gemba/achievements/retro_achievements/unlock_retry_worker.rb +35 -0
- data/lib/gemba/achievements.rb +19 -0
- data/lib/gemba/achievements_window.rb +556 -0
- data/lib/gemba/app_controller.rb +1036 -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 +154 -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 +1084 -0
- data/lib/gemba/event_bus.rb +48 -0
- data/lib/gemba/frame_stack.rb +70 -0
- data/lib/gemba/game_index.rb +84 -0
- data/lib/gemba/game_picker_frame.rb +309 -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/list_picker_frame.rb +271 -0
- data/lib/gemba/locales/en.yml +109 -5
- data/lib/gemba/locales/ja.yml +109 -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 +119 -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 +377 -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 +92 -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 +78 -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 +3 -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_list_picker_frame.rb +391 -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_ra_backend_unlock_retry.rb +123 -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 +383 -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 +221 -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 +277 -10
- data/lib/gemba/input_mappings.rb +0 -214
- data/lib/gemba/player.rb +0 -1525
data/lib/gemba/locales/en.yml
CHANGED
|
@@ -5,8 +5,12 @@ menu:
|
|
|
5
5
|
quit: "Quit"
|
|
6
6
|
settings: "Settings"
|
|
7
7
|
view: "View"
|
|
8
|
+
game_library: "Game Library"
|
|
8
9
|
fullscreen: "Fullscreen"
|
|
9
10
|
rom_info: "ROM Info…"
|
|
11
|
+
achievements: "Achievements…"
|
|
12
|
+
open_logs_dir: "Open Logs Directory"
|
|
13
|
+
patch_rom: "Patch ROM…"
|
|
10
14
|
emulation: "Emulation"
|
|
11
15
|
pause: "Pause"
|
|
12
16
|
resume: "Resume"
|
|
@@ -14,8 +18,10 @@ menu:
|
|
|
14
18
|
quick_save: "Quick Save"
|
|
15
19
|
quick_load: "Quick Load"
|
|
16
20
|
save_states: "Save States…"
|
|
17
|
-
start_recording: "Start
|
|
18
|
-
stop_recording: "Stop
|
|
21
|
+
start_recording: "Start Capture"
|
|
22
|
+
stop_recording: "Stop Capture"
|
|
23
|
+
start_input_recording: "Start Recording Inputs"
|
|
24
|
+
stop_input_recording: "Stop Recording Inputs"
|
|
19
25
|
|
|
20
26
|
toast:
|
|
21
27
|
save_blocked: "Save blocked (too fast)"
|
|
@@ -32,12 +38,18 @@ toast:
|
|
|
32
38
|
no_rewind: "No rewind data"
|
|
33
39
|
paused: "Paused"
|
|
34
40
|
waiting_for: "Waiting for {label}…"
|
|
35
|
-
recording_started: "
|
|
36
|
-
recording_stopped: "
|
|
41
|
+
recording_started: "Capture started"
|
|
42
|
+
recording_stopped: "Captured {frames} frames"
|
|
43
|
+
input_recording_started: "Recording inputs"
|
|
44
|
+
input_recording_stopped: "Inputs recorded ({frames} frames)"
|
|
37
45
|
|
|
38
46
|
dialog:
|
|
39
47
|
game_running_title: "Game Running"
|
|
40
48
|
game_running_msg: "Another game is running. Switch to {name}?"
|
|
49
|
+
return_to_library_title: "Return to Game Library"
|
|
50
|
+
return_to_library_msg: "Return to the Game Library? Unsaved progress will be lost."
|
|
51
|
+
quit_title: "Quit Gemba"
|
|
52
|
+
quit_msg: "A game is running. Quit anyway? Unsaved progress will be lost."
|
|
41
53
|
drop_error_title: "Drop Error"
|
|
42
54
|
drop_single_file_only: "Please drop a single ROM file."
|
|
43
55
|
drop_unsupported_type: "Unsupported file type: {ext}"
|
|
@@ -51,6 +63,8 @@ dialog:
|
|
|
51
63
|
reset_hotkeys_title: "Reset Hotkeys"
|
|
52
64
|
reset_hotkeys_msg: "Reset all hotkey bindings to defaults?"
|
|
53
65
|
key_conflict_title: "Key Conflict"
|
|
66
|
+
cancel_bulk_sync_title: "Cancel Sync?"
|
|
67
|
+
cancel_bulk_sync_msg: "A bulk sync is in progress. Closing will cancel it — games will need to be re-synced manually."
|
|
54
68
|
|
|
55
69
|
settings:
|
|
56
70
|
video: "Video"
|
|
@@ -91,7 +105,9 @@ settings:
|
|
|
91
105
|
hk_save_states: "Save States"
|
|
92
106
|
hk_screenshot: "Screenshot"
|
|
93
107
|
hk_rewind: "Rewind"
|
|
94
|
-
hk_record: "
|
|
108
|
+
hk_record: "Capture"
|
|
109
|
+
hk_input_record: "Record Inputs"
|
|
110
|
+
hk_open_rom: "Open ROM"
|
|
95
111
|
hk_reset_defaults: "Reset to Defaults"
|
|
96
112
|
pixel_filter: "Pixel Filter:"
|
|
97
113
|
filter_nearest: "Nearest Neighbor"
|
|
@@ -111,11 +127,40 @@ settings:
|
|
|
111
127
|
tip_per_game: "Save separate video, audio, and save state settings for each ROM."
|
|
112
128
|
tip_turbo_speed: "Fast-forward speed when holding the turbo hotkey."
|
|
113
129
|
tip_toast_duration: "How long on-screen notifications stay visible."
|
|
130
|
+
system: "System"
|
|
131
|
+
bios_header: "GBA BIOS"
|
|
132
|
+
bios_path: "BIOS file:"
|
|
133
|
+
bios_browse: "Browse…"
|
|
134
|
+
bios_clear: "Clear"
|
|
135
|
+
bios_not_set: "Not set — using built-in HLE (recommended for most games)"
|
|
136
|
+
bios_not_found: "File not found"
|
|
137
|
+
skip_bios: "Skip boot animation"
|
|
138
|
+
tip_skip_bios: "Jump straight to the game, skipping the Game Boy Advance logo screen.\nOnly applies when a real BIOS file is loaded."
|
|
139
|
+
retroachievements: "Achievements"
|
|
140
|
+
ra_enabled: "Enable RetroAchievements"
|
|
141
|
+
ra_credentials: "Account"
|
|
142
|
+
ra_username_placeholder: "Username:"
|
|
143
|
+
ra_token_placeholder: "Password:"
|
|
144
|
+
ra_rich_presence: "Rich Presence (per-game)"
|
|
145
|
+
ra_screenshot_on_unlock: "Screenshot on achievement unlock (per-game)"
|
|
146
|
+
ra_hardcore: "Hardcore mode (disables save states and rewind)"
|
|
147
|
+
tip_ra_password: "Your password is only used to fetch an API token and is never saved."
|
|
148
|
+
ra_login: "Login"
|
|
149
|
+
ra_verify: "Verify Token"
|
|
150
|
+
ra_logout: "Logout"
|
|
151
|
+
ra_reset: "Reset"
|
|
152
|
+
ra_reset_title: "Reset RetroAchievements"
|
|
153
|
+
ra_reset_confirm: "Clear saved credentials and log out?"
|
|
154
|
+
ra_test_ok: "Connection OK ✓"
|
|
155
|
+
ra_disabled: "RetroAchievements is disabled"
|
|
156
|
+
ra_not_logged_in: "Not logged in"
|
|
157
|
+
ra_logged_in_as: "Logged in as {username}"
|
|
114
158
|
recording: "Recording"
|
|
115
159
|
recording_compression: "Compression:"
|
|
116
160
|
tip_recording_compression: "Zlib level for .grec files.\n1 = fastest (default), 6+ has diminishing returns."
|
|
117
161
|
recordings_folder: "Recordings folder:"
|
|
118
162
|
open_recordings_folder: "Open Recordings Folder…"
|
|
163
|
+
open_replay_player: "Open Input Replay…"
|
|
119
164
|
gp_a: "A"
|
|
120
165
|
gp_b: "B"
|
|
121
166
|
gp_l: "L"
|
|
@@ -134,6 +179,24 @@ picker:
|
|
|
134
179
|
slot: "Slot {n}"
|
|
135
180
|
close: "Close"
|
|
136
181
|
|
|
182
|
+
game_picker:
|
|
183
|
+
menu:
|
|
184
|
+
play: "Play"
|
|
185
|
+
quick_load: "Quick Load"
|
|
186
|
+
set_boxart: "Set Boxart"
|
|
187
|
+
remove: "Remove from Library"
|
|
188
|
+
|
|
189
|
+
picker:
|
|
190
|
+
toolbar:
|
|
191
|
+
boxart_view: "Box art view"
|
|
192
|
+
list_view: "List view"
|
|
193
|
+
|
|
194
|
+
list_picker:
|
|
195
|
+
columns:
|
|
196
|
+
title: "Title"
|
|
197
|
+
last_played: "Last Played"
|
|
198
|
+
never_played: "Never"
|
|
199
|
+
|
|
137
200
|
rom_info:
|
|
138
201
|
title: "ROM Info"
|
|
139
202
|
field_title: "Title:"
|
|
@@ -148,6 +211,29 @@ rom_info:
|
|
|
148
211
|
close: "Close"
|
|
149
212
|
na: "N/A"
|
|
150
213
|
|
|
214
|
+
replay:
|
|
215
|
+
open_recording: "Open Input Recording…"
|
|
216
|
+
replay_player: "Input Replay"
|
|
217
|
+
ended: "Replay complete ({frames} frames)"
|
|
218
|
+
empty_hint: "Open Input Recording (Cmd+O)"
|
|
219
|
+
|
|
220
|
+
patcher:
|
|
221
|
+
title: "Patch ROM"
|
|
222
|
+
rom_label: "ROM file:"
|
|
223
|
+
patch_label: "Patch file:"
|
|
224
|
+
outdir_label: "Output dir:"
|
|
225
|
+
browse: "Browse…"
|
|
226
|
+
apply: "Apply Patch"
|
|
227
|
+
working: "Applying patch…"
|
|
228
|
+
done: "Done →"
|
|
229
|
+
err_missing_fields: "Please fill in all fields."
|
|
230
|
+
err_rom_not_found: "ROM file not found."
|
|
231
|
+
err_patch_not_found: "Patch file not found."
|
|
232
|
+
err_failed: "Patch failed:"
|
|
233
|
+
overwrite_title: "File Exists"
|
|
234
|
+
overwrite_msg: "{path} already exists. Overwrite it?"
|
|
235
|
+
thread_mode_warn: "Note: Progress may appear stuck on Ruby < 4"
|
|
236
|
+
|
|
151
237
|
player:
|
|
152
238
|
open_rom_hint: "File > Open ROM…"
|
|
153
239
|
fps: "{fps} fps"
|
|
@@ -155,3 +241,21 @@ player:
|
|
|
155
241
|
ff_max: ">> MAX"
|
|
156
242
|
none: "(none)"
|
|
157
243
|
clear: "Clear"
|
|
244
|
+
|
|
245
|
+
achievements:
|
|
246
|
+
title: "Achievements"
|
|
247
|
+
game_label: "Game:"
|
|
248
|
+
sync: "Sync"
|
|
249
|
+
name_col: "Achievement"
|
|
250
|
+
points_col: "Points"
|
|
251
|
+
earned_col: "Earned"
|
|
252
|
+
none: "No achievements loaded"
|
|
253
|
+
earned_label: "{earned} / {total} earned"
|
|
254
|
+
sync_pending: "Syncing…"
|
|
255
|
+
sync_failed: "Sync failed"
|
|
256
|
+
sync_no_game: "No game loaded"
|
|
257
|
+
sync_timeout: "Sync timed out"
|
|
258
|
+
not_logged_in: "Not logged in"
|
|
259
|
+
include_unofficial: "Include Unofficial"
|
|
260
|
+
bulk_syncing: "Syncing {title} ({n}/{total})…"
|
|
261
|
+
bulk_sync_done: "Synced {count} games"
|
data/lib/gemba/locales/ja.yml
CHANGED
|
@@ -5,8 +5,12 @@ menu:
|
|
|
5
5
|
quit: "終了"
|
|
6
6
|
settings: "設定"
|
|
7
7
|
view: "表示"
|
|
8
|
+
game_library: "ゲームライブラリ"
|
|
8
9
|
fullscreen: "フルスクリーン"
|
|
9
10
|
rom_info: "ROM情報…"
|
|
11
|
+
achievements: "アチーブメント…"
|
|
12
|
+
open_logs_dir: "ログフォルダを開く"
|
|
13
|
+
patch_rom: "ROMをパッチ…"
|
|
10
14
|
emulation: "エミュレーション"
|
|
11
15
|
pause: "一時停止"
|
|
12
16
|
resume: "再開"
|
|
@@ -14,8 +18,10 @@ menu:
|
|
|
14
18
|
quick_save: "クイックセーブ"
|
|
15
19
|
quick_load: "クイックロード"
|
|
16
20
|
save_states: "ステートセーブ…"
|
|
17
|
-
start_recording: "
|
|
18
|
-
stop_recording: "
|
|
21
|
+
start_recording: "キャプチャ開始"
|
|
22
|
+
stop_recording: "キャプチャ停止"
|
|
23
|
+
start_input_recording: "入力記録開始"
|
|
24
|
+
stop_input_recording: "入力記録停止"
|
|
19
25
|
|
|
20
26
|
toast:
|
|
21
27
|
save_blocked: "セーブ制限中(間隔が短すぎます)"
|
|
@@ -32,12 +38,18 @@ toast:
|
|
|
32
38
|
no_rewind: "巻き戻しデータがありません"
|
|
33
39
|
paused: "一時停止"
|
|
34
40
|
waiting_for: "{label}を待機中…"
|
|
35
|
-
recording_started: "
|
|
36
|
-
recording_stopped: "{frames}
|
|
41
|
+
recording_started: "キャプチャを開始しました"
|
|
42
|
+
recording_stopped: "{frames}フレームをキャプチャしました"
|
|
43
|
+
input_recording_started: "入力記録を開始しました"
|
|
44
|
+
input_recording_stopped: "入力を記録しました({frames}フレーム)"
|
|
37
45
|
|
|
38
46
|
dialog:
|
|
39
47
|
game_running_title: "ゲーム実行中"
|
|
40
48
|
game_running_msg: "別のゲームが実行中です。{name}に切り替えますか?"
|
|
49
|
+
return_to_library_title: "ゲームライブラリに戻る"
|
|
50
|
+
return_to_library_msg: "ゲームライブラリに戻りますか?保存されていない進行状況は失われます。"
|
|
51
|
+
quit_title: "Gembaを終了"
|
|
52
|
+
quit_msg: "ゲームが実行中です。終了しますか?保存されていない進行状況は失われます。"
|
|
41
53
|
drop_error_title: "ドロップエラー"
|
|
42
54
|
drop_single_file_only: "ROMファイルを1つだけドロップしてください。"
|
|
43
55
|
drop_unsupported_type: "対応していないファイル形式: {ext}"
|
|
@@ -51,6 +63,8 @@ dialog:
|
|
|
51
63
|
reset_hotkeys_title: "ホットキーをリセット"
|
|
52
64
|
reset_hotkeys_msg: "すべてのホットキー設定をデフォルトに戻しますか?"
|
|
53
65
|
key_conflict_title: "キーの競合"
|
|
66
|
+
cancel_bulk_sync_title: "同期をキャンセル?"
|
|
67
|
+
cancel_bulk_sync_msg: "一括同期が実行中です。閉じるとキャンセルされます — 手動で再同期が必要になります。"
|
|
54
68
|
|
|
55
69
|
settings:
|
|
56
70
|
video: "映像"
|
|
@@ -91,7 +105,9 @@ settings:
|
|
|
91
105
|
hk_save_states: "ステートセーブ"
|
|
92
106
|
hk_screenshot: "スクリーンショット"
|
|
93
107
|
hk_rewind: "巻き戻し"
|
|
94
|
-
hk_record: "
|
|
108
|
+
hk_record: "キャプチャ"
|
|
109
|
+
hk_input_record: "入力記録"
|
|
110
|
+
hk_open_rom: "ROM を開く"
|
|
95
111
|
hk_reset_defaults: "デフォルトに戻す"
|
|
96
112
|
pixel_filter: "ピクセルフィルタ:"
|
|
97
113
|
filter_nearest: "ニアレストネイバー"
|
|
@@ -111,11 +127,40 @@ settings:
|
|
|
111
127
|
tip_per_game: "ROM毎に映像・音声・ステートセーブの設定を個別に保存します。"
|
|
112
128
|
tip_turbo_speed: "早送りホットキー使用時の速度。"
|
|
113
129
|
tip_toast_duration: "画面上の通知の表示時間。"
|
|
130
|
+
system: "システム"
|
|
131
|
+
bios_header: "GBA BIOS"
|
|
132
|
+
bios_path: "BIOSファイル:"
|
|
133
|
+
bios_browse: "参照…"
|
|
134
|
+
bios_clear: "クリア"
|
|
135
|
+
bios_not_set: "未設定 — 内蔵HLEを使用(ほとんどのゲームに推奨)"
|
|
136
|
+
bios_not_found: "ファイルが見つかりません"
|
|
137
|
+
skip_bios: "起動アニメーションをスキップ"
|
|
138
|
+
tip_skip_bios: "ゲームボーイアドバンスのロゴ画面をスキップして\n直接ゲームを開始します。実BIOSが必要です。"
|
|
139
|
+
retroachievements: "実績"
|
|
140
|
+
ra_enabled: "RetroAchievementsを有効にする"
|
|
141
|
+
ra_credentials: "アカウント"
|
|
142
|
+
ra_username_placeholder: "ユーザー名:"
|
|
143
|
+
ra_token_placeholder: "パスワード:"
|
|
144
|
+
ra_rich_presence: "リッチプレゼンス(ゲームごと)"
|
|
145
|
+
ra_screenshot_on_unlock: "実績解除時にスクリーンショット(ゲームごと)"
|
|
146
|
+
ra_hardcore: "ハードコアモード(セーブステートと巻き戻し無効)"
|
|
147
|
+
tip_ra_password: "パスワードはAPIトークン取得のみに使用され、保存されません。"
|
|
148
|
+
ra_login: "ログイン"
|
|
149
|
+
ra_verify: "トークン確認"
|
|
150
|
+
ra_logout: "ログアウト"
|
|
151
|
+
ra_reset: "リセット"
|
|
152
|
+
ra_reset_title: "RetroAchievementsをリセット"
|
|
153
|
+
ra_reset_confirm: "保存済みの認証情報を削除してログアウトしますか?"
|
|
154
|
+
ra_test_ok: "接続OK ✓"
|
|
155
|
+
ra_disabled: "RetroAchievementsは無効です"
|
|
156
|
+
ra_not_logged_in: "未ログイン"
|
|
157
|
+
ra_logged_in_as: "{username}でログイン中"
|
|
114
158
|
recording: "録画"
|
|
115
159
|
recording_compression: "圧縮レベル:"
|
|
116
160
|
tip_recording_compression: ".grecファイルのzlib圧縮レベル。\n1 = 最速(デフォルト)、6以上は効果が小さくなります。"
|
|
117
161
|
recordings_folder: "録画フォルダ:"
|
|
118
162
|
open_recordings_folder: "録画フォルダを開く…"
|
|
163
|
+
open_replay_player: "入力リプレイを開く…"
|
|
119
164
|
gp_a: "A"
|
|
120
165
|
gp_b: "B"
|
|
121
166
|
gp_l: "L"
|
|
@@ -134,6 +179,24 @@ picker:
|
|
|
134
179
|
slot: "スロット{n}"
|
|
135
180
|
close: "閉じる"
|
|
136
181
|
|
|
182
|
+
game_picker:
|
|
183
|
+
menu:
|
|
184
|
+
play: "プレイ"
|
|
185
|
+
quick_load: "クイックロード"
|
|
186
|
+
set_boxart: "カスタム画像を設定"
|
|
187
|
+
remove: "ライブラリから削除"
|
|
188
|
+
|
|
189
|
+
picker:
|
|
190
|
+
toolbar:
|
|
191
|
+
boxart_view: "ボックスアート表示"
|
|
192
|
+
list_view: "リスト表示"
|
|
193
|
+
|
|
194
|
+
list_picker:
|
|
195
|
+
columns:
|
|
196
|
+
title: "タイトル"
|
|
197
|
+
last_played: "最終プレイ日"
|
|
198
|
+
never_played: "未プレイ"
|
|
199
|
+
|
|
137
200
|
rom_info:
|
|
138
201
|
title: "ROM情報"
|
|
139
202
|
field_title: "タイトル:"
|
|
@@ -148,6 +211,29 @@ rom_info:
|
|
|
148
211
|
close: "閉じる"
|
|
149
212
|
na: "N/A"
|
|
150
213
|
|
|
214
|
+
replay:
|
|
215
|
+
open_recording: "入力記録を開く…"
|
|
216
|
+
replay_player: "入力リプレイ"
|
|
217
|
+
ended: "リプレイ完了({frames}フレーム)"
|
|
218
|
+
empty_hint: "入力記録を開く (Cmd+O)"
|
|
219
|
+
|
|
220
|
+
patcher:
|
|
221
|
+
title: "ROMをパッチ"
|
|
222
|
+
rom_label: "ROMファイル:"
|
|
223
|
+
patch_label: "パッチファイル:"
|
|
224
|
+
outdir_label: "出力フォルダ:"
|
|
225
|
+
browse: "参照…"
|
|
226
|
+
apply: "パッチを適用"
|
|
227
|
+
working: "パッチ適用中…"
|
|
228
|
+
done: "完了 →"
|
|
229
|
+
err_missing_fields: "すべての項目を入力してください。"
|
|
230
|
+
err_rom_not_found: "ROMファイルが見つかりません。"
|
|
231
|
+
err_patch_not_found: "パッチファイルが見つかりません。"
|
|
232
|
+
err_failed: "パッチ失敗:"
|
|
233
|
+
overwrite_title: "ファイルが存在します"
|
|
234
|
+
overwrite_msg: "{path} は既に存在します。上書きしますか?"
|
|
235
|
+
thread_mode_warn: "注意: Ruby < 4 ではプログレスが止まって見える場合があります"
|
|
236
|
+
|
|
151
237
|
player:
|
|
152
238
|
open_rom_hint: "ファイル > ROMを開く…"
|
|
153
239
|
fps: "{fps} fps"
|
|
@@ -155,3 +241,21 @@ player:
|
|
|
155
241
|
ff_max: ">> 最大"
|
|
156
242
|
none: "(なし)"
|
|
157
243
|
clear: "クリア"
|
|
244
|
+
|
|
245
|
+
achievements:
|
|
246
|
+
title: "アチーブメント"
|
|
247
|
+
game_label: "ゲーム:"
|
|
248
|
+
sync: "同期"
|
|
249
|
+
name_col: "アチーブメント"
|
|
250
|
+
points_col: "ポイント"
|
|
251
|
+
earned_col: "取得日時"
|
|
252
|
+
none: "アチーブメントなし"
|
|
253
|
+
earned_label: "{earned} / {total} 取得"
|
|
254
|
+
sync_pending: "同期中…"
|
|
255
|
+
sync_failed: "同期に失敗しました"
|
|
256
|
+
sync_no_game: "ゲームが読み込まれていません"
|
|
257
|
+
sync_timeout: "同期がタイムアウトしました"
|
|
258
|
+
not_logged_in: "ログインしていません"
|
|
259
|
+
include_unofficial: "非公式を含む"
|
|
260
|
+
bulk_syncing: "{title} を同期中 ({n}/{total})…"
|
|
261
|
+
bulk_sync_done: "{count} ゲームを同期しました"
|
|
@@ -0,0 +1,56 @@
|
|
|
1
|
+
# frozen_string_literal: true
|
|
2
|
+
|
|
3
|
+
|
|
4
|
+
module Gemba
|
|
5
|
+
# Pure Tk shell — creates the app window and hosts a FrameStack.
|
|
6
|
+
#
|
|
7
|
+
# MainWindow knows nothing about ROMs, emulation, menus, or config.
|
|
8
|
+
# It provides geometry/title/fullscreen primitives that the AppController
|
|
9
|
+
# drives. Its only structural contribution is the FrameStack, which
|
|
10
|
+
# manages show/hide transitions to prevent visual flash (FOUC).
|
|
11
|
+
class MainWindow
|
|
12
|
+
attr_reader :app, :frame_stack
|
|
13
|
+
|
|
14
|
+
def initialize
|
|
15
|
+
@app = Teek::App.new
|
|
16
|
+
@app.show
|
|
17
|
+
@frame_stack = FrameStack.new
|
|
18
|
+
end
|
|
19
|
+
|
|
20
|
+
def set_title(title)
|
|
21
|
+
@app.set_window_title(title)
|
|
22
|
+
end
|
|
23
|
+
|
|
24
|
+
def set_geometry(w, h)
|
|
25
|
+
@app.set_window_geometry("#{w}x#{h}")
|
|
26
|
+
end
|
|
27
|
+
|
|
28
|
+
def set_aspect(numer, denom)
|
|
29
|
+
@app.command(:wm, 'aspect', '.', numer, denom, numer, denom)
|
|
30
|
+
end
|
|
31
|
+
|
|
32
|
+
def set_minsize(w, h)
|
|
33
|
+
@app.command(:wm, 'minsize', '.', w, h)
|
|
34
|
+
end
|
|
35
|
+
|
|
36
|
+
def reset_minsize
|
|
37
|
+
@app.command(:wm, 'minsize', '.', 0, 0)
|
|
38
|
+
end
|
|
39
|
+
|
|
40
|
+
def reset_aspect_ratio
|
|
41
|
+
@app.command(:wm, 'aspect', '.', '', '', '', '')
|
|
42
|
+
end
|
|
43
|
+
|
|
44
|
+
def set_timer_speed(ms)
|
|
45
|
+
@app.interp.thread_timer_ms = ms
|
|
46
|
+
end
|
|
47
|
+
|
|
48
|
+
def fullscreen=(val)
|
|
49
|
+
@app.command(:wm, 'attributes', '.', '-fullscreen', val ? 1 : 0)
|
|
50
|
+
end
|
|
51
|
+
|
|
52
|
+
def mainloop
|
|
53
|
+
@app.mainloop
|
|
54
|
+
end
|
|
55
|
+
end
|
|
56
|
+
end
|
|
@@ -0,0 +1,81 @@
|
|
|
1
|
+
# frozen_string_literal: true
|
|
2
|
+
|
|
3
|
+
module Gemba
|
|
4
|
+
# Push/pop stack for modal child windows.
|
|
5
|
+
#
|
|
6
|
+
# One modal can push another (e.g. Settings → Replay Player) and the
|
|
7
|
+
# previous modal is automatically re-shown on pop.
|
|
8
|
+
#
|
|
9
|
+
# Windows must implement the ModalWindow protocol:
|
|
10
|
+
# show_modal(**args) — reveal the window (deiconify, grab, position)
|
|
11
|
+
# withdraw — hide the window (release grab, withdraw — NO callback)
|
|
12
|
+
#
|
|
13
|
+
# @example
|
|
14
|
+
# stack = ModalStack.new(
|
|
15
|
+
# on_enter: ->(name) { pause_emulation },
|
|
16
|
+
# on_exit: -> { unpause_emulation },
|
|
17
|
+
# on_focus_change: ->(name) { update_toast(name) },
|
|
18
|
+
# )
|
|
19
|
+
# stack.push(:settings, @settings_window, show_args: { tab: :video })
|
|
20
|
+
# stack.push(:replay, @replay_player) # settings auto-withdrawn
|
|
21
|
+
# stack.pop # replay closed, settings re-shown
|
|
22
|
+
# stack.pop # settings closed, on_exit fired
|
|
23
|
+
class ModalStack
|
|
24
|
+
Entry = Data.define(:name, :window, :show_args)
|
|
25
|
+
|
|
26
|
+
# @param on_enter [Proc] called with (name) when stack goes empty → non-empty
|
|
27
|
+
# @param on_exit [Proc] called when stack goes non-empty → empty
|
|
28
|
+
# @param on_focus_change [Proc, nil] called with (name) whenever the top modal changes
|
|
29
|
+
def initialize(on_enter:, on_exit:, on_focus_change: nil)
|
|
30
|
+
@stack = []
|
|
31
|
+
@on_enter = on_enter
|
|
32
|
+
@on_exit = on_exit
|
|
33
|
+
@on_focus_change = on_focus_change
|
|
34
|
+
end
|
|
35
|
+
|
|
36
|
+
# @return [Boolean] true if any modal is open
|
|
37
|
+
def active? = !@stack.empty?
|
|
38
|
+
|
|
39
|
+
# @return [Symbol, nil] name of the topmost modal, or nil
|
|
40
|
+
def current = @stack.last&.name
|
|
41
|
+
|
|
42
|
+
# @return [Integer] number of modals on the stack
|
|
43
|
+
def size = @stack.length
|
|
44
|
+
|
|
45
|
+
# Push a modal onto the stack.
|
|
46
|
+
#
|
|
47
|
+
# If another modal is on top, it is withdrawn (without callback).
|
|
48
|
+
# If the stack was empty, on_enter is fired (pause emulation, etc.).
|
|
49
|
+
#
|
|
50
|
+
# @param name [Symbol] identifier for the modal (e.g. :settings, :picker)
|
|
51
|
+
# @param window [#show_modal, #withdraw] the modal window object
|
|
52
|
+
# @param show_args [Hash] keyword arguments forwarded to window.show_modal
|
|
53
|
+
def push(name, window, show_args: {})
|
|
54
|
+
was_empty = @stack.empty?
|
|
55
|
+
|
|
56
|
+
# Withdraw current top without firing its on_dismiss
|
|
57
|
+
@stack.last&.window&.withdraw
|
|
58
|
+
|
|
59
|
+
@stack.push(Entry.new(name: name, window: window, show_args: show_args))
|
|
60
|
+
@on_enter.call(name) if was_empty
|
|
61
|
+
@on_focus_change&.call(name)
|
|
62
|
+
window.show_modal(**show_args)
|
|
63
|
+
end
|
|
64
|
+
|
|
65
|
+
# Pop the current modal off the stack.
|
|
66
|
+
#
|
|
67
|
+
# If the stack still has entries, the previous modal is re-shown.
|
|
68
|
+
# If the stack is now empty, on_exit is fired (unpause emulation, etc.).
|
|
69
|
+
def pop
|
|
70
|
+
return unless (entry = @stack.pop)
|
|
71
|
+
entry.window.withdraw
|
|
72
|
+
|
|
73
|
+
if (prev = @stack.last)
|
|
74
|
+
@on_focus_change&.call(prev.name)
|
|
75
|
+
prev.window.show_modal(**prev.show_args)
|
|
76
|
+
else
|
|
77
|
+
@on_exit.call
|
|
78
|
+
end
|
|
79
|
+
end
|
|
80
|
+
end
|
|
81
|
+
end
|