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.
Files changed (285) hide show
  1. checksums.yaml +4 -4
  2. data/THIRD_PARTY_NOTICES +37 -2
  3. data/assets/placeholder_boxart.png +0 -0
  4. data/bin/gemba +2 -2
  5. data/ext/gemba/extconf.rb +23 -1
  6. data/ext/gemba/gemba_ext.c +436 -2
  7. data/ext/gemba/gemba_ext.h +2 -0
  8. data/gemba.gemspec +5 -3
  9. data/lib/gemba/achievements/achievement.rb +23 -0
  10. data/lib/gemba/achievements/backend.rb +186 -0
  11. data/lib/gemba/achievements/cache.rb +70 -0
  12. data/lib/gemba/achievements/credentials_presenter.rb +142 -0
  13. data/lib/gemba/achievements/fake_backend.rb +205 -0
  14. data/lib/gemba/achievements/null_backend.rb +11 -0
  15. data/lib/gemba/achievements/offline_backend.rb +168 -0
  16. data/lib/gemba/achievements/retro_achievements/backend.rb +453 -0
  17. data/lib/gemba/achievements/retro_achievements/cli_sync_requester.rb +64 -0
  18. data/lib/gemba/achievements/retro_achievements/ping_worker.rb +27 -0
  19. data/lib/gemba/achievements.rb +19 -0
  20. data/lib/gemba/achievements_window.rb +556 -0
  21. data/lib/gemba/app_controller.rb +1015 -0
  22. data/lib/gemba/bios.rb +54 -0
  23. data/lib/gemba/boxart_fetcher/libretro_backend.rb +39 -0
  24. data/lib/gemba/boxart_fetcher/null_backend.rb +12 -0
  25. data/lib/gemba/boxart_fetcher.rb +79 -0
  26. data/lib/gemba/bus_emitter.rb +13 -0
  27. data/lib/gemba/child_window.rb +24 -1
  28. data/lib/gemba/cli/commands/config_cmd.rb +83 -0
  29. data/lib/gemba/cli/commands/decode.rb +154 -0
  30. data/lib/gemba/cli/commands/patch.rb +78 -0
  31. data/lib/gemba/cli/commands/play.rb +78 -0
  32. data/lib/gemba/cli/commands/record.rb +114 -0
  33. data/lib/gemba/cli/commands/replay.rb +161 -0
  34. data/lib/gemba/cli/commands/retro_achievements.rb +213 -0
  35. data/lib/gemba/cli/commands/version.rb +22 -0
  36. data/lib/gemba/cli.rb +52 -364
  37. data/lib/gemba/config.rb +134 -1
  38. data/lib/gemba/data/gb_games.json +1 -0
  39. data/lib/gemba/data/gb_md5.json +1 -0
  40. data/lib/gemba/data/gba_games.json +1 -0
  41. data/lib/gemba/data/gba_md5.json +1 -0
  42. data/lib/gemba/data/gbc_games.json +1 -0
  43. data/lib/gemba/data/gbc_md5.json +1 -0
  44. data/lib/gemba/emulator_frame.rb +1060 -0
  45. data/lib/gemba/event_bus.rb +48 -0
  46. data/lib/gemba/frame_stack.rb +60 -0
  47. data/lib/gemba/game_index.rb +84 -0
  48. data/lib/gemba/game_picker_frame.rb +268 -0
  49. data/lib/gemba/gamepad_map.rb +103 -0
  50. data/lib/gemba/headless.rb +6 -5
  51. data/lib/gemba/headless_player.rb +33 -3
  52. data/lib/gemba/help_window.rb +61 -0
  53. data/lib/gemba/hotkey_map.rb +3 -1
  54. data/lib/gemba/input_recorder.rb +107 -0
  55. data/lib/gemba/input_replayer.rb +119 -0
  56. data/lib/gemba/keyboard_map.rb +90 -0
  57. data/lib/gemba/locales/en.yml +97 -5
  58. data/lib/gemba/locales/ja.yml +97 -5
  59. data/lib/gemba/main_window.rb +56 -0
  60. data/lib/gemba/modal_stack.rb +81 -0
  61. data/lib/gemba/patcher_window.rb +223 -0
  62. data/lib/gemba/platform/gb.rb +21 -0
  63. data/lib/gemba/platform/gba.rb +21 -0
  64. data/lib/gemba/platform/gbc.rb +23 -0
  65. data/lib/gemba/platform.rb +20 -0
  66. data/lib/gemba/platform_open.rb +19 -0
  67. data/lib/gemba/recorder.rb +4 -3
  68. data/lib/gemba/replay_player.rb +691 -0
  69. data/lib/gemba/rom_info.rb +57 -0
  70. data/lib/gemba/rom_info_window.rb +16 -3
  71. data/lib/gemba/rom_library.rb +106 -0
  72. data/lib/gemba/rom_overrides.rb +47 -0
  73. data/lib/gemba/rom_patcher/bps.rb +161 -0
  74. data/lib/gemba/rom_patcher/ips.rb +101 -0
  75. data/lib/gemba/rom_patcher/ups.rb +118 -0
  76. data/lib/gemba/rom_patcher.rb +109 -0
  77. data/lib/gemba/{rom_loader.rb → rom_resolver.rb} +7 -6
  78. data/lib/gemba/runtime.rb +59 -26
  79. data/lib/gemba/save_state_manager.rb +4 -7
  80. data/lib/gemba/save_state_picker.rb +17 -4
  81. data/lib/gemba/session_logger.rb +64 -0
  82. data/lib/gemba/settings/audio_tab.rb +77 -0
  83. data/lib/gemba/settings/gamepad_tab.rb +351 -0
  84. data/lib/gemba/settings/hotkeys_tab.rb +259 -0
  85. data/lib/gemba/settings/paths.rb +11 -0
  86. data/lib/gemba/settings/recording_tab.rb +83 -0
  87. data/lib/gemba/settings/save_states_tab.rb +91 -0
  88. data/lib/gemba/settings/system_tab.rb +362 -0
  89. data/lib/gemba/settings/video_tab.rb +318 -0
  90. data/lib/gemba/settings_window.rb +162 -1036
  91. data/lib/gemba/version.rb +1 -1
  92. data/lib/gemba/virtual_keyboard.rb +19 -0
  93. data/lib/gemba.rb +2 -12
  94. data/test/achievements_window/test_bulk_sync.rb +218 -0
  95. data/test/achievements_window/test_bus_events.rb +125 -0
  96. data/test/achievements_window/test_close_confirmation.rb +201 -0
  97. data/test/achievements_window/test_initial_state.rb +164 -0
  98. data/test/achievements_window/test_sorting.rb +227 -0
  99. data/test/achievements_window/test_tree_rendering.rb +133 -0
  100. data/test/fixtures/fake_bios.bin +0 -0
  101. data/test/fixtures/pong.gba +0 -0
  102. data/test/fixtures/test.gb +0 -0
  103. data/test/fixtures/test.gbc +0 -0
  104. data/test/fixtures/test_quicksave.ss +0 -0
  105. data/test/screenshots/no_focus.png +0 -0
  106. data/test/shared/teek_test_worker.rb +17 -1
  107. data/test/shared/tk_test_helper.rb +91 -4
  108. data/test/support/achievements_window_helpers.rb +18 -0
  109. data/test/support/fake_core.rb +25 -0
  110. data/test/support/fake_ra_runtime.rb +74 -0
  111. data/test/support/fake_requester.rb +68 -0
  112. data/test/support/player_helpers.rb +20 -5
  113. data/test/test_achievement.rb +32 -0
  114. data/test/{test_player.rb → test_app_controller.rb} +353 -85
  115. data/test/test_bios.rb +123 -0
  116. data/test/test_boxart_fetcher.rb +150 -0
  117. data/test/test_cli.rb +17 -265
  118. data/test/test_cli_config.rb +64 -0
  119. data/test/test_cli_decode.rb +97 -0
  120. data/test/test_cli_patch.rb +58 -0
  121. data/test/test_cli_play.rb +213 -0
  122. data/test/test_cli_ra.rb +175 -0
  123. data/test/test_cli_record.rb +69 -0
  124. data/test/test_cli_replay.rb +72 -0
  125. data/test/test_cli_sync_requester.rb +152 -0
  126. data/test/test_cli_version.rb +27 -0
  127. data/test/test_config.rb +2 -3
  128. data/test/test_config_ra.rb +69 -0
  129. data/test/test_core.rb +62 -1
  130. data/test/test_credentials_presenter.rb +192 -0
  131. data/test/test_event_bus.rb +100 -0
  132. data/test/test_fake_backend_achievements.rb +130 -0
  133. data/test/test_fake_backend_auth.rb +68 -0
  134. data/test/test_game_index.rb +77 -0
  135. data/test/test_game_picker_frame.rb +310 -0
  136. data/test/test_gamepad_map.rb +1 -3
  137. data/test/test_headless_player.rb +17 -3
  138. data/test/test_help_window.rb +82 -0
  139. data/test/test_hotkey_map.rb +22 -1
  140. data/test/test_input_recorder.rb +179 -0
  141. data/test/test_input_replay_determinism.rb +113 -0
  142. data/test/test_input_replayer.rb +162 -0
  143. data/test/test_keyboard_map.rb +1 -3
  144. data/test/test_libretro_backend.rb +41 -0
  145. data/test/test_locale.rb +1 -1
  146. data/test/test_logging.rb +123 -0
  147. data/test/test_null_backend.rb +42 -0
  148. data/test/test_offline_backend.rb +116 -0
  149. data/test/test_overlay_renderer.rb +1 -1
  150. data/test/test_platform.rb +149 -0
  151. data/test/test_ra_backend.rb +313 -0
  152. data/test/test_ra_backend_unlock_gate.rb +56 -0
  153. data/test/test_recorder.rb +0 -3
  154. data/test/test_replay_player.rb +316 -0
  155. data/test/test_rom_info.rb +149 -0
  156. data/test/test_rom_overrides.rb +86 -0
  157. data/test/test_rom_patcher.rb +382 -0
  158. data/test/{test_rom_loader.rb → test_rom_resolver.rb} +25 -26
  159. data/test/test_save_state_manager.rb +2 -4
  160. data/test/test_settings_audio.rb +107 -0
  161. data/test/test_settings_hotkeys.rb +83 -66
  162. data/test/test_settings_recording.rb +49 -0
  163. data/test/test_settings_save_states.rb +97 -0
  164. data/test/test_settings_system.rb +133 -0
  165. data/test/test_settings_video.rb +450 -0
  166. data/test/test_settings_window.rb +76 -507
  167. data/test/test_tip_service.rb +6 -6
  168. data/test/test_toast_overlay.rb +1 -1
  169. data/test/test_virtual_events.rb +156 -0
  170. data/test/test_virtual_keyboard.rb +1 -1
  171. data/vendor/rcheevos/CHANGELOG.md +495 -0
  172. data/vendor/rcheevos/LICENSE +21 -0
  173. data/vendor/rcheevos/Package.swift +33 -0
  174. data/vendor/rcheevos/README.md +67 -0
  175. data/vendor/rcheevos/include/module.modulemap +70 -0
  176. data/vendor/rcheevos/include/rc_api_editor.h +296 -0
  177. data/vendor/rcheevos/include/rc_api_info.h +280 -0
  178. data/vendor/rcheevos/include/rc_api_request.h +77 -0
  179. data/vendor/rcheevos/include/rc_api_runtime.h +417 -0
  180. data/vendor/rcheevos/include/rc_api_user.h +262 -0
  181. data/vendor/rcheevos/include/rc_client.h +877 -0
  182. data/vendor/rcheevos/include/rc_client_raintegration.h +101 -0
  183. data/vendor/rcheevos/include/rc_consoles.h +138 -0
  184. data/vendor/rcheevos/include/rc_error.h +59 -0
  185. data/vendor/rcheevos/include/rc_export.h +100 -0
  186. data/vendor/rcheevos/include/rc_hash.h +200 -0
  187. data/vendor/rcheevos/include/rc_runtime.h +148 -0
  188. data/vendor/rcheevos/include/rc_runtime_types.h +452 -0
  189. data/vendor/rcheevos/include/rc_util.h +51 -0
  190. data/vendor/rcheevos/include/rcheevos.h +8 -0
  191. data/vendor/rcheevos/src/rapi/rc_api_common.c +1379 -0
  192. data/vendor/rcheevos/src/rapi/rc_api_common.h +88 -0
  193. data/vendor/rcheevos/src/rapi/rc_api_editor.c +625 -0
  194. data/vendor/rcheevos/src/rapi/rc_api_info.c +587 -0
  195. data/vendor/rcheevos/src/rapi/rc_api_runtime.c +901 -0
  196. data/vendor/rcheevos/src/rapi/rc_api_user.c +483 -0
  197. data/vendor/rcheevos/src/rc_client.c +6941 -0
  198. data/vendor/rcheevos/src/rc_client_external.c +281 -0
  199. data/vendor/rcheevos/src/rc_client_external.h +177 -0
  200. data/vendor/rcheevos/src/rc_client_external_versions.h +171 -0
  201. data/vendor/rcheevos/src/rc_client_internal.h +409 -0
  202. data/vendor/rcheevos/src/rc_client_raintegration.c +566 -0
  203. data/vendor/rcheevos/src/rc_client_raintegration_internal.h +61 -0
  204. data/vendor/rcheevos/src/rc_client_types.natvis +396 -0
  205. data/vendor/rcheevos/src/rc_compat.c +251 -0
  206. data/vendor/rcheevos/src/rc_compat.h +121 -0
  207. data/vendor/rcheevos/src/rc_libretro.c +915 -0
  208. data/vendor/rcheevos/src/rc_libretro.h +98 -0
  209. data/vendor/rcheevos/src/rc_util.c +199 -0
  210. data/vendor/rcheevos/src/rc_version.c +11 -0
  211. data/vendor/rcheevos/src/rc_version.h +32 -0
  212. data/vendor/rcheevos/src/rcheevos/alloc.c +312 -0
  213. data/vendor/rcheevos/src/rcheevos/condition.c +754 -0
  214. data/vendor/rcheevos/src/rcheevos/condset.c +777 -0
  215. data/vendor/rcheevos/src/rcheevos/consoleinfo.c +1215 -0
  216. data/vendor/rcheevos/src/rcheevos/format.c +330 -0
  217. data/vendor/rcheevos/src/rcheevos/lboard.c +287 -0
  218. data/vendor/rcheevos/src/rcheevos/memref.c +805 -0
  219. data/vendor/rcheevos/src/rcheevos/operand.c +607 -0
  220. data/vendor/rcheevos/src/rcheevos/rc_internal.h +390 -0
  221. data/vendor/rcheevos/src/rcheevos/rc_runtime_types.natvis +541 -0
  222. data/vendor/rcheevos/src/rcheevos/rc_validate.c +1406 -0
  223. data/vendor/rcheevos/src/rcheevos/rc_validate.h +18 -0
  224. data/vendor/rcheevos/src/rcheevos/richpresence.c +922 -0
  225. data/vendor/rcheevos/src/rcheevos/runtime.c +852 -0
  226. data/vendor/rcheevos/src/rcheevos/runtime_progress.c +1073 -0
  227. data/vendor/rcheevos/src/rcheevos/trigger.c +344 -0
  228. data/vendor/rcheevos/src/rcheevos/value.c +935 -0
  229. data/vendor/rcheevos/src/rhash/aes.c +480 -0
  230. data/vendor/rcheevos/src/rhash/aes.h +49 -0
  231. data/vendor/rcheevos/src/rhash/cdreader.c +838 -0
  232. data/vendor/rcheevos/src/rhash/hash.c +1402 -0
  233. data/vendor/rcheevos/src/rhash/hash_disc.c +1340 -0
  234. data/vendor/rcheevos/src/rhash/hash_encrypted.c +566 -0
  235. data/vendor/rcheevos/src/rhash/hash_rom.c +426 -0
  236. data/vendor/rcheevos/src/rhash/hash_zip.c +460 -0
  237. data/vendor/rcheevos/src/rhash/md5.c +382 -0
  238. data/vendor/rcheevos/src/rhash/md5.h +91 -0
  239. data/vendor/rcheevos/src/rhash/rc_hash_internal.h +116 -0
  240. data/vendor/rcheevos/test/libretro.h +205 -0
  241. data/vendor/rcheevos/test/rapi/test_rc_api_common.c +941 -0
  242. data/vendor/rcheevos/test/rapi/test_rc_api_editor.c +931 -0
  243. data/vendor/rcheevos/test/rapi/test_rc_api_info.c +545 -0
  244. data/vendor/rcheevos/test/rapi/test_rc_api_runtime.c +2213 -0
  245. data/vendor/rcheevos/test/rapi/test_rc_api_user.c +998 -0
  246. data/vendor/rcheevos/test/rcheevos/mock_memory.h +32 -0
  247. data/vendor/rcheevos/test/rcheevos/test_condition.c +570 -0
  248. data/vendor/rcheevos/test/rcheevos/test_condset.c +5170 -0
  249. data/vendor/rcheevos/test/rcheevos/test_consoleinfo.c +203 -0
  250. data/vendor/rcheevos/test/rcheevos/test_format.c +112 -0
  251. data/vendor/rcheevos/test/rcheevos/test_lboard.c +746 -0
  252. data/vendor/rcheevos/test/rcheevos/test_memref.c +520 -0
  253. data/vendor/rcheevos/test/rcheevos/test_operand.c +692 -0
  254. data/vendor/rcheevos/test/rcheevos/test_rc_validate.c +502 -0
  255. data/vendor/rcheevos/test/rcheevos/test_richpresence.c +1564 -0
  256. data/vendor/rcheevos/test/rcheevos/test_runtime.c +1667 -0
  257. data/vendor/rcheevos/test/rcheevos/test_runtime_progress.c +1821 -0
  258. data/vendor/rcheevos/test/rcheevos/test_timing.c +166 -0
  259. data/vendor/rcheevos/test/rcheevos/test_trigger.c +2521 -0
  260. data/vendor/rcheevos/test/rcheevos/test_value.c +870 -0
  261. data/vendor/rcheevos/test/rcheevos-test.sln +46 -0
  262. data/vendor/rcheevos/test/rcheevos-test.vcxproj +239 -0
  263. data/vendor/rcheevos/test/rcheevos-test.vcxproj.filters +335 -0
  264. data/vendor/rcheevos/test/rhash/data.c +657 -0
  265. data/vendor/rcheevos/test/rhash/data.h +32 -0
  266. data/vendor/rcheevos/test/rhash/mock_filereader.c +236 -0
  267. data/vendor/rcheevos/test/rhash/mock_filereader.h +31 -0
  268. data/vendor/rcheevos/test/rhash/test_cdreader.c +920 -0
  269. data/vendor/rcheevos/test/rhash/test_hash.c +310 -0
  270. data/vendor/rcheevos/test/rhash/test_hash_disc.c +1450 -0
  271. data/vendor/rcheevos/test/rhash/test_hash_rom.c +899 -0
  272. data/vendor/rcheevos/test/rhash/test_hash_zip.c +551 -0
  273. data/vendor/rcheevos/test/test.c +113 -0
  274. data/vendor/rcheevos/test/test_framework.h +205 -0
  275. data/vendor/rcheevos/test/test_rc_client.c +10509 -0
  276. data/vendor/rcheevos/test/test_rc_client_external.c +2197 -0
  277. data/vendor/rcheevos/test/test_rc_client_raintegration.c +441 -0
  278. data/vendor/rcheevos/test/test_rc_libretro.c +952 -0
  279. data/vendor/rcheevos/test/test_types.natvis +9 -0
  280. data/vendor/rcheevos/validator/validator.c +658 -0
  281. data/vendor/rcheevos/validator/validator.vcxproj +152 -0
  282. data/vendor/rcheevos/validator/validator.vcxproj.filters +82 -0
  283. metadata +274 -11
  284. data/lib/gemba/input_mappings.rb +0 -214
  285. data/lib/gemba/player.rb +0 -1525
@@ -0,0 +1,920 @@
1
+ #include "rc_hash.h"
2
+
3
+ #include "../rc_compat.h"
4
+ #include "../src/rhash/rc_hash_internal.h"
5
+ #include "../test_framework.h"
6
+ #include "data.h"
7
+ #include "mock_filereader.h"
8
+
9
+ #include <stdlib.h>
10
+
11
+ static const uint8_t sync_pattern[] = {
12
+ 0x00, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0x00
13
+ };
14
+
15
+ static char cue_single_track[] =
16
+ "FILE \"game.bin\" BINARY\n"
17
+ " TRACK 01 MODE2/2352\n"
18
+ " INDEX 01 00:00:00\n";
19
+
20
+ static char cue_single_bin_multiple_data[] =
21
+ "FILE \"game.bin\" BINARY\n"
22
+ " TRACK 01 AUDIO\n"
23
+ " INDEX 01 00:00:00\n"
24
+ " TRACK 02 MODE1/2352\n"
25
+ " PREGAP 00:03:00\n"
26
+ " INDEX 01 00:55:45\n"
27
+ " TRACK 03 MODE1/2352\n"
28
+ " INDEX 01 11:30:74\n"
29
+ " TRACK 04 MODE1/2352\n"
30
+ " INDEX 01 13:31:51\n"
31
+ " TRACK 05 MODE1/2352\n"
32
+ " INDEX 01 13:48:56\n"
33
+ " TRACK 06 MODE1/2352\n"
34
+ " INDEX 01 34:48:19\n"
35
+ " TRACK 07 MODE1/2352\n"
36
+ " INDEX 01 50:42:74\n"
37
+ " TRACK 08 MODE1/2352\n"
38
+ " INDEX 01 55:20:74\n"
39
+ " TRACK 09 MODE1/2352\n"
40
+ " INDEX 01 56:25:67\n"
41
+ " TRACK 10 MODE1/2352\n"
42
+ " INDEX 01 59:04:08\n"
43
+ " TRACK 11 MODE1/2352\n"
44
+ " INDEX 01 61:17:18\n"
45
+ " TRACK 12 MODE1/2352\n"
46
+ " INDEX 01 62:44:33\n"
47
+ " TRACK 13 AUDIO\n"
48
+ " PREGAP 00:02:00\n"
49
+ " INDEX 01 66:24:37\n";
50
+
51
+ static char cue_multiple_bin_multiple_data[] =
52
+ "FILE \"track1.bin\" BINARY\n"
53
+ " TRACK 01 AUDIO\n"
54
+ " INDEX 01 00:00:00\n"
55
+ "FILE \"track2.bin\" BINARY\n"
56
+ " TRACK 02 MODE1/2352\n"
57
+ " INDEX 00 00:00:00\n"
58
+ " INDEX 01 00:03:00\n"
59
+ "FILE \"track3.bin\" BINARY\n"
60
+ " TRACK 03 MODE1/2352\n"
61
+ " INDEX 00 00:00:00\n"
62
+ " INDEX 01 00:02:00\n"
63
+ "FILE \"track4.bin\" BINARY\n"
64
+ " TRACK 04 AUDIO\n"
65
+ " INDEX 00 00:00:00\n";
66
+
67
+ static char gdi_three_tracks[] =
68
+ "3\n"
69
+ "1 0 4 2352 track01.bin 0\n"
70
+ "2 600 0 2352 track02.raw 0\n"
71
+ "3 45000 4 2352 track03.bin 0";
72
+
73
+ static char gdi_many_tracks[] =
74
+ "26\n"
75
+ "1 0 4 2352 track01.bin 0\n"
76
+ "2 450 0 2352 track02.raw 0\n"
77
+ "3 45000 4 2352 track03.bin 0\n"
78
+ "4 370673 0 2352 track04.raw 0\n"
79
+ "5 371347 0 2352 track05.raw 0\n"
80
+ "6 372014 0 2352 track06.raw 0\n"
81
+ "7 372915 0 2352 track07.raw 0\n"
82
+ "8 373626 0 2352 track08.raw 0\n"
83
+ "9 379011 0 2352 track09.raw 0\n"
84
+ "10 384738 0 2352 track10.raw 0\n"
85
+ "11 390481 0 2352 track11.raw 0\n"
86
+ "12 395473 0 2352 track12.raw 0\n"
87
+ "13 398926 0 2352 track13.raw 0\n"
88
+ "14 404448 0 2352 track14.raw 0\n"
89
+ "15 425246 0 2352 track15.raw 0\n"
90
+ "16 445520 0 2352 track16.raw 0\n"
91
+ "17 466032 0 2352 track17.raw 0\n"
92
+ "18 474231 0 2352 track18.raw 0\n"
93
+ "19 485598 0 2352 track19.raw 0\n"
94
+ "20 486386 0 2352 track20.raw 0\n"
95
+ "21 487098 0 2352 track21.raw 0\n"
96
+ "22 487822 0 2352 track22.raw 0\n"
97
+ "23 498356 0 2352 track23.raw 0\n"
98
+ "24 508297 0 2352 track24.raw 0\n"
99
+ "25 527383 0 2352 track25.raw 0\n"
100
+ "26 548106 4 2352 track26.bin 0\n";
101
+
102
+ static void initialize_iterator(rc_hash_iterator_t* iterator)
103
+ {
104
+ memset(iterator, 0, sizeof(*iterator));
105
+ rc_hash_get_default_cdreader(&iterator->callbacks.cdreader);
106
+ get_mock_filereader(&iterator->callbacks.filereader);
107
+ }
108
+
109
+ static rc_hash_cdrom_track_t* open_track(rc_hash_iterator_t* iterator, const char* path, uint32_t index)
110
+ {
111
+ return (rc_hash_cdrom_track_t*)iterator->callbacks.cdreader.open_track_iterator(path, index, iterator);
112
+ }
113
+
114
+ static void close_track(rc_hash_iterator_t* iterator, rc_hash_cdrom_track_t* track_handle)
115
+ {
116
+ iterator->callbacks.cdreader.close_track(track_handle);
117
+ }
118
+
119
+ static void test_open_cue_track_2()
120
+ {
121
+ rc_hash_cdrom_track_t* track_handle;
122
+ rc_hash_iterator_t iterator;
123
+ initialize_iterator(&iterator);
124
+
125
+ mock_file_text(0, "game.cue", cue_single_bin_multiple_data);
126
+ mock_empty_file(1, "game.bin", 718310208);
127
+
128
+ track_handle = open_track(&iterator, "game.cue", 2);
129
+ ASSERT_PTR_NOT_NULL(track_handle);
130
+
131
+ ASSERT_PTR_NOT_NULL(track_handle->file_handle);
132
+ ASSERT_STR_EQUALS(get_mock_filename(track_handle->file_handle), "game.bin");
133
+ ASSERT_NUM64_EQUALS(track_handle->file_track_offset, 9807840); /* track 2: 0x95A7E0 */
134
+ ASSERT_NUM_EQUALS(track_handle->sector_size, 2352);
135
+ ASSERT_NUM_EQUALS(track_handle->sector_header_size, 16);
136
+ ASSERT_NUM_EQUALS(track_handle->raw_data_size, 2048);
137
+
138
+ close_track(&iterator, track_handle);
139
+ }
140
+
141
+ static void test_open_cue_track_12()
142
+ {
143
+ rc_hash_cdrom_track_t* track_handle;
144
+ rc_hash_iterator_t iterator;
145
+ initialize_iterator(&iterator);
146
+
147
+ mock_file_text(0, "game.cue", cue_single_bin_multiple_data);
148
+ mock_empty_file(1, "game.bin", 718310208);
149
+
150
+ track_handle = open_track(&iterator, "game.cue", 12);
151
+ ASSERT_PTR_NOT_NULL(track_handle);
152
+
153
+ ASSERT_PTR_NOT_NULL(track_handle->file_handle);
154
+ ASSERT_STR_EQUALS(get_mock_filename(track_handle->file_handle), "game.bin");
155
+ ASSERT_NUM64_EQUALS(track_handle->file_track_offset, 664047216); /* track 12: 0x27948E70 */
156
+ ASSERT_NUM_EQUALS(track_handle->sector_size, 2352);
157
+ ASSERT_NUM_EQUALS(track_handle->sector_header_size, 16);
158
+ ASSERT_NUM_EQUALS(track_handle->raw_data_size, 2048);
159
+
160
+ close_track(&iterator, track_handle);
161
+ }
162
+
163
+ static void test_open_cue_track_14()
164
+ {
165
+ rc_hash_cdrom_track_t* track_handle;
166
+ rc_hash_iterator_t iterator;
167
+ initialize_iterator(&iterator);
168
+
169
+ mock_file_text(0, "game.cue", cue_single_bin_multiple_data);
170
+ mock_empty_file(1, "game.bin", 718310208);
171
+
172
+ /* only 13 tracks */
173
+ track_handle = open_track(&iterator, "game.cue", 14);
174
+ ASSERT_PTR_NULL(track_handle);
175
+ }
176
+
177
+ static void test_open_cue_track_missing_bin()
178
+ {
179
+ rc_hash_cdrom_track_t* track_handle;
180
+ rc_hash_iterator_t iterator;
181
+ initialize_iterator(&iterator);
182
+
183
+ mock_file_text(0, "game.cue", cue_single_bin_multiple_data);
184
+
185
+ track_handle = open_track(&iterator, "game.cue", 2);
186
+ ASSERT_PTR_NULL(track_handle);
187
+ }
188
+
189
+ static void test_open_gdi_track_3()
190
+ {
191
+ rc_hash_cdrom_track_t* track_handle;
192
+ rc_hash_iterator_t iterator;
193
+ initialize_iterator(&iterator);
194
+
195
+ mock_file_text(0, "game.gdi", gdi_three_tracks);
196
+ mock_empty_file(1, "track03.bin", 1185760800);
197
+
198
+ track_handle = open_track(&iterator, "game.gdi", 3);
199
+ ASSERT_PTR_NOT_NULL(track_handle);
200
+
201
+ ASSERT_PTR_NOT_NULL(track_handle->file_handle);
202
+ ASSERT_STR_EQUALS(get_mock_filename(track_handle->file_handle), "track03.bin");
203
+ ASSERT_NUM64_EQUALS(track_handle->track_pregap_sectors, 0);
204
+ ASSERT_NUM_EQUALS(track_handle->track_first_sector, 45000);
205
+ ASSERT_NUM_EQUALS(track_handle->sector_size, 2352);
206
+ ASSERT_NUM_EQUALS(track_handle->sector_header_size, 16);
207
+ ASSERT_NUM_EQUALS(track_handle->raw_data_size, 2048);
208
+
209
+ close_track(&iterator, track_handle);
210
+ }
211
+
212
+ static void test_open_gdi_track_3_quoted()
213
+ {
214
+ const char gdi_contents[] =
215
+ "3\n"
216
+ "1 0 4 2352 \"track 01.bin\" 0\n"
217
+ "2 600 0 2352 \"track 02.raw\" 0\n"
218
+ "3 45000 4 2352 \"track 03.bin\" 0";
219
+
220
+ rc_hash_cdrom_track_t* track_handle;
221
+ rc_hash_iterator_t iterator;
222
+ initialize_iterator(&iterator);
223
+
224
+ mock_file_text(0, "game.gdi", gdi_contents);
225
+ mock_empty_file(1, "track 03.bin", 1185760800);
226
+
227
+ track_handle = open_track(&iterator, "game.gdi", 3);
228
+ ASSERT_PTR_NOT_NULL(track_handle);
229
+
230
+ ASSERT_PTR_NOT_NULL(track_handle->file_handle);
231
+ ASSERT_STR_EQUALS(get_mock_filename(track_handle->file_handle), "track 03.bin");
232
+ ASSERT_NUM64_EQUALS(track_handle->track_pregap_sectors, 0);
233
+ ASSERT_NUM_EQUALS(track_handle->track_first_sector, 45000);
234
+ ASSERT_NUM_EQUALS(track_handle->sector_size, 2352);
235
+ ASSERT_NUM_EQUALS(track_handle->sector_header_size, 16);
236
+ ASSERT_NUM_EQUALS(track_handle->raw_data_size, 2048);
237
+
238
+ close_track(&iterator, track_handle);
239
+ }
240
+
241
+ static void test_open_gdi_track_3_extra_whitespace()
242
+ {
243
+ const char gdi_contents[] =
244
+ "3\n\n"
245
+ " 1 0 4 2352 \"track 01.bin\" 0\n\n"
246
+ " 2 600 0 2352 \"track 02.raw\" 0\n\n"
247
+ " 3 45000 4 2352 \"track 03.bin\" 0\n\n";
248
+
249
+ rc_hash_cdrom_track_t* track_handle;
250
+ rc_hash_iterator_t iterator;
251
+ initialize_iterator(&iterator);
252
+
253
+ mock_file_text(0, "game.gdi", gdi_contents);
254
+ mock_empty_file(1, "track 03.bin", 1185760800);
255
+
256
+ track_handle = open_track(&iterator, "game.gdi", 3);
257
+ ASSERT_PTR_NOT_NULL(track_handle);
258
+
259
+ ASSERT_PTR_NOT_NULL(track_handle->file_handle);
260
+ ASSERT_STR_EQUALS(get_mock_filename(track_handle->file_handle), "track 03.bin");
261
+ ASSERT_NUM64_EQUALS(track_handle->track_pregap_sectors, 0);
262
+ ASSERT_NUM_EQUALS(track_handle->track_first_sector, 45000);
263
+ ASSERT_NUM_EQUALS(track_handle->sector_size, 2352);
264
+ ASSERT_NUM_EQUALS(track_handle->sector_header_size, 16);
265
+
266
+ close_track(&iterator, track_handle);
267
+ }
268
+
269
+ static void test_open_gdi_track_last()
270
+ {
271
+ rc_hash_cdrom_track_t* track_handle;
272
+ rc_hash_iterator_t iterator;
273
+ initialize_iterator(&iterator);
274
+
275
+ mock_file_text(0, "game.gdi", gdi_many_tracks);
276
+ mock_empty_file(1, "track26.bin", 2457600);
277
+
278
+ track_handle = open_track(&iterator, "game.gdi", RC_HASH_CDTRACK_LAST);
279
+ ASSERT_PTR_NOT_NULL(track_handle);
280
+
281
+ ASSERT_PTR_NOT_NULL(track_handle->file_handle);
282
+ ASSERT_STR_EQUALS(get_mock_filename(track_handle->file_handle), "track26.bin");
283
+ ASSERT_NUM64_EQUALS(track_handle->track_pregap_sectors, 0);
284
+ ASSERT_NUM_EQUALS(track_handle->track_first_sector, 548106);
285
+ ASSERT_NUM_EQUALS(track_handle->sector_size, 2352);
286
+ ASSERT_NUM_EQUALS(track_handle->sector_header_size, 16);
287
+
288
+ close_track(&iterator, track_handle);
289
+ }
290
+
291
+ static void test_open_cue_track_largest_data()
292
+ {
293
+ rc_hash_cdrom_track_t* track_handle;
294
+ rc_hash_iterator_t iterator;
295
+ initialize_iterator(&iterator);
296
+
297
+ mock_file_text(0, "game.cue", cue_single_bin_multiple_data);
298
+ mock_empty_file(1, "game.bin", 718310208);
299
+
300
+ track_handle = open_track(&iterator, "game.cue", RC_HASH_CDTRACK_LARGEST);
301
+ ASSERT_PTR_NOT_NULL(track_handle);
302
+
303
+ ASSERT_PTR_NOT_NULL(track_handle->file_handle);
304
+ ASSERT_STR_EQUALS(get_mock_filename(track_handle->file_handle), "game.bin");
305
+ ASSERT_NUM64_EQUALS(track_handle->file_track_offset, 146190912); /* track 5: 0x8B6B240 */
306
+ ASSERT_NUM_EQUALS(track_handle->sector_size, 2352);
307
+ ASSERT_NUM_EQUALS(track_handle->sector_header_size, 16);
308
+ ASSERT_NUM_EQUALS(track_handle->raw_data_size, 2048);
309
+
310
+ close_track(&iterator, track_handle);
311
+ }
312
+
313
+ static void test_open_cue_track_largest_data_multiple_bin()
314
+ {
315
+ rc_hash_cdrom_track_t* track_handle;
316
+ rc_hash_iterator_t iterator;
317
+ initialize_iterator(&iterator);
318
+
319
+ mock_file_text(0, "game.cue", cue_multiple_bin_multiple_data);
320
+ mock_empty_file(1, "track2.bin", 406423248);
321
+ mock_empty_file(2, "track3.bin", 11553024);
322
+
323
+ track_handle = open_track(&iterator, "game.cue", RC_HASH_CDTRACK_LARGEST);
324
+ ASSERT_PTR_NOT_NULL(track_handle);
325
+
326
+ ASSERT_PTR_NOT_NULL(track_handle->file_handle);
327
+ ASSERT_STR_EQUALS(get_mock_filename(track_handle->file_handle), "track2.bin");
328
+ ASSERT_NUM64_EQUALS(track_handle->file_track_offset, 0);
329
+ ASSERT_NUM_EQUALS(track_handle->track_pregap_sectors, 225); /* INDEX 01 00:03:00 */
330
+ ASSERT_NUM_EQUALS(track_handle->sector_size, 2352);
331
+ ASSERT_NUM_EQUALS(track_handle->sector_header_size, 16);
332
+ ASSERT_NUM_EQUALS(track_handle->raw_data_size, 2048);
333
+
334
+ close_track(&iterator, track_handle);
335
+ }
336
+
337
+ static void test_open_cue_track_largest_data_backwards_compatibility()
338
+ {
339
+ rc_hash_cdrom_track_t* track_handle;
340
+ rc_hash_iterator_t iterator;
341
+ initialize_iterator(&iterator);
342
+
343
+ mock_file_text(0, "game.cue", cue_single_bin_multiple_data);
344
+ mock_empty_file(1, "game.bin", 718310208);
345
+
346
+ /* before defining the enum, 0 meant largest */
347
+ track_handle = open_track(&iterator, "game.cue", 0);
348
+ ASSERT_PTR_NOT_NULL(track_handle);
349
+
350
+ ASSERT_PTR_NOT_NULL(track_handle->file_handle);
351
+ ASSERT_STR_EQUALS(get_mock_filename(track_handle->file_handle), "game.bin");
352
+ ASSERT_NUM64_EQUALS(track_handle->file_track_offset, 146190912); /* track 5: 0x8B6B240 */
353
+ ASSERT_NUM_EQUALS(track_handle->sector_size, 2352);
354
+ ASSERT_NUM_EQUALS(track_handle->sector_header_size, 16);
355
+ ASSERT_NUM_EQUALS(track_handle->raw_data_size, 2048);
356
+
357
+ close_track(&iterator, track_handle);
358
+ }
359
+
360
+ static void test_open_cue_track_largest_data_last_track()
361
+ {
362
+ const char cue[] =
363
+ "FILE \"game.bin\" BINARY\n"
364
+ " TRACK 01 AUDIO\n"
365
+ " INDEX 01 00:00:00\n"
366
+ " TRACK 02 MODE1/2352\n"
367
+ " PREGAP 00:03:00\n"
368
+ " INDEX 01 00:55:45\n"
369
+ " TRACK 03 MODE1/2352\n"
370
+ " INDEX 01 11:30:74\n"
371
+ " TRACK 04 MODE1/2352\n"
372
+ " INDEX 01 13:31:51\n"
373
+ " TRACK 05 MODE1/2352\n"
374
+ " INDEX 01 13:48:56\n";
375
+
376
+ rc_hash_cdrom_track_t* track_handle;
377
+ rc_hash_iterator_t iterator;
378
+ initialize_iterator(&iterator);
379
+
380
+ mock_file_text(0, "game.cue", cue);
381
+ mock_empty_file(1, "game.bin", 718310208);
382
+
383
+ track_handle = open_track(&iterator, "game.cue", RC_HASH_CDTRACK_LARGEST);
384
+ ASSERT_PTR_NOT_NULL(track_handle);
385
+
386
+ ASSERT_PTR_NOT_NULL(track_handle->file_handle);
387
+ ASSERT_STR_EQUALS(get_mock_filename(track_handle->file_handle), "game.bin");
388
+ ASSERT_NUM64_EQUALS(track_handle->file_track_offset, 146190912); /* track 5: 0x8B6B240 (13:48:56) */
389
+ ASSERT_NUM_EQUALS(track_handle->sector_size, 2352);
390
+ ASSERT_NUM_EQUALS(track_handle->sector_header_size, 16);
391
+
392
+ close_track(&iterator, track_handle);
393
+ }
394
+
395
+ static void test_open_cue_track_largest_data_index0s()
396
+ {
397
+ const char cue[] =
398
+ "FILE \"game.bin\" BINARY\n"
399
+ " TRACK 01 AUDIO\n"
400
+ " INDEX 01 00:00:00\n"
401
+ " TRACK 02 MODE1/2352\n"
402
+ " INDEX 00 00:44:65\n"
403
+ " INDEX 01 00:47:65\n"
404
+ " TRACK 03 AUDIO\n"
405
+ " INDEX 00 01:19:52\n"
406
+ " INDEX 01 01:21:52\n";
407
+
408
+ rc_hash_cdrom_track_t* track_handle;
409
+ rc_hash_iterator_t iterator;
410
+ initialize_iterator(&iterator);
411
+
412
+ mock_file_text(0, "game.cue", cue);
413
+ mock_empty_file(1, "game.bin", 718310208);
414
+
415
+ track_handle = open_track(&iterator, "game.cue", RC_HASH_CDTRACK_LARGEST);
416
+ ASSERT_PTR_NOT_NULL(track_handle);
417
+
418
+ ASSERT_PTR_NOT_NULL(track_handle->file_handle);
419
+ ASSERT_STR_EQUALS(get_mock_filename(track_handle->file_handle), "game.bin");
420
+ ASSERT_NUM64_EQUALS(track_handle->file_track_offset, 7914480); /* track 2: 0x78C3F0 (00:44:65) */
421
+ ASSERT_NUM_EQUALS(track_handle->track_pregap_sectors, 225);
422
+ ASSERT_NUM_EQUALS(track_handle->sector_size, 2352);
423
+ ASSERT_NUM_EQUALS(track_handle->sector_header_size, 16);
424
+
425
+ close_track(&iterator, track_handle);
426
+ }
427
+
428
+ static void test_open_cue_track_largest_data_index2()
429
+ {
430
+ const char cue[] =
431
+ "FILE \"game.bin\" BINARY\n"
432
+ " TRACK 01 AUDIO\n"
433
+ " INDEX 01 00:00:00\n"
434
+ " TRACK 02 MODE1/2352\n"
435
+ " INDEX 00 00:00:00\n"
436
+ " INDEX 01 00:02:00\n"
437
+ " INDEX 02 00:08:64\n";
438
+
439
+ rc_hash_cdrom_track_t* track_handle;
440
+ rc_hash_iterator_t iterator;
441
+ initialize_iterator(&iterator);
442
+
443
+ mock_file_text(0, "game.cue", cue);
444
+ mock_empty_file(1, "game.bin", 718310208);
445
+
446
+ track_handle = open_track(&iterator, "game.cue", RC_HASH_CDTRACK_LARGEST);
447
+ ASSERT_PTR_NOT_NULL(track_handle);
448
+
449
+ ASSERT_PTR_NOT_NULL(track_handle->file_handle);
450
+ ASSERT_STR_EQUALS(get_mock_filename(track_handle->file_handle), "game.bin");
451
+ ASSERT_NUM64_EQUALS(track_handle->file_track_offset, 0);
452
+ ASSERT_NUM_EQUALS(track_handle->track_pregap_sectors, 150); /* 00:02:00 = 150 frames in */
453
+ ASSERT_NUM_EQUALS(track_handle->sector_size, 2352);
454
+ ASSERT_NUM_EQUALS(track_handle->sector_header_size, 16);
455
+
456
+ close_track(&iterator, track_handle);
457
+ }
458
+
459
+ static void test_open_cue_track_largest_data_multiple_bins()
460
+ {
461
+ rc_hash_cdrom_track_t* track_handle;
462
+ rc_hash_iterator_t iterator;
463
+ initialize_iterator(&iterator);
464
+
465
+ mock_file_text(0, "game.cue", cue_multiple_bin_multiple_data);
466
+ mock_empty_file(1, "track1.bin", 4132464);
467
+ mock_empty_file(2, "track2.bin", 30080102);
468
+ mock_empty_file(3, "track3.bin", 40343152);
469
+ mock_empty_file(4, "track4.bin", 47277552);
470
+
471
+ track_handle = open_track(&iterator, "game.cue", 0);
472
+ ASSERT_PTR_NOT_NULL(track_handle);
473
+
474
+ ASSERT_PTR_NOT_NULL(track_handle->file_handle);
475
+ ASSERT_STR_EQUALS(get_mock_filename(track_handle->file_handle), "track3.bin");
476
+ ASSERT_NUM64_EQUALS(track_handle->file_track_offset, 0);
477
+ ASSERT_NUM_EQUALS(track_handle->track_pregap_sectors, 150); /* 00:02:00 = 150 frames in */
478
+ ASSERT_NUM_EQUALS(track_handle->sector_size, 2352);
479
+ ASSERT_NUM_EQUALS(track_handle->sector_header_size, 16);
480
+
481
+ close_track(&iterator, track_handle);
482
+ }
483
+
484
+ static void test_open_cue_track_largest_data_only_audio()
485
+ {
486
+ const char cue[] =
487
+ "FILE \"track1.bin\" BINARY\n"
488
+ " TRACK 01 AUDIO\n"
489
+ " INDEX 01 00:00:00\n"
490
+ "FILE \"track2.bin\" BINARY\n"
491
+ " TRACK 02 AUDIO\n"
492
+ " INDEX 00 00:00:00\n"
493
+ " INDEX 01 00:03:00\n"
494
+ "FILE \"track3.bin\" BINARY\n"
495
+ " TRACK 03 AUDIO\n"
496
+ " INDEX 00 00:00:00\n"
497
+ " INDEX 01 00:02:00\n"
498
+ "FILE \"track4.bin\" BINARY\n"
499
+ " TRACK 04 AUDIO\n"
500
+ " INDEX 00 00:00:00\n";
501
+
502
+ rc_hash_cdrom_track_t* track_handle;
503
+ rc_hash_iterator_t iterator;
504
+ initialize_iterator(&iterator);
505
+
506
+ mock_file_text(0, "game.cue", cue);
507
+ mock_empty_file(1, "track1.bin", 4132464);
508
+ mock_empty_file(2, "track2.bin", 30080102);
509
+ mock_empty_file(3, "track3.bin", 40343152);
510
+ mock_empty_file(4, "track4.bin", 47277552);
511
+
512
+ track_handle = open_track(&iterator, "game.cue", 0);
513
+ ASSERT_PTR_NULL(track_handle);
514
+ }
515
+
516
+ static void test_open_cue_track_first_data()
517
+ {
518
+ rc_hash_cdrom_track_t* track_handle;
519
+ rc_hash_iterator_t iterator;
520
+ initialize_iterator(&iterator);
521
+
522
+ mock_file_text(0, "game.cue", cue_single_bin_multiple_data);
523
+ mock_empty_file(1, "game.bin", 718310208);
524
+
525
+ track_handle = open_track(&iterator, "game.cue", RC_HASH_CDTRACK_FIRST_DATA);
526
+ ASSERT_PTR_NOT_NULL(track_handle);
527
+
528
+ ASSERT_PTR_NOT_NULL(track_handle->file_handle);
529
+ ASSERT_STR_EQUALS(get_mock_filename(track_handle->file_handle), "game.bin");
530
+ ASSERT_NUM64_EQUALS(track_handle->file_track_offset, 9807840); /* track 2: 0x0095a7e0 (00:55:45) */
531
+ ASSERT_NUM_EQUALS(track_handle->track_pregap_sectors, 0);
532
+ ASSERT_NUM_EQUALS(track_handle->sector_size, 2352);
533
+ ASSERT_NUM_EQUALS(track_handle->sector_header_size, 16);
534
+
535
+ close_track(&iterator, track_handle);
536
+ }
537
+
538
+ static void test_determine_sector_size_sync(int sector_size)
539
+ {
540
+ rc_hash_cdrom_track_t* track_handle;
541
+ rc_hash_iterator_t iterator;
542
+
543
+ const size_t image_size = (size_t)sector_size * 32;
544
+ uint8_t* image = (uint8_t*)malloc(image_size);
545
+ ASSERT_PTR_NOT_NULL(image);
546
+
547
+ initialize_iterator(&iterator);
548
+
549
+ mock_file_text(0, "game.cue", cue_single_track);
550
+ mock_file(1, "game.bin", image, image_size);
551
+
552
+ memset(image, 0, image_size);
553
+ memcpy(&image[sector_size * 16], sync_pattern, sizeof(sync_pattern));
554
+
555
+ track_handle = open_track(&iterator, "game.cue", 1);
556
+ ASSERT_PTR_NOT_NULL(track_handle);
557
+
558
+ ASSERT_PTR_NOT_NULL(track_handle->file_handle);
559
+ ASSERT_STR_EQUALS(get_mock_filename(track_handle->file_handle), "game.bin");
560
+ ASSERT_NUM64_EQUALS(track_handle->file_track_offset, 0);
561
+ ASSERT_NUM_EQUALS(track_handle->sector_size, sector_size);
562
+ ASSERT_NUM_EQUALS(track_handle->sector_header_size, 16);
563
+ ASSERT_NUM_EQUALS(track_handle->raw_data_size, 2048);
564
+
565
+ close_track(&iterator, track_handle);
566
+ free(image);
567
+ }
568
+
569
+ static void test_determine_sector_size_sync_primary_volume_descriptor(int sector_size)
570
+ {
571
+ rc_hash_cdrom_track_t* track_handle;
572
+ rc_hash_iterator_t iterator;
573
+
574
+ const size_t image_size = (size_t)sector_size * 32;
575
+ uint8_t* image = (uint8_t*)malloc(image_size);
576
+ ASSERT_PTR_NOT_NULL(image);
577
+
578
+ initialize_iterator(&iterator);
579
+
580
+ mock_file_text(0, "game.cue", cue_single_track);
581
+ mock_file(1, "game.bin", image, image_size);
582
+
583
+ memset(image, 0, image_size);
584
+ memcpy(&image[sector_size * 16], sync_pattern, sizeof(sync_pattern));
585
+ memcpy(&image[sector_size * 16 + 25], "CD001", 5);
586
+
587
+ track_handle = open_track(&iterator, "game.cue", 1);
588
+ ASSERT_PTR_NOT_NULL(track_handle);
589
+
590
+ ASSERT_PTR_NOT_NULL(track_handle->file_handle);
591
+ ASSERT_STR_EQUALS(get_mock_filename(track_handle->file_handle), "game.bin");
592
+ ASSERT_NUM64_EQUALS(track_handle->file_track_offset, 0);
593
+ ASSERT_NUM_EQUALS(track_handle->sector_size, sector_size);
594
+ ASSERT_NUM_EQUALS(track_handle->sector_header_size, 24);
595
+ ASSERT_NUM_EQUALS(track_handle->raw_data_size, 2048);
596
+
597
+ close_track(&iterator, track_handle);
598
+ free(image);
599
+ }
600
+
601
+ static void test_determine_sector_size_sync_primary_volume_descriptor_index0(int sector_size)
602
+ {
603
+ char cue[] =
604
+ "FILE \"game.bin\" BINARY\n"
605
+ " TRACK 01 MODE2/2352\n"
606
+ " INDEX 00 00:00:00\n"
607
+ " INDEX 01 00:02:00\n";
608
+
609
+ rc_hash_cdrom_track_t* track_handle;
610
+ rc_hash_iterator_t iterator;
611
+
612
+ const size_t image_size = (size_t)sector_size * 200;
613
+ uint8_t* image = (uint8_t*)malloc(image_size);
614
+ ASSERT_PTR_NOT_NULL(image);
615
+
616
+ initialize_iterator(&iterator);
617
+
618
+ mock_file_text(0, "game.cue", cue);
619
+ mock_file(1, "game.bin", image, image_size);
620
+
621
+ char sector_size_str[16];
622
+ snprintf(sector_size_str, sizeof(sector_size_str), "%d", sector_size);
623
+ memcpy(&cue[40], sector_size_str, 4);
624
+
625
+ memset(image, 0, image_size);
626
+ memcpy(&image[sector_size * (150 + 16)], sync_pattern, sizeof(sync_pattern));
627
+ memcpy(&image[sector_size * (150 + 16) + 25], "CD001", 5);
628
+
629
+ track_handle = open_track(&iterator, "game.cue", 1);
630
+ ASSERT_PTR_NOT_NULL(track_handle);
631
+
632
+ ASSERT_PTR_NOT_NULL(track_handle->file_handle);
633
+ ASSERT_STR_EQUALS(get_mock_filename(track_handle->file_handle), "game.bin");
634
+ ASSERT_NUM64_EQUALS(track_handle->file_track_offset, 0);
635
+ ASSERT_NUM_EQUALS(track_handle->track_pregap_sectors, 150);
636
+ ASSERT_NUM_EQUALS(track_handle->sector_size, sector_size);
637
+ ASSERT_NUM_EQUALS(track_handle->sector_header_size, 24);
638
+ ASSERT_NUM_EQUALS(track_handle->raw_data_size, 2048);
639
+
640
+ close_track(&iterator, track_handle);
641
+ free(image);
642
+ }
643
+
644
+ static void test_determine_sector_size_sync_2048()
645
+ {
646
+ rc_hash_cdrom_track_t* track_handle;
647
+ rc_hash_iterator_t iterator;
648
+ const int sector_size = 2048;
649
+ const size_t image_size = (size_t)sector_size * 32;
650
+ uint8_t* image = (uint8_t*)malloc(image_size);
651
+ ASSERT_PTR_NOT_NULL(image);
652
+
653
+ initialize_iterator(&iterator);
654
+
655
+ mock_file_text(0, "game.cue", cue_single_track);
656
+ mock_file(1, "game.bin", image, image_size);
657
+
658
+ memset(image, 0, image_size);
659
+
660
+ /* 2048 byte sectors don't have a sync pattern - will use mode specified in header */
661
+ track_handle = open_track(&iterator, "game.cue", 1);
662
+ ASSERT_PTR_NOT_NULL(track_handle);
663
+
664
+ ASSERT_PTR_NOT_NULL(track_handle->file_handle);
665
+ ASSERT_STR_EQUALS(get_mock_filename(track_handle->file_handle), "game.bin");
666
+ ASSERT_NUM64_EQUALS(track_handle->file_track_offset, 0);
667
+ ASSERT_NUM_EQUALS(track_handle->sector_size, 2352);
668
+ ASSERT_NUM_EQUALS(track_handle->sector_header_size, 24);
669
+ ASSERT_NUM_EQUALS(track_handle->raw_data_size, 2048);
670
+
671
+ close_track(&iterator, track_handle);
672
+ free(image);
673
+ }
674
+
675
+ static void test_determine_sector_size_sync_primary_volume_descriptor_2048()
676
+ {
677
+ rc_hash_cdrom_track_t* track_handle;
678
+ rc_hash_iterator_t iterator;
679
+ const int sector_size = 2048;
680
+ const size_t image_size = (size_t)sector_size * 32;
681
+ uint8_t* image = (uint8_t*)malloc(image_size);
682
+ ASSERT_PTR_NOT_NULL(image);
683
+
684
+ initialize_iterator(&iterator);
685
+
686
+ mock_file_text(0, "game.cue", cue_single_track);
687
+ mock_file(1, "game.bin", image, image_size);
688
+
689
+ memset(image, 0, image_size);
690
+ memcpy(&image[sector_size * 16 + 1], "CD001", 5);
691
+
692
+ track_handle = open_track(&iterator, "game.cue", 1);
693
+ ASSERT_PTR_NOT_NULL(track_handle);
694
+
695
+ ASSERT_PTR_NOT_NULL(track_handle->file_handle);
696
+ ASSERT_STR_EQUALS(get_mock_filename(track_handle->file_handle), "game.bin");
697
+ ASSERT_NUM64_EQUALS(track_handle->file_track_offset, 0);
698
+ ASSERT_NUM_EQUALS(track_handle->sector_size, sector_size);
699
+ ASSERT_NUM_EQUALS(track_handle->sector_header_size, 0);
700
+ ASSERT_NUM_EQUALS(track_handle->raw_data_size, 2048);
701
+
702
+ close_track(&iterator, track_handle);
703
+ free(image);
704
+ }
705
+
706
+ static void test_determine_sector_size_sync_primary_volume_descriptor_index0_2048()
707
+ {
708
+ char cue[] =
709
+ "FILE \"game.bin\" BINARY\n"
710
+ " TRACK 01 MODE1/2048\n"
711
+ " INDEX 00 00:00:00\n"
712
+ " INDEX 01 00:02:00\n";
713
+
714
+ rc_hash_cdrom_track_t* track_handle;
715
+ rc_hash_iterator_t iterator;
716
+
717
+ const int sector_size = 2048;
718
+ const size_t image_size = (size_t)sector_size * 200;
719
+ uint8_t* image = (uint8_t*)malloc(image_size);
720
+ ASSERT_PTR_NOT_NULL(image);
721
+
722
+ initialize_iterator(&iterator);
723
+
724
+ mock_file_text(0, "game.cue", cue);
725
+ mock_file(1, "game.bin", image, image_size);
726
+
727
+ char sector_size_str[16];
728
+ snprintf(sector_size_str, sizeof(sector_size_str), "%d", sector_size);
729
+ memcpy(&cue[40], sector_size_str, 4);
730
+
731
+ memset(image, 0, image_size);
732
+ memcpy(&image[sector_size * (150 + 16) + 1], "CD001", 5);
733
+
734
+ track_handle = open_track(&iterator, "game.cue", 1);
735
+ ASSERT_PTR_NOT_NULL(track_handle);
736
+
737
+ ASSERT_PTR_NOT_NULL(track_handle->file_handle);
738
+ ASSERT_STR_EQUALS(get_mock_filename(track_handle->file_handle), "game.bin");
739
+ ASSERT_NUM64_EQUALS(track_handle->file_track_offset, 0);
740
+ ASSERT_NUM_EQUALS(track_handle->track_pregap_sectors, 150);
741
+ ASSERT_NUM_EQUALS(track_handle->sector_size, sector_size);
742
+ ASSERT_NUM_EQUALS(track_handle->sector_header_size, 0);
743
+ ASSERT_NUM_EQUALS(track_handle->raw_data_size, 2048);
744
+
745
+ close_track(&iterator, track_handle);
746
+ free(image);
747
+ }
748
+
749
+ static void test_absolute_sector_to_track_sector_cue_pregap()
750
+ {
751
+ const char cue[] =
752
+ "FILE \"game1.bin\" BINARY\n"/* file contains 500 sectors of data [1176000 bytes] */
753
+ " TRACK 01 MODE2/2352\n"
754
+ " INDEX 00 00:00:00\n" /* 150 pre-gap sectors */
755
+ " INDEX 01 00:02:00\n" /* 350 sectors of data */
756
+ "FILE \"game2.bin\" BINARY\n"
757
+ " TRACK 02 MODE2/2352\n"
758
+ " INDEX 00 00:00:00\n" /* 150 pre-gap sectors */
759
+ " INDEX 01 00:02:00\n";
760
+
761
+ rc_hash_cdrom_track_t* track_handle;
762
+ rc_hash_iterator_t iterator;
763
+
764
+ const size_t image_size = (size_t)60 * 200;
765
+ uint8_t* image = (uint8_t*)malloc(image_size);
766
+ ASSERT_PTR_NOT_NULL(image);
767
+
768
+ initialize_iterator(&iterator);
769
+
770
+ mock_file_text(0, "game.cue", cue);
771
+ mock_file(1, "game1.bin", NULL, (size_t)500 * 2352);
772
+ mock_file(2, "game2.bin", image, image_size);
773
+
774
+ track_handle = open_track(&iterator, "game.cue", 2);
775
+ ASSERT_PTR_NOT_NULL(track_handle);
776
+
777
+ ASSERT_PTR_NOT_NULL(track_handle->file_handle);
778
+ ASSERT_STR_EQUALS(get_mock_filename(track_handle->file_handle), "game2.bin");
779
+
780
+ /* pregap of second track starts at sector 500 */
781
+ ASSERT_NUM_EQUALS(track_handle->track_first_sector, 500);
782
+ ASSERT_NUM_EQUALS(track_handle->track_pregap_sectors, 150);
783
+
784
+ /* data for second track starts at sector 650 */
785
+ ASSERT_NUM_EQUALS(iterator.callbacks.cdreader.first_track_sector(track_handle), 650);
786
+
787
+ close_track(&iterator, track_handle);
788
+ free(image);
789
+ }
790
+
791
+ static void test_absolute_sector_to_track_sector_gdi()
792
+ {
793
+ rc_hash_cdrom_track_t* track_handle;
794
+ rc_hash_iterator_t iterator;
795
+ initialize_iterator(&iterator);
796
+
797
+ mock_file_text(0, "game.gdi", gdi_many_tracks);
798
+ mock_file(1, "track26.bin", NULL, 1234567);
799
+
800
+ track_handle = open_track(&iterator, "game.gdi", 26);
801
+ ASSERT_PTR_NOT_NULL(track_handle);
802
+
803
+ ASSERT_PTR_NOT_NULL(track_handle->file_handle);
804
+ ASSERT_STR_EQUALS(get_mock_filename(track_handle->file_handle), "track26.bin");
805
+ ASSERT_NUM_EQUALS(track_handle->track_first_sector, 548106);
806
+
807
+ ASSERT_NUM_EQUALS(iterator.callbacks.cdreader.first_track_sector(track_handle), 548106);
808
+
809
+ close_track(&iterator, track_handle);
810
+ }
811
+
812
+ static void test_read_sector()
813
+ {
814
+ char buffer[4096];
815
+ rc_hash_cdrom_track_t* track_handle;
816
+ rc_hash_iterator_t iterator;
817
+ const size_t image_size = (size_t)2352 * 32;
818
+ uint8_t* image = (uint8_t*)malloc(image_size);
819
+ int offset, i;
820
+ ASSERT_PTR_NOT_NULL(image);
821
+
822
+ initialize_iterator(&iterator);
823
+
824
+ mock_file_text(0, "game.cue", cue_single_track);
825
+ mock_file(1, "game.bin", image, image_size);
826
+
827
+ memset(image, 0, image_size);
828
+ memcpy(&image[2352 * 16], sync_pattern, sizeof(sync_pattern));
829
+ image[2352 * 16 + 12] = 0;
830
+ image[2352 * 16 + 13] = 2;
831
+ image[2352 * 16 + 14] = 0x16;
832
+ image[2352 * 16 + 15] = 2;
833
+
834
+ offset = 2352 * 1 + 16;
835
+ for (i = 0; i < 26; i++)
836
+ {
837
+ memset(&image[offset], i + 'A', 256);
838
+ offset += 256;
839
+
840
+ if ((i % 8) == 7)
841
+ offset += (2352 - 2048);
842
+ }
843
+
844
+ track_handle = open_track(&iterator, "game.cue", 1);
845
+ ASSERT_PTR_NOT_NULL(track_handle);
846
+
847
+ ASSERT_PTR_NOT_NULL(track_handle->file_handle);
848
+ ASSERT_STR_EQUALS(get_mock_filename(track_handle->file_handle), "game.bin");
849
+ ASSERT_NUM64_EQUALS(track_handle->track_pregap_sectors, 0);
850
+ ASSERT_NUM_EQUALS(track_handle->sector_size, 2352);
851
+ ASSERT_NUM_EQUALS(track_handle->sector_header_size, 16);
852
+
853
+ /* read across multiple sectors */
854
+ ASSERT_NUM_EQUALS(iterator.callbacks.cdreader.read_sector(track_handle, 1, buffer, sizeof(buffer)), 4096);
855
+
856
+ ASSERT_NUM_EQUALS(buffer[0], 'A');
857
+ ASSERT_NUM_EQUALS(buffer[255], 'A');
858
+ ASSERT_NUM_EQUALS(buffer[256], 'B');
859
+ ASSERT_NUM_EQUALS(buffer[2047], 'H');
860
+ ASSERT_NUM_EQUALS(buffer[2048], 'I');
861
+ ASSERT_NUM_EQUALS(buffer[4095], 'P');
862
+
863
+ /* read of partial sector */
864
+ ASSERT_NUM_EQUALS(iterator.callbacks.cdreader.read_sector(track_handle, 2, buffer, 10), 10);
865
+ ASSERT_NUM_EQUALS(buffer[0], 'I');
866
+ ASSERT_NUM_EQUALS(buffer[9], 'I');
867
+ ASSERT_NUM_EQUALS(buffer[10], 'A');
868
+
869
+ close_track(&iterator, track_handle);
870
+ free(image);
871
+ }
872
+
873
+ /* ========================================================================= */
874
+
875
+ void test_cdreader(void) {
876
+ TEST_SUITE_BEGIN();
877
+
878
+ init_mock_filereader();
879
+ rc_hash_init_default_cdreader();
880
+
881
+ TEST(test_open_cue_track_2);
882
+ TEST(test_open_cue_track_12);
883
+ TEST(test_open_cue_track_14);
884
+ TEST(test_open_cue_track_missing_bin);
885
+
886
+ TEST(test_open_gdi_track_3);
887
+ TEST(test_open_gdi_track_3_quoted);
888
+ TEST(test_open_gdi_track_3_extra_whitespace);
889
+ TEST(test_open_gdi_track_last);
890
+
891
+ TEST(test_open_cue_track_largest_data);
892
+ TEST(test_open_cue_track_largest_data_multiple_bin);
893
+ TEST(test_open_cue_track_largest_data_backwards_compatibility);
894
+ TEST(test_open_cue_track_largest_data_last_track);
895
+ TEST(test_open_cue_track_largest_data_index0s);
896
+ TEST(test_open_cue_track_largest_data_index2);
897
+ TEST(test_open_cue_track_largest_data_multiple_bins);
898
+ TEST(test_open_cue_track_largest_data_only_audio);
899
+
900
+ TEST(test_open_cue_track_first_data);
901
+
902
+ TEST_PARAMS1(test_determine_sector_size_sync, 2352);
903
+ TEST_PARAMS1(test_determine_sector_size_sync_primary_volume_descriptor, 2352);
904
+ TEST_PARAMS1(test_determine_sector_size_sync_primary_volume_descriptor_index0, 2352);
905
+
906
+ TEST_PARAMS1(test_determine_sector_size_sync, 2336);
907
+ TEST_PARAMS1(test_determine_sector_size_sync_primary_volume_descriptor, 2336);
908
+ TEST_PARAMS1(test_determine_sector_size_sync_primary_volume_descriptor_index0, 2336);
909
+
910
+ TEST(test_determine_sector_size_sync_2048);
911
+ TEST(test_determine_sector_size_sync_primary_volume_descriptor_2048);
912
+ TEST(test_determine_sector_size_sync_primary_volume_descriptor_index0_2048);
913
+
914
+ TEST(test_absolute_sector_to_track_sector_cue_pregap);
915
+ TEST(test_absolute_sector_to_track_sector_gdi);
916
+
917
+ TEST(test_read_sector);
918
+
919
+ TEST_SUITE_END();
920
+ }