runahead.c 52 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823824825826827828829830831832833834835836837838839840841842843844845846847848849850851852853854855856857858859860861862863864865866867868869870871872873874875876877878879880881882883884885886887888889890891892893894895896897898899900901902903904905906907908909910911912913914915916917918919920921922923924925926927928929930931932933934935936937938939940941942943944945946947948949950951952953954955956957958959960961962963964965966967968969970971972973974975976977978979980981982983984985986987988989990991992993994995996997998999100010011002100310041005100610071008100910101011101210131014101510161017101810191020102110221023102410251026102710281029103010311032103310341035103610371038103910401041104210431044104510461047104810491050105110521053105410551056105710581059106010611062106310641065106610671068106910701071107210731074107510761077107810791080108110821083108410851086108710881089109010911092109310941095109610971098109911001101110211031104110511061107110811091110111111121113111411151116111711181119112011211122112311241125112611271128112911301131113211331134113511361137113811391140114111421143114411451146114711481149115011511152115311541155115611571158115911601161116211631164116511661167116811691170117111721173117411751176117711781179118011811182118311841185118611871188118911901191119211931194119511961197119811991200120112021203120412051206120712081209121012111212121312141215121612171218121912201221122212231224122512261227122812291230123112321233123412351236123712381239124012411242124312441245124612471248124912501251125212531254125512561257125812591260126112621263126412651266126712681269127012711272127312741275127612771278127912801281128212831284128512861287128812891290129112921293129412951296129712981299130013011302130313041305130613071308130913101311131213131314131513161317131813191320132113221323132413251326132713281329133013311332133313341335133613371338133913401341134213431344134513461347134813491350135113521353135413551356135713581359136013611362136313641365136613671368136913701371137213731374137513761377137813791380138113821383138413851386138713881389139013911392139313941395139613971398139914001401140214031404140514061407140814091410141114121413141414151416141714181419142014211422142314241425142614271428142914301431143214331434143514361437143814391440144114421443144414451446144714481449145014511452145314541455145614571458145914601461146214631464146514661467146814691470147114721473147414751476147714781479148014811482148314841485148614871488148914901491149214931494149514961497149814991500150115021503150415051506150715081509151015111512151315141515151615171518151915201521152215231524152515261527152815291530153115321533153415351536153715381539154015411542154315441545154615471548154915501551155215531554155515561557155815591560156115621563156415651566156715681569157015711572157315741575157615771578157915801581158215831584158515861587158815891590159115921593159415951596159715981599160016011602160316041605160616071608160916101611161216131614161516161617161816191620162116221623162416251626162716281629163016311632163316341635163616371638163916401641164216431644164516461647164816491650165116521653165416551656165716581659166016611662166316641665166616671668166916701671167216731674167516761677167816791680168116821683168416851686168716881689169016911692169316941695169616971698169917001701170217031704170517061707170817091710
  1. /* RetroArch - A frontend for libretro.
  2. * Copyright (C) 2010-2014 - Hans-Kristian Arntzen
  3. * Copyright (C) 2011-2023 - Daniel De Matteis
  4. * Copyright (C) 2018-2023 - Dan Weiss
  5. * Copyright (C) 2022-2023 - Neil Fore
  6. *
  7. * RetroArch is free software: you can redistribute it and/or modify it under the terms
  8. * of the GNU General Public License as published by the Free Software Found-
  9. * ation, either version 3 of the License, or (at your option) any later version.
  10. *
  11. * RetroArch is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY;
  12. * without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR
  13. * PURPOSE. See the GNU General Public License for more details.
  14. *
  15. * You should have received a copy of the GNU General Public License along with RetroArch.
  16. * If not, see <http://www.gnu.org/licenses/>.
  17. */
  18. #include <stdint.h>
  19. #ifdef HAVE_CONFIG_H
  20. #include "config.h"
  21. #endif
  22. #include <encodings/utf.h>
  23. #include <string/stdstring.h>
  24. #include <streams/file_stream.h>
  25. #include <time/rtime.h>
  26. #include "content.h"
  27. #include "core.h"
  28. #include "dynamic.h"
  29. #include "driver.h"
  30. #include "audio/audio_driver.h"
  31. #include "gfx/video_driver.h"
  32. #include "paths.h"
  33. #include "runloop.h"
  34. #include "verbosity.h"
  35. static int16_t input_state_get_last(unsigned port,
  36. unsigned device, unsigned index, unsigned id)
  37. {
  38. int i;
  39. runloop_state_t *runloop_st = runloop_state_get_ptr();
  40. if (!runloop_st->input_state_list)
  41. return 0;
  42. /* find list item */
  43. for (i = 0; i < runloop_st->input_state_list->size; i++)
  44. {
  45. input_list_element *element =
  46. (input_list_element*)runloop_st->input_state_list->data[i];
  47. if ( (element->port == port) &&
  48. (element->device == device) &&
  49. (element->index == index))
  50. {
  51. if (id < element->state_size)
  52. return element->state[id];
  53. return 0;
  54. }
  55. }
  56. return 0;
  57. }
  58. static void free_retro_ctx_load_content_info(struct
  59. retro_ctx_load_content_info *dest)
  60. {
  61. if (!dest)
  62. return;
  63. string_list_free((struct string_list*)dest->content);
  64. if (dest->info)
  65. free(dest->info);
  66. dest->info = NULL;
  67. dest->content = NULL;
  68. }
  69. static struct retro_game_info* clone_retro_game_info(const
  70. struct retro_game_info *src)
  71. {
  72. struct retro_game_info *dest = (struct retro_game_info*)malloc(
  73. sizeof(struct retro_game_info));
  74. if (!dest)
  75. return NULL;
  76. /* content_file_init() guarantees that all
  77. * elements of the source retro_game_info
  78. * struct will persist for the lifetime of
  79. * the core. This means we do not have to
  80. * copy any data; pointer assignment is
  81. * sufficient */
  82. dest->path = src->path;
  83. dest->data = src->data;
  84. dest->size = src->size;
  85. dest->meta = src->meta;
  86. return dest;
  87. }
  88. static struct retro_ctx_load_content_info
  89. *clone_retro_ctx_load_content_info(
  90. const struct retro_ctx_load_content_info *src)
  91. {
  92. struct retro_ctx_load_content_info *dest = NULL;
  93. if (!src || src->special)
  94. return NULL; /* refuse to deal with the Special field */
  95. dest = (struct retro_ctx_load_content_info*)
  96. malloc(sizeof(*dest));
  97. if (!dest)
  98. return NULL;
  99. dest->info = NULL;
  100. dest->content = NULL;
  101. dest->special = NULL;
  102. if (src->info)
  103. dest->info = clone_retro_game_info(src->info);
  104. if (src->content)
  105. dest->content = string_list_clone(src->content);
  106. return dest;
  107. }
  108. void runahead_set_load_content_info(void *data,
  109. const retro_ctx_load_content_info_t *ctx)
  110. {
  111. runloop_state_t *runloop_st = (runloop_state_t*)data;
  112. free_retro_ctx_load_content_info(runloop_st->load_content_info);
  113. free(runloop_st->load_content_info);
  114. runloop_st->load_content_info = clone_retro_ctx_load_content_info(ctx);
  115. }
  116. /* RUNAHEAD - SECONDARY CORE */
  117. #if defined(HAVE_DYNAMIC) || defined(HAVE_DYLIB)
  118. static void strcat_alloc(char **dst, const char *s)
  119. {
  120. size_t len1;
  121. char *src = *dst;
  122. if (!src)
  123. {
  124. if (s)
  125. {
  126. size_t len = strlen(s);
  127. if (len != 0)
  128. {
  129. char *_dst= (char*)malloc(len + 1);
  130. strcpy_literal(_dst, s);
  131. src = _dst;
  132. }
  133. else
  134. src = NULL;
  135. }
  136. else
  137. src = (char*)calloc(1,1);
  138. *dst = src;
  139. return;
  140. }
  141. if (!s)
  142. return;
  143. len1 = strlen(src);
  144. if (!(src = (char*)realloc(src, len1 + strlen(s) + 1)))
  145. return;
  146. *dst = src;
  147. strcpy_literal(src + len1, s);
  148. }
  149. void runahead_secondary_core_destroy(void *data)
  150. {
  151. runloop_state_t *runloop_st = (runloop_state_t*)data;
  152. if (!runloop_st->secondary_lib_handle)
  153. return;
  154. /* unload game from core */
  155. if (runloop_st->secondary_core.retro_unload_game)
  156. runloop_st->secondary_core.retro_unload_game();
  157. runloop_st->core_poll_type_override = POLL_TYPE_OVERRIDE_DONTCARE;
  158. /* deinit */
  159. if (runloop_st->secondary_core.retro_deinit)
  160. runloop_st->secondary_core.retro_deinit();
  161. memset(&runloop_st->secondary_core, 0, sizeof(struct retro_core_t));
  162. dylib_close(runloop_st->secondary_lib_handle);
  163. runloop_st->secondary_lib_handle = NULL;
  164. filestream_delete(runloop_st->secondary_library_path);
  165. if (runloop_st->secondary_library_path)
  166. free(runloop_st->secondary_library_path);
  167. runloop_st->secondary_library_path = NULL;
  168. }
  169. static char *get_tmpdir_alloc(const char *override_dir)
  170. {
  171. const char *src = NULL;
  172. char *path = NULL;
  173. #ifdef _WIN32
  174. #ifdef LEGACY_WIN32
  175. DWORD plen = GetTempPath(0, NULL) + 1;
  176. if (!(path = (char*)malloc(plen * sizeof(char))))
  177. return NULL;
  178. path[plen - 1] = 0;
  179. GetTempPath(plen, path);
  180. #else
  181. DWORD plen = GetTempPathW(0, NULL) + 1;
  182. wchar_t *wide_str = (wchar_t*)malloc(plen * sizeof(wchar_t));
  183. if (!wide_str)
  184. return NULL;
  185. wide_str[plen - 1] = 0;
  186. GetTempPathW(plen, wide_str);
  187. path = utf16_to_utf8_string_alloc(wide_str);
  188. free(wide_str);
  189. #endif
  190. #else
  191. #if defined ANDROID
  192. src = override_dir;
  193. #else
  194. {
  195. char *tmpdir = getenv("TMPDIR");
  196. if (tmpdir)
  197. src = tmpdir;
  198. else
  199. src = "/tmp";
  200. }
  201. #endif
  202. if (src)
  203. {
  204. size_t len = strlen(src);
  205. if (len != 0)
  206. {
  207. char *dst = (char*)malloc(len + 1);
  208. strcpy_literal(dst, src);
  209. path = dst;
  210. }
  211. }
  212. else
  213. path = (char*)calloc(1,1);
  214. #endif
  215. return path;
  216. }
  217. static bool write_file_with_random_name(char **temp_dll_path,
  218. const char *tmp_path, const void* data, ssize_t dataSize)
  219. {
  220. int i;
  221. size_t ext_len;
  222. char number_buf[32];
  223. bool okay = false;
  224. const char *prefix = "tmp";
  225. char *ext = NULL;
  226. time_t time_value = time(NULL);
  227. unsigned _number_value = (unsigned)time_value;
  228. const char *src = path_get_extension(*temp_dll_path);
  229. if (src)
  230. {
  231. size_t len = strlen(src);
  232. if (len != 0)
  233. {
  234. char *dst = (char*)malloc(len + 1);
  235. strcpy_literal(dst, src);
  236. ext = dst;
  237. }
  238. }
  239. else
  240. ext = (char*)calloc(1,1);
  241. ext_len = strlen(ext);
  242. if (ext_len > 0)
  243. {
  244. strcat_alloc(&ext, ".");
  245. memmove(ext + 1, ext, ext_len);
  246. ext[0] = '.';
  247. ext_len++;
  248. }
  249. /* Try up to 30 'random' filenames before giving up */
  250. for (i = 0; i < 30; i++)
  251. {
  252. int number_value = _number_value * 214013 + 2531011;
  253. int number = (number_value >> 14) % 100000;
  254. snprintf(number_buf, sizeof(number_buf), "%05d", number);
  255. if (*temp_dll_path)
  256. free(*temp_dll_path);
  257. *temp_dll_path = NULL;
  258. strcat_alloc(temp_dll_path, tmp_path);
  259. strcat_alloc(temp_dll_path, PATH_DEFAULT_SLASH());
  260. strcat_alloc(temp_dll_path, prefix);
  261. strcat_alloc(temp_dll_path, number_buf);
  262. strcat_alloc(temp_dll_path, ext);
  263. if (filestream_write_file(*temp_dll_path, data, dataSize))
  264. {
  265. okay = true;
  266. break;
  267. }
  268. }
  269. if (ext)
  270. free(ext);
  271. ext = NULL;
  272. return okay;
  273. }
  274. static char *copy_core_to_temp_file(
  275. const char *core_path,
  276. const char *dir_libretro)
  277. {
  278. char tmp_path[PATH_MAX_LENGTH];
  279. bool failed = false;
  280. char *tmpdir = NULL;
  281. char *tmp_dll_path = NULL;
  282. void *dll_file_data = NULL;
  283. int64_t dll_file_size = 0;
  284. const char *core_base_name = path_basename_nocompression(core_path);
  285. if (strlen(core_base_name) == 0)
  286. return NULL;
  287. if (!(tmpdir = get_tmpdir_alloc(dir_libretro)))
  288. return NULL;
  289. fill_pathname_join_special(tmp_path,
  290. tmpdir, "retroarch_temp",
  291. sizeof(tmp_path));
  292. if (!path_mkdir(tmp_path))
  293. {
  294. failed = true;
  295. goto end;
  296. }
  297. if (!filestream_read_file(core_path, &dll_file_data, &dll_file_size))
  298. {
  299. failed = true;
  300. goto end;
  301. }
  302. strcat_alloc(&tmp_dll_path, tmp_path);
  303. strcat_alloc(&tmp_dll_path, PATH_DEFAULT_SLASH());
  304. strcat_alloc(&tmp_dll_path, core_base_name);
  305. if (!filestream_write_file(tmp_dll_path, dll_file_data, dll_file_size))
  306. {
  307. /* try other file names */
  308. if (!write_file_with_random_name(&tmp_dll_path,
  309. tmp_path, dll_file_data, dll_file_size))
  310. failed = true;
  311. }
  312. end:
  313. if (tmpdir)
  314. free(tmpdir);
  315. if (dll_file_data)
  316. free(dll_file_data);
  317. tmpdir = NULL;
  318. dll_file_data = NULL;
  319. if (!failed)
  320. return tmp_dll_path;
  321. if (tmp_dll_path)
  322. free(tmp_dll_path);
  323. tmp_dll_path = NULL;
  324. return NULL;
  325. }
  326. static bool runloop_environment_secondary_core_hook(
  327. unsigned cmd, void *data)
  328. {
  329. runloop_state_t *runloop_st = runloop_state_get_ptr();
  330. bool result = runloop_environment_cb(cmd, data);
  331. if (runloop_st->flags & RUNLOOP_FLAG_HAS_VARIABLE_UPDATE)
  332. {
  333. if (cmd == RETRO_ENVIRONMENT_GET_VARIABLE_UPDATE)
  334. {
  335. bool *bool_p = (bool*)data;
  336. *bool_p = true;
  337. runloop_st->flags &= ~RUNLOOP_FLAG_HAS_VARIABLE_UPDATE;
  338. return true;
  339. }
  340. else if (cmd == RETRO_ENVIRONMENT_GET_VARIABLE)
  341. runloop_st->flags &= ~RUNLOOP_FLAG_HAS_VARIABLE_UPDATE;
  342. }
  343. return result;
  344. }
  345. void runahead_clear_controller_port_map(void *data)
  346. {
  347. int port;
  348. runloop_state_t *runloop_st = (runloop_state_t*)data;
  349. for (port = 0; port < MAX_USERS; port++)
  350. runloop_st->port_map[port] = -1;
  351. }
  352. static bool secondary_core_create(runloop_state_t *runloop_st,
  353. settings_t *settings)
  354. {
  355. const enum rarch_core_type
  356. last_core_type = runloop_st->last_core_type;
  357. rarch_system_info_t *info = &runloop_st->system;
  358. unsigned num_active_users = settings->uints.input_max_users;
  359. uint8_t flags = content_get_flags();
  360. if ( (last_core_type != CORE_TYPE_PLAIN)
  361. || (!runloop_st->load_content_info)
  362. || ( runloop_st->load_content_info->special))
  363. return false;
  364. if (runloop_st->secondary_library_path)
  365. free(runloop_st->secondary_library_path);
  366. runloop_st->secondary_library_path = NULL;
  367. runloop_st->secondary_library_path = copy_core_to_temp_file(
  368. path_get(RARCH_PATH_CORE),
  369. settings->paths.directory_libretro);
  370. if (!runloop_st->secondary_library_path)
  371. return false;
  372. /* Load Core */
  373. if (!runloop_init_libretro_symbols(runloop_st,
  374. CORE_TYPE_PLAIN, &runloop_st->secondary_core,
  375. runloop_st->secondary_library_path,
  376. &runloop_st->secondary_lib_handle))
  377. return false;
  378. runloop_st->secondary_core.flags |= RETRO_CORE_FLAG_SYMBOLS_INITED;
  379. runloop_st->secondary_core.retro_set_environment(
  380. runloop_environment_secondary_core_hook);
  381. runloop_st->flags |= RUNLOOP_FLAG_HAS_VARIABLE_UPDATE;
  382. runloop_st->secondary_core.retro_init();
  383. if (flags & CONTENT_ST_FLAG_IS_INITED)
  384. runloop_st->secondary_core.flags |= RETRO_CORE_FLAG_INITED;
  385. else
  386. runloop_st->secondary_core.flags &= ~RETRO_CORE_FLAG_INITED;
  387. /* Load Content */
  388. /* disabled due to crashes */
  389. if ( (!runloop_st->load_content_info)
  390. || (runloop_st->load_content_info->special))
  391. return false;
  392. if ( ( runloop_st->load_content_info->content->size > 0)
  393. && runloop_st->load_content_info->content->elems[0].data)
  394. {
  395. if (!runloop_st->secondary_core.retro_load_game(
  396. runloop_st->load_content_info->info))
  397. {
  398. runloop_st->secondary_core.flags &= ~RETRO_CORE_FLAG_GAME_LOADED;
  399. goto error;
  400. }
  401. runloop_st->secondary_core.flags |= RETRO_CORE_FLAG_GAME_LOADED;
  402. }
  403. else if (flags & CONTENT_ST_FLAG_CORE_DOES_NOT_NEED_CONTENT)
  404. {
  405. if (!runloop_st->secondary_core.retro_load_game(NULL))
  406. {
  407. runloop_st->secondary_core.flags &= ~RETRO_CORE_FLAG_GAME_LOADED;
  408. goto error;
  409. }
  410. runloop_st->secondary_core.flags |= RETRO_CORE_FLAG_GAME_LOADED;
  411. }
  412. else
  413. runloop_st->secondary_core.flags &= ~RETRO_CORE_FLAG_GAME_LOADED;
  414. if (!(runloop_st->secondary_core.flags & RETRO_CORE_FLAG_INITED))
  415. goto error;
  416. core_set_default_callbacks(&runloop_st->secondary_callbacks);
  417. runloop_st->secondary_core.retro_set_video_refresh(
  418. runloop_st->secondary_callbacks.frame_cb);
  419. runloop_st->secondary_core.retro_set_audio_sample(
  420. runloop_st->secondary_callbacks.sample_cb);
  421. runloop_st->secondary_core.retro_set_audio_sample_batch(
  422. runloop_st->secondary_callbacks.sample_batch_cb);
  423. runloop_st->secondary_core.retro_set_input_state(
  424. runloop_st->secondary_callbacks.state_cb);
  425. runloop_st->secondary_core.retro_set_input_poll(
  426. runloop_st->secondary_callbacks.poll_cb);
  427. if (info)
  428. {
  429. int port;
  430. for (port = 0; port < MAX_USERS; port++)
  431. {
  432. if (port < (int)info->ports.size)
  433. {
  434. unsigned device = (port < (int)num_active_users) ?
  435. runloop_st->port_map[port] : RETRO_DEVICE_NONE;
  436. runloop_st->secondary_core.retro_set_controller_port_device(
  437. port, device);
  438. }
  439. }
  440. }
  441. #if defined(HAVE_DYNAMIC) || defined(HAVE_DYLIB)
  442. runahead_clear_controller_port_map(runloop_st);
  443. #endif
  444. return true;
  445. error:
  446. runahead_secondary_core_destroy(runloop_st);
  447. return false;
  448. }
  449. #if defined(HAVE_DYNAMIC) || defined(HAVE_DYLIB)
  450. bool secondary_core_ensure_exists(void *data, settings_t *settings)
  451. {
  452. runloop_state_t *runloop_st = (runloop_state_t*)data;
  453. if (!runloop_st->secondary_lib_handle)
  454. if (!secondary_core_create(runloop_st, settings))
  455. return false;
  456. return true;
  457. }
  458. #endif
  459. #if defined(HAVE_DYNAMIC)
  460. static bool secondary_core_deserialize(runloop_state_t *runloop_st,
  461. settings_t *settings,
  462. const void *data, size_t size)
  463. {
  464. bool ret = false;
  465. if (secondary_core_ensure_exists(runloop_st, settings))
  466. {
  467. runloop_st->flags |= RUNLOOP_FLAG_REQUEST_SPECIAL_SAVESTATE;
  468. ret = runloop_st->secondary_core.retro_unserialize(data, size);
  469. runloop_st->flags &= ~RUNLOOP_FLAG_REQUEST_SPECIAL_SAVESTATE;
  470. }
  471. else
  472. runahead_secondary_core_destroy(runloop_st);
  473. return ret;
  474. }
  475. #endif
  476. static void secondary_core_input_poll_null(void) { }
  477. static bool secondary_core_run_use_last_input(runloop_state_t *runloop_st)
  478. {
  479. retro_input_poll_t old_poll_function;
  480. retro_input_state_t old_input_function;
  481. if (!secondary_core_ensure_exists(runloop_st, config_get_ptr()))
  482. {
  483. runahead_secondary_core_destroy(runloop_st);
  484. return false;
  485. }
  486. old_poll_function = runloop_st->secondary_callbacks.poll_cb;
  487. old_input_function = runloop_st->secondary_callbacks.state_cb;
  488. runloop_st->secondary_callbacks.poll_cb = secondary_core_input_poll_null;
  489. runloop_st->secondary_callbacks.state_cb = input_state_get_last;
  490. runloop_st->secondary_core.retro_set_input_poll(
  491. runloop_st->secondary_callbacks.poll_cb);
  492. runloop_st->secondary_core.retro_set_input_state(
  493. runloop_st->secondary_callbacks.state_cb);
  494. runloop_st->secondary_core.retro_run();
  495. runloop_st->secondary_callbacks.poll_cb = old_poll_function;
  496. runloop_st->secondary_callbacks.state_cb = old_input_function;
  497. runloop_st->secondary_core.retro_set_input_poll(
  498. runloop_st->secondary_callbacks.poll_cb);
  499. runloop_st->secondary_core.retro_set_input_state(
  500. runloop_st->secondary_callbacks.state_cb);
  501. return true;
  502. }
  503. void runahead_remember_controller_port_device(void *data,
  504. long port, long device)
  505. {
  506. runloop_state_t *runloop_st = (runloop_state_t*)data;
  507. if (port >= 0 && port < MAX_USERS)
  508. runloop_st->port_map[port] = (int)device;
  509. if ( runloop_st->secondary_lib_handle
  510. && runloop_st->secondary_core.retro_set_controller_port_device)
  511. runloop_st->secondary_core.retro_set_controller_port_device((unsigned)port, (unsigned)device);
  512. }
  513. #else
  514. void runahead_secondary_core_destroy(void *data) { }
  515. #endif
  516. static void mylist_resize(my_list *list,
  517. int new_size, bool run_constructor)
  518. {
  519. int i;
  520. int new_capacity;
  521. int old_size;
  522. void *element = NULL;
  523. if (new_size < 0)
  524. new_size = 0;
  525. new_capacity = new_size;
  526. old_size = list->size;
  527. if (new_size == old_size)
  528. return;
  529. if (new_size > list->capacity)
  530. {
  531. if (new_capacity < list->capacity * 2)
  532. new_capacity = list->capacity * 2;
  533. /* try to realloc */
  534. list->data = (void**)realloc(
  535. (void*)list->data, new_capacity * sizeof(void*));
  536. for (i = list->capacity; i < new_capacity; i++)
  537. list->data[i] = NULL;
  538. list->capacity = new_capacity;
  539. }
  540. if (new_size <= list->size)
  541. {
  542. for (i = new_size; i < list->size; i++)
  543. {
  544. element = list->data[i];
  545. if (element)
  546. {
  547. list->destructor(element);
  548. list->data[i] = NULL;
  549. }
  550. }
  551. }
  552. else
  553. {
  554. for (i = list->size; i < new_size; i++)
  555. {
  556. list->data[i] = NULL;
  557. if (run_constructor)
  558. list->data[i] = list->constructor();
  559. }
  560. }
  561. list->size = new_size;
  562. }
  563. static void *mylist_add_element(my_list *list)
  564. {
  565. int old_size = list->size;
  566. if (list)
  567. mylist_resize(list, old_size + 1, true);
  568. return list->data[old_size];
  569. }
  570. static void mylist_destroy(my_list **list_p)
  571. {
  572. my_list *list = NULL;
  573. if (!list_p)
  574. return;
  575. list = *list_p;
  576. if (list)
  577. {
  578. mylist_resize(list, 0, false);
  579. free(list->data);
  580. free(list);
  581. *list_p = NULL;
  582. }
  583. }
  584. static void mylist_create(my_list **list_p, int initial_capacity,
  585. constructor_t constructor, destructor_t destructor)
  586. {
  587. my_list *list = NULL;
  588. if (!list_p)
  589. return;
  590. list = *list_p;
  591. if (list)
  592. mylist_destroy(list_p);
  593. list = (my_list*)malloc(sizeof(my_list));
  594. *list_p = list;
  595. list->size = 0;
  596. list->constructor = constructor;
  597. list->destructor = destructor;
  598. list->data = (void**)calloc(initial_capacity, sizeof(void*));
  599. list->capacity = initial_capacity;
  600. }
  601. static void *input_list_element_constructor(void)
  602. {
  603. void *ptr = malloc(sizeof(input_list_element));
  604. input_list_element *element = (input_list_element*)ptr;
  605. element->port = 0;
  606. element->device = 0;
  607. element->index = 0;
  608. element->state = (int16_t*)calloc(NAME_MAX_LENGTH,
  609. sizeof(int16_t));
  610. element->state_size = NAME_MAX_LENGTH;
  611. return ptr;
  612. }
  613. static void input_list_element_realloc(
  614. input_list_element *element,
  615. unsigned int new_size)
  616. {
  617. if (new_size > element->state_size)
  618. {
  619. element->state = (int16_t*)realloc(element->state,
  620. new_size * sizeof(int16_t));
  621. memset(&element->state[element->state_size], 0,
  622. (new_size - element->state_size) * sizeof(int16_t));
  623. element->state_size = new_size;
  624. }
  625. }
  626. static void input_list_element_expand(
  627. input_list_element *element, unsigned int new_index)
  628. {
  629. unsigned int new_size = element->state_size;
  630. if (new_size == 0)
  631. new_size = 32;
  632. while (new_index >= new_size)
  633. new_size *= 2;
  634. input_list_element_realloc(element, new_size);
  635. }
  636. static void input_list_element_destructor(void* element_ptr)
  637. {
  638. input_list_element *element = (input_list_element*)element_ptr;
  639. if (!element)
  640. return;
  641. free(element->state);
  642. free(element_ptr);
  643. }
  644. static void runahead_input_state_set_last(
  645. runloop_state_t *runloop_st,
  646. unsigned port, unsigned device,
  647. unsigned index, unsigned id, int16_t value)
  648. {
  649. unsigned i;
  650. input_list_element *element = NULL;
  651. if (!runloop_st->input_state_list)
  652. mylist_create(&runloop_st->input_state_list, 16,
  653. input_list_element_constructor,
  654. input_list_element_destructor);
  655. /* Find list item */
  656. for (i = 0; i < (unsigned)runloop_st->input_state_list->size; i++)
  657. {
  658. element = (input_list_element*)runloop_st->input_state_list->data[i];
  659. if ( (element->port == port) &&
  660. (element->device == device) &&
  661. (element->index == index)
  662. )
  663. {
  664. if (id >= element->state_size)
  665. input_list_element_expand(element, id);
  666. element->state[id] = value;
  667. return;
  668. }
  669. }
  670. element = NULL;
  671. if (runloop_st->input_state_list)
  672. element = (input_list_element*)
  673. mylist_add_element(runloop_st->input_state_list);
  674. if (element)
  675. {
  676. element->port = port;
  677. element->device = device;
  678. element->index = index;
  679. if (id >= element->state_size)
  680. input_list_element_expand(element, id);
  681. element->state[id] = value;
  682. }
  683. }
  684. static int16_t runahead_input_state_with_logging(unsigned port,
  685. unsigned device, unsigned index, unsigned id)
  686. {
  687. runloop_state_t *runloop_st = runloop_state_get_ptr();
  688. if (runloop_st->input_state_callback_original)
  689. {
  690. int16_t result =
  691. runloop_st->input_state_callback_original(
  692. port, device, index, id);
  693. int16_t last_input =
  694. input_state_get_last(port, device, index, id);
  695. if (result != last_input)
  696. runloop_st->flags |= RUNLOOP_FLAG_INPUT_IS_DIRTY;
  697. /*arbitrary limit of up to 65536 elements in state array*/
  698. if (id < 65536)
  699. runahead_input_state_set_last(runloop_st, port, device, index, id, result);
  700. return result;
  701. }
  702. return 0;
  703. }
  704. static void runahead_reset_hook(void)
  705. {
  706. runloop_state_t *runloop_st = runloop_state_get_ptr();
  707. runloop_st->flags |= RUNLOOP_FLAG_INPUT_IS_DIRTY;
  708. if (runloop_st->retro_reset_callback_original)
  709. runloop_st->retro_reset_callback_original();
  710. }
  711. static bool runahead_unserialize_hook(const void *buf, size_t size)
  712. {
  713. runloop_state_t *runloop_st = runloop_state_get_ptr();
  714. runloop_st->flags |= RUNLOOP_FLAG_INPUT_IS_DIRTY;
  715. if (runloop_st->retro_unserialize_callback_original)
  716. return runloop_st->retro_unserialize_callback_original(buf, size);
  717. return false;
  718. }
  719. static void runahead_add_input_state_hook(runloop_state_t *runloop_st)
  720. {
  721. struct retro_callbacks *cbs = &runloop_st->retro_ctx;
  722. if (!runloop_st->input_state_callback_original)
  723. {
  724. runloop_st->input_state_callback_original = cbs->state_cb;
  725. cbs->state_cb = runahead_input_state_with_logging;
  726. runloop_st->current_core.retro_set_input_state(cbs->state_cb);
  727. }
  728. if (!runloop_st->retro_reset_callback_original)
  729. {
  730. runloop_st->retro_reset_callback_original
  731. = runloop_st->current_core.retro_reset;
  732. runloop_st->current_core.retro_reset = runahead_reset_hook;
  733. }
  734. if (!runloop_st->retro_unserialize_callback_original)
  735. {
  736. runloop_st->retro_unserialize_callback_original = runloop_st->current_core.retro_unserialize;
  737. runloop_st->current_core.retro_unserialize = runahead_unserialize_hook;
  738. }
  739. }
  740. static void runahead_remove_input_state_hook(runloop_state_t *runloop_st)
  741. {
  742. struct retro_callbacks *cbs = &runloop_st->retro_ctx;
  743. if (runloop_st->input_state_callback_original)
  744. {
  745. cbs->state_cb =
  746. runloop_st->input_state_callback_original;
  747. runloop_st->current_core.retro_set_input_state(cbs->state_cb);
  748. runloop_st->input_state_callback_original = NULL;
  749. mylist_destroy(&runloop_st->input_state_list);
  750. }
  751. if (runloop_st->retro_reset_callback_original)
  752. {
  753. runloop_st->current_core.retro_reset =
  754. runloop_st->retro_reset_callback_original;
  755. runloop_st->retro_reset_callback_original = NULL;
  756. }
  757. if (runloop_st->retro_unserialize_callback_original)
  758. {
  759. runloop_st->current_core.retro_unserialize =
  760. runloop_st->retro_unserialize_callback_original;
  761. runloop_st->retro_unserialize_callback_original = NULL;
  762. }
  763. }
  764. static void *runahead_save_state_alloc(void)
  765. {
  766. runloop_state_t *runloop_st = runloop_state_get_ptr();
  767. retro_ctx_serialize_info_t *savestate = (retro_ctx_serialize_info_t*)
  768. malloc(sizeof(retro_ctx_serialize_info_t));
  769. if (!savestate)
  770. return NULL;
  771. savestate->data = NULL;
  772. savestate->data_const = NULL;
  773. savestate->size = 0;
  774. if ( (runloop_st->runahead_save_state_size > 0)
  775. && (runloop_st->flags & RUNLOOP_FLAG_RUNAHEAD_SAVE_STATE_SIZE_KNOWN))
  776. {
  777. savestate->data = malloc(runloop_st->runahead_save_state_size);
  778. savestate->data_const = savestate->data;
  779. savestate->size = runloop_st->runahead_save_state_size;
  780. }
  781. return savestate;
  782. }
  783. static void runahead_save_state_free(void *data)
  784. {
  785. retro_ctx_serialize_info_t *savestate = (retro_ctx_serialize_info_t*)data;
  786. if (!savestate)
  787. return;
  788. free(savestate->data);
  789. free(savestate);
  790. }
  791. static void runahead_save_state_list_init(
  792. runloop_state_t *runloop_st,
  793. size_t save_state_size)
  794. {
  795. runloop_st->runahead_save_state_size = save_state_size;
  796. runloop_st->flags |= RUNLOOP_FLAG_RUNAHEAD_SAVE_STATE_SIZE_KNOWN;
  797. mylist_create(&runloop_st->runahead_save_state_list, 16,
  798. runahead_save_state_alloc, runahead_save_state_free);
  799. }
  800. /* Hooks - Hooks to cleanup, and add dirty input hooks */
  801. static void runahead_remove_hooks(runloop_state_t *runloop_st)
  802. {
  803. if (runloop_st->original_retro_deinit)
  804. {
  805. runloop_st->current_core.retro_deinit =
  806. runloop_st->original_retro_deinit;
  807. runloop_st->original_retro_deinit = NULL;
  808. }
  809. if (runloop_st->original_retro_unload)
  810. {
  811. runloop_st->current_core.retro_unload_game =
  812. runloop_st->original_retro_unload;
  813. runloop_st->original_retro_unload = NULL;
  814. }
  815. runahead_remove_input_state_hook(runloop_st);
  816. }
  817. static void runahead_destroy(runloop_state_t *runloop_st)
  818. {
  819. mylist_destroy(&runloop_st->runahead_save_state_list);
  820. runahead_remove_hooks(runloop_st);
  821. runahead_clear_variables(runloop_st);
  822. }
  823. static void runahead_unload_hook(void)
  824. {
  825. runloop_state_t *runloop_st = runloop_state_get_ptr();
  826. runahead_remove_hooks(runloop_st);
  827. runahead_destroy(runloop_st);
  828. runahead_secondary_core_destroy(runloop_st);
  829. if (runloop_st->current_core.retro_unload_game)
  830. runloop_st->current_core.retro_unload_game();
  831. runloop_st->core_poll_type_override = POLL_TYPE_OVERRIDE_DONTCARE;
  832. }
  833. static void runahead_deinit_hook(void)
  834. {
  835. runloop_state_t *runloop_st = runloop_state_get_ptr();
  836. runahead_remove_hooks(runloop_st);
  837. runahead_destroy(runloop_st);
  838. runahead_secondary_core_destroy(runloop_st);
  839. if (runloop_st->current_core.retro_deinit)
  840. runloop_st->current_core.retro_deinit();
  841. }
  842. static void runahead_add_hooks(runloop_state_t *runloop_st)
  843. {
  844. if (!runloop_st->original_retro_deinit)
  845. {
  846. runloop_st->original_retro_deinit =
  847. runloop_st->current_core.retro_deinit;
  848. runloop_st->current_core.retro_deinit = runahead_deinit_hook;
  849. }
  850. if (!runloop_st->original_retro_unload)
  851. {
  852. runloop_st->original_retro_unload = runloop_st->current_core.retro_unload_game;
  853. runloop_st->current_core.retro_unload_game = runahead_unload_hook;
  854. }
  855. runahead_add_input_state_hook(runloop_st);
  856. }
  857. /* Runahead Code */
  858. static void runahead_error(runloop_state_t *runloop_st)
  859. {
  860. runloop_st->flags &= ~RUNLOOP_FLAG_RUNAHEAD_AVAILABLE;
  861. mylist_destroy(&runloop_st->runahead_save_state_list);
  862. runahead_remove_hooks(runloop_st);
  863. runloop_st->runahead_save_state_size = 0;
  864. runloop_st->flags |= RUNLOOP_FLAG_RUNAHEAD_SAVE_STATE_SIZE_KNOWN;
  865. }
  866. static bool runahead_create(runloop_state_t *runloop_st)
  867. {
  868. /* get savestate size and allocate buffer */
  869. retro_ctx_size_info_t info;
  870. video_driver_state_t *video_st = video_state_get_ptr();
  871. core_serialize_size_special(&info);
  872. runahead_save_state_list_init(runloop_st, info.size);
  873. if (video_st->flags & VIDEO_FLAG_ACTIVE)
  874. video_st->flags |= VIDEO_FLAG_RUNAHEAD_IS_ACTIVE;
  875. else
  876. video_st->flags &= ~VIDEO_FLAG_RUNAHEAD_IS_ACTIVE;
  877. if ( (runloop_st->runahead_save_state_size == 0)
  878. || !(runloop_st->flags & RUNLOOP_FLAG_RUNAHEAD_SAVE_STATE_SIZE_KNOWN))
  879. {
  880. runahead_error(runloop_st);
  881. return false;
  882. }
  883. runahead_add_hooks(runloop_st);
  884. runloop_st->flags |= RUNLOOP_FLAG_RUNAHEAD_FORCE_INPUT_DIRTY;
  885. if (runloop_st->runahead_save_state_list)
  886. mylist_resize(runloop_st->runahead_save_state_list, 1, true);
  887. return true;
  888. }
  889. static bool runahead_save_state(runloop_state_t *runloop_st)
  890. {
  891. retro_ctx_serialize_info_t *serialize_info;
  892. if (!runloop_st->runahead_save_state_list)
  893. return false;
  894. serialize_info =
  895. (retro_ctx_serialize_info_t*)runloop_st->runahead_save_state_list->data[0];
  896. if (core_serialize_special(serialize_info))
  897. return true;
  898. runahead_error(runloop_st);
  899. return false;
  900. }
  901. static bool runahead_load_state(runloop_state_t *runloop_st)
  902. {
  903. retro_ctx_serialize_info_t *serialize_info =
  904. (retro_ctx_serialize_info_t*)
  905. runloop_st->runahead_save_state_list->data[0];
  906. bool last_dirty = runloop_st->flags & RUNLOOP_FLAG_INPUT_IS_DIRTY;
  907. bool ret = core_unserialize_special(serialize_info);
  908. if (last_dirty)
  909. runloop_st->flags |= RUNLOOP_FLAG_INPUT_IS_DIRTY;
  910. else
  911. runloop_st->flags &= ~RUNLOOP_FLAG_INPUT_IS_DIRTY;
  912. if (!ret)
  913. runahead_error(runloop_st);
  914. return ret;
  915. }
  916. #if HAVE_DYNAMIC
  917. static bool runahead_load_state_secondary(runloop_state_t *runloop_st, settings_t *settings)
  918. {
  919. retro_ctx_serialize_info_t *serialize_info =
  920. (retro_ctx_serialize_info_t*)runloop_st->runahead_save_state_list->data[0];
  921. if (!secondary_core_deserialize(runloop_st,
  922. settings, serialize_info->data_const,
  923. serialize_info->size))
  924. {
  925. runloop_st->flags &= ~RUNLOOP_FLAG_RUNAHEAD_SECONDARY_CORE_AVAILABLE;
  926. runahead_error(runloop_st);
  927. return false;
  928. }
  929. return true;
  930. }
  931. #endif
  932. static void runahead_core_run_use_last_input(runloop_state_t *runloop_st)
  933. {
  934. struct retro_callbacks *cbs = &runloop_st->retro_ctx;
  935. retro_input_poll_t old_poll_function = cbs->poll_cb;
  936. retro_input_state_t old_input_function = cbs->state_cb;
  937. cbs->poll_cb = retro_input_poll_null;
  938. cbs->state_cb = input_state_get_last;
  939. runloop_st->current_core.retro_set_input_poll(cbs->poll_cb);
  940. runloop_st->current_core.retro_set_input_state(cbs->state_cb);
  941. runloop_st->current_core.retro_run();
  942. cbs->poll_cb = old_poll_function;
  943. cbs->state_cb = old_input_function;
  944. runloop_st->current_core.retro_set_input_poll(cbs->poll_cb);
  945. runloop_st->current_core.retro_set_input_state(cbs->state_cb);
  946. }
  947. void runahead_run(void *data,
  948. int runahead_count,
  949. bool runahead_hide_warnings,
  950. bool use_secondary)
  951. {
  952. runloop_state_t *runloop_st = (runloop_state_t*)data;
  953. int frame_number = 0;
  954. bool last_frame = false;
  955. bool suspended_frame = false;
  956. #if defined(HAVE_DYNAMIC) || defined(HAVE_DYLIB)
  957. const bool have_dynamic = true;
  958. settings_t *settings = config_get_ptr();
  959. #else
  960. const bool have_dynamic = false;
  961. #endif
  962. video_driver_state_t
  963. *video_st = video_state_get_ptr();
  964. uint64_t frame_count = video_st->frame_count;
  965. audio_driver_state_t
  966. *audio_st = audio_state_get_ptr();
  967. if ( runahead_count <= 0
  968. || !(runloop_st->flags & RUNLOOP_FLAG_RUNAHEAD_AVAILABLE))
  969. goto force_input_dirty;
  970. if (!(runloop_st->flags & RUNLOOP_FLAG_RUNAHEAD_SAVE_STATE_SIZE_KNOWN))
  971. {
  972. /* Disable runahead if current core reports
  973. * that it has an insufficient savestate
  974. * support level */
  975. if (!core_info_current_supports_runahead())
  976. {
  977. runahead_error(runloop_st);
  978. /* If core is incompatible with runahead,
  979. * log a warning but do not spam OSD messages.
  980. * Runahead menu entries are hidden when using
  981. * incompatible cores, so there is no mechanism
  982. * for users to respond to notifications. In
  983. * addition, auto-disabling runahead is a feature,
  984. * not a cause for 'concern'; OSD warnings should
  985. * be reserved for when a core reports that it is
  986. * runahead-compatible but subsequently fails in
  987. * execution */
  988. RARCH_WARN("[Run-Ahead]: %s\n", msg_hash_to_str(MSG_RUNAHEAD_CORE_DOES_NOT_SUPPORT_RUNAHEAD));
  989. goto force_input_dirty;
  990. }
  991. if (!runahead_create(runloop_st))
  992. {
  993. const char *runahead_failed_str =
  994. msg_hash_to_str(MSG_RUNAHEAD_CORE_DOES_NOT_SUPPORT_SAVESTATES);
  995. if (!runahead_hide_warnings)
  996. runloop_msg_queue_push(runahead_failed_str, 0, 2 * 60, true, NULL, MESSAGE_QUEUE_ICON_DEFAULT, MESSAGE_QUEUE_CATEGORY_INFO);
  997. RARCH_WARN("[Run-Ahead]: %s\n", runahead_failed_str);
  998. goto force_input_dirty;
  999. }
  1000. }
  1001. /* Check for GUI */
  1002. /* Hack: If we were in the GUI, force a resync. */
  1003. if (frame_count != runloop_st->runahead_last_frame_count + 1)
  1004. runloop_st->flags |= RUNLOOP_FLAG_RUNAHEAD_FORCE_INPUT_DIRTY;
  1005. runloop_st->runahead_last_frame_count = frame_count;
  1006. if ( !use_secondary
  1007. || !have_dynamic
  1008. || !(runloop_st->flags & RUNLOOP_FLAG_RUNAHEAD_SECONDARY_CORE_AVAILABLE))
  1009. {
  1010. /* TODO: multiple savestates for higher performance
  1011. * when not using secondary core */
  1012. for (frame_number = 0; frame_number <= runahead_count; frame_number++)
  1013. {
  1014. last_frame = frame_number == runahead_count;
  1015. suspended_frame = !last_frame;
  1016. if (suspended_frame)
  1017. {
  1018. audio_st->flags |= AUDIO_FLAG_SUSPENDED;
  1019. video_st->flags &= ~VIDEO_FLAG_ACTIVE;
  1020. }
  1021. if (frame_number == 0)
  1022. core_run();
  1023. else
  1024. runahead_core_run_use_last_input(runloop_st);
  1025. if (suspended_frame)
  1026. {
  1027. if (video_st->flags & VIDEO_FLAG_RUNAHEAD_IS_ACTIVE)
  1028. video_st->flags |= VIDEO_FLAG_ACTIVE;
  1029. else
  1030. video_st->flags &= ~VIDEO_FLAG_ACTIVE;
  1031. audio_st->flags &= ~AUDIO_FLAG_SUSPENDED;
  1032. }
  1033. if (frame_number == 0)
  1034. {
  1035. if (!runahead_save_state(runloop_st))
  1036. {
  1037. const char *runahead_failed_str =
  1038. msg_hash_to_str(MSG_RUNAHEAD_FAILED_TO_SAVE_STATE);
  1039. runloop_msg_queue_push(runahead_failed_str, 0, 3 * 60, true, NULL, MESSAGE_QUEUE_ICON_DEFAULT, MESSAGE_QUEUE_CATEGORY_INFO);
  1040. RARCH_WARN("[Run-Ahead]: %s\n", runahead_failed_str);
  1041. return;
  1042. }
  1043. }
  1044. if (last_frame)
  1045. {
  1046. if (!runahead_load_state(runloop_st))
  1047. {
  1048. const char *runahead_failed_str =
  1049. msg_hash_to_str(MSG_RUNAHEAD_FAILED_TO_LOAD_STATE);
  1050. runloop_msg_queue_push(runahead_failed_str, 0, 3 * 60, true, NULL, MESSAGE_QUEUE_ICON_DEFAULT, MESSAGE_QUEUE_CATEGORY_INFO);
  1051. RARCH_WARN("[Run-Ahead]: %s\n", runahead_failed_str);
  1052. return;
  1053. }
  1054. }
  1055. }
  1056. }
  1057. else
  1058. {
  1059. #if HAVE_DYNAMIC
  1060. if (!secondary_core_ensure_exists(runloop_st, config_get_ptr()))
  1061. {
  1062. const char *runahead_failed_str =
  1063. msg_hash_to_str(MSG_RUNAHEAD_FAILED_TO_CREATE_SECONDARY_INSTANCE);
  1064. runahead_secondary_core_destroy(runloop_st);
  1065. runloop_st->flags &= ~RUNLOOP_FLAG_RUNAHEAD_SECONDARY_CORE_AVAILABLE;
  1066. runloop_msg_queue_push(runahead_failed_str, 0, 3 * 60, true, NULL, MESSAGE_QUEUE_ICON_DEFAULT, MESSAGE_QUEUE_CATEGORY_INFO);
  1067. RARCH_WARN("[Run-Ahead]: %s\n", runahead_failed_str);
  1068. goto force_input_dirty;
  1069. }
  1070. /* run main core with video suspended */
  1071. video_st->flags &= ~VIDEO_FLAG_ACTIVE;
  1072. core_run();
  1073. if (video_st->flags & VIDEO_FLAG_RUNAHEAD_IS_ACTIVE)
  1074. video_st->flags |= VIDEO_FLAG_ACTIVE;
  1075. else
  1076. video_st->flags &= ~VIDEO_FLAG_ACTIVE;
  1077. if ( (runloop_st->flags & RUNLOOP_FLAG_INPUT_IS_DIRTY)
  1078. || (runloop_st->flags & RUNLOOP_FLAG_RUNAHEAD_FORCE_INPUT_DIRTY))
  1079. {
  1080. runloop_st->flags &= ~RUNLOOP_FLAG_INPUT_IS_DIRTY;
  1081. if (!runahead_save_state(runloop_st))
  1082. {
  1083. const char *runahead_failed_str =
  1084. msg_hash_to_str(MSG_RUNAHEAD_FAILED_TO_SAVE_STATE);
  1085. runloop_msg_queue_push(runahead_failed_str, 0, 3 * 60, true, NULL, MESSAGE_QUEUE_ICON_DEFAULT, MESSAGE_QUEUE_CATEGORY_INFO);
  1086. RARCH_WARN("[Run-Ahead]: %s\n", runahead_failed_str);
  1087. return;
  1088. }
  1089. if (!runahead_load_state_secondary(runloop_st, settings))
  1090. {
  1091. const char *runahead_failed_str =
  1092. msg_hash_to_str(MSG_RUNAHEAD_FAILED_TO_LOAD_STATE);
  1093. runloop_msg_queue_push(runahead_failed_str, 0, 3 * 60, true, NULL, MESSAGE_QUEUE_ICON_DEFAULT, MESSAGE_QUEUE_CATEGORY_INFO);
  1094. RARCH_WARN("[Run-Ahead]: %s\n", runahead_failed_str);
  1095. return;
  1096. }
  1097. for (frame_number = 0; frame_number < runahead_count - 1; frame_number++)
  1098. {
  1099. video_st->flags &= ~VIDEO_FLAG_ACTIVE;
  1100. audio_st->flags |= AUDIO_FLAG_SUSPENDED
  1101. | AUDIO_FLAG_HARD_DISABLE;
  1102. if (secondary_core_run_use_last_input(runloop_st))
  1103. runloop_st->flags |= RUNLOOP_FLAG_RUNAHEAD_SECONDARY_CORE_AVAILABLE;
  1104. else
  1105. runloop_st->flags &= ~RUNLOOP_FLAG_RUNAHEAD_SECONDARY_CORE_AVAILABLE;
  1106. audio_st->flags &= ~(AUDIO_FLAG_SUSPENDED
  1107. | AUDIO_FLAG_HARD_DISABLE);
  1108. if (video_st->flags & VIDEO_FLAG_RUNAHEAD_IS_ACTIVE)
  1109. video_st->flags |= VIDEO_FLAG_ACTIVE;
  1110. else
  1111. video_st->flags &= ~VIDEO_FLAG_ACTIVE;
  1112. }
  1113. }
  1114. audio_st->flags |= AUDIO_FLAG_SUSPENDED
  1115. | AUDIO_FLAG_HARD_DISABLE;
  1116. if (secondary_core_run_use_last_input(runloop_st))
  1117. runloop_st->flags |= RUNLOOP_FLAG_RUNAHEAD_SECONDARY_CORE_AVAILABLE;
  1118. else
  1119. runloop_st->flags &= ~RUNLOOP_FLAG_RUNAHEAD_SECONDARY_CORE_AVAILABLE;
  1120. audio_st->flags &= ~(AUDIO_FLAG_SUSPENDED
  1121. | AUDIO_FLAG_HARD_DISABLE);
  1122. #endif
  1123. }
  1124. runloop_st->flags &= ~RUNLOOP_FLAG_RUNAHEAD_FORCE_INPUT_DIRTY;
  1125. return;
  1126. force_input_dirty:
  1127. core_run();
  1128. runloop_st->flags |= RUNLOOP_FLAG_RUNAHEAD_FORCE_INPUT_DIRTY;
  1129. }
  1130. /* Preemptive Frames */
  1131. static int16_t preempt_input_state(unsigned port,
  1132. unsigned device, unsigned index, unsigned id)
  1133. {
  1134. settings_t *settings = config_get_ptr();
  1135. runloop_state_t *runloop_st = runloop_state_get_ptr();
  1136. preempt_t *preempt = runloop_st->preempt_data;
  1137. unsigned device_class = device & RETRO_DEVICE_MASK;
  1138. unsigned *port_map = settings->uints.input_remap_port_map[port];
  1139. uint8_t p;
  1140. switch (device_class)
  1141. {
  1142. case RETRO_DEVICE_ANALOG:
  1143. /* Add requested inputs to mask */
  1144. while ((p = *(port_map++)) < MAX_USERS)
  1145. preempt->analog_mask[p] |= (1 << (id + index * 2));
  1146. break;
  1147. case RETRO_DEVICE_LIGHTGUN:
  1148. case RETRO_DEVICE_MOUSE:
  1149. case RETRO_DEVICE_POINTER:
  1150. /* Set pointing device for this port */
  1151. while ((p = *(port_map++)) < MAX_USERS)
  1152. preempt->ptr_dev[p] = device_class;
  1153. break;
  1154. default:
  1155. break;
  1156. }
  1157. return input_driver_state_wrapper(port, device, index, id);
  1158. }
  1159. static const char* preempt_allocate(runloop_state_t *runloop_st,
  1160. const uint8_t frames)
  1161. {
  1162. preempt_t *preempt = (preempt_t*)calloc(1, sizeof(preempt_t));
  1163. retro_ctx_size_info_t info;
  1164. uint8_t i;
  1165. if (!(runloop_st->preempt_data = preempt))
  1166. return msg_hash_to_str(MSG_PREEMPT_FAILED_TO_ALLOCATE);
  1167. core_serialize_size_special(&info);
  1168. if (!info.size)
  1169. return msg_hash_to_str(MSG_PREEMPT_CORE_DOES_NOT_SUPPORT_SAVESTATES);
  1170. preempt->state_size = info.size;
  1171. preempt->frames = frames;
  1172. for (i = 0; i < frames; i++)
  1173. {
  1174. preempt->buffer[i] = malloc(preempt->state_size);
  1175. if (!preempt->buffer[i])
  1176. return msg_hash_to_str(MSG_PREEMPT_FAILED_TO_ALLOCATE);
  1177. }
  1178. return NULL;
  1179. }
  1180. /**
  1181. * preempt_deinit:
  1182. *
  1183. * Frees preempt object and unsets overrides.
  1184. **/
  1185. void preempt_deinit(void *data)
  1186. {
  1187. runloop_state_t *runloop_st = (runloop_state_t*)data;
  1188. preempt_t *preempt = runloop_st->preempt_data;
  1189. struct retro_core_t *current_core = &runloop_st->current_core;
  1190. size_t i;
  1191. if (!preempt)
  1192. return;
  1193. /* Free memory */
  1194. for (i = 0; i < preempt->frames; i++)
  1195. free(preempt->buffer[i]);
  1196. free(preempt);
  1197. runloop_st->preempt_data = NULL;
  1198. /* Undo overrides */
  1199. runloop_st->flags |= (RUNLOOP_FLAG_RUNAHEAD_AVAILABLE
  1200. | RUNLOOP_FLAG_RUNAHEAD_SECONDARY_CORE_AVAILABLE);
  1201. if (current_core->retro_set_input_poll)
  1202. current_core->retro_set_input_poll(runloop_st->input_poll_callback_original);
  1203. if (current_core->retro_set_input_state)
  1204. current_core->retro_set_input_state(runloop_st->retro_ctx.state_cb);
  1205. }
  1206. /**
  1207. * preempt_init:
  1208. *
  1209. * @return true on success, false on failure
  1210. *
  1211. * Allocates savestate buffer and sets overrides for preemptive frames.
  1212. **/
  1213. bool preempt_init(void *data)
  1214. {
  1215. runloop_state_t *runloop_st = (runloop_state_t*)data;
  1216. settings_t *settings = config_get_ptr();
  1217. const char *failed_str = NULL;
  1218. if ( runloop_st->preempt_data
  1219. || !settings->bools.preemptive_frames_enable
  1220. || !settings->uints.run_ahead_frames
  1221. || !(runloop_st->current_core.flags & RETRO_CORE_FLAG_GAME_LOADED))
  1222. return false;
  1223. /* Check if supported - same requirements as runahead */
  1224. if (!core_info_current_supports_runahead())
  1225. {
  1226. failed_str = msg_hash_to_str(MSG_PREEMPT_CORE_DOES_NOT_SUPPORT_PREEMPT);
  1227. goto error;
  1228. }
  1229. /* Set flags to block runahead and request 'same instance' states */
  1230. runloop_st->flags &= ~(RUNLOOP_FLAG_RUNAHEAD_AVAILABLE
  1231. | RUNLOOP_FLAG_RUNAHEAD_SECONDARY_CORE_AVAILABLE);
  1232. /* Run at least one frame before attempting
  1233. * retro_serialize_size or retro_serialize */
  1234. if (video_state_get_ptr()->frame_count == 0)
  1235. runloop_st->current_core.retro_run();
  1236. /* Allocate - same 'frames' setting as runahead */
  1237. if ((failed_str = preempt_allocate(runloop_st,
  1238. settings->uints.run_ahead_frames)))
  1239. goto error;
  1240. /* Only poll in preempt_run() */
  1241. runloop_st->current_core.retro_set_input_poll(retro_input_poll_null);
  1242. /* Track requested analog states and pointing device types */
  1243. runloop_st->current_core.retro_set_input_state(preempt_input_state);
  1244. return true;
  1245. error:
  1246. preempt_deinit(runloop_st);
  1247. if (!settings->bools.preemptive_frames_hide_warnings)
  1248. runloop_msg_queue_push(
  1249. failed_str, 0, 2 * 60, true,
  1250. NULL, MESSAGE_QUEUE_ICON_DEFAULT, MESSAGE_QUEUE_CATEGORY_INFO);
  1251. RARCH_WARN("[Preemptive Frames]: %s\n", failed_str);
  1252. return false;
  1253. }
  1254. static INLINE bool preempt_analog_input_dirty(preempt_t *preempt,
  1255. retro_input_state_t state_cb, unsigned port, unsigned mapped_port)
  1256. {
  1257. int16_t state[20] = {0};
  1258. uint8_t base, i;
  1259. /* axes */
  1260. for (i = 0; i < 2; i++)
  1261. {
  1262. base = i * 2;
  1263. if (preempt->analog_mask[port] & (1 << (base )))
  1264. state[base ] = state_cb(mapped_port, RETRO_DEVICE_ANALOG, i, 0);
  1265. if (preempt->analog_mask[port] & (1 << (base + 1)))
  1266. state[base + 1] = state_cb(mapped_port, RETRO_DEVICE_ANALOG, i, 1);
  1267. }
  1268. /* buttons */
  1269. for (i = 0; i < RARCH_FIRST_CUSTOM_BIND; i++)
  1270. {
  1271. if (preempt->analog_mask[port] & (1 << (i + 4)))
  1272. state[i + 4] = state_cb(mapped_port, RETRO_DEVICE_ANALOG,
  1273. RETRO_DEVICE_INDEX_ANALOG_BUTTON, i);
  1274. }
  1275. if (memcmp(preempt->analog_state[port], state, sizeof(state)) == 0)
  1276. return false;
  1277. memcpy(preempt->analog_state[port], state, sizeof(state));
  1278. return true;
  1279. }
  1280. static INLINE bool preempt_ptr_input_dirty(preempt_t *preempt,
  1281. retro_input_state_t state_cb, unsigned device,
  1282. unsigned port, unsigned mapped_port)
  1283. {
  1284. int16_t state[4] = {0};
  1285. unsigned count_id = 0;
  1286. unsigned x_id = 0;
  1287. unsigned id, max_id;
  1288. switch (device)
  1289. {
  1290. case RETRO_DEVICE_MOUSE:
  1291. max_id = RETRO_DEVICE_ID_MOUSE_BUTTON_5;
  1292. break;
  1293. case RETRO_DEVICE_LIGHTGUN:
  1294. x_id = RETRO_DEVICE_ID_LIGHTGUN_SCREEN_X;
  1295. max_id = RETRO_DEVICE_ID_LIGHTGUN_DPAD_RIGHT;
  1296. break;
  1297. case RETRO_DEVICE_POINTER:
  1298. max_id = RETRO_DEVICE_ID_POINTER_PRESSED;
  1299. count_id = RETRO_DEVICE_ID_POINTER_COUNT;
  1300. break;
  1301. default:
  1302. return false;
  1303. }
  1304. /* x, y */
  1305. state[0] = state_cb(mapped_port, device, 0, x_id );
  1306. state[1] = state_cb(mapped_port, device, 0, x_id + 1);
  1307. /* buttons */
  1308. for (id = 2; id <= max_id; id++)
  1309. state[2] |= state_cb(mapped_port, device, 0, id) ? 1 << id : 0;
  1310. /* ptr count */
  1311. if (count_id)
  1312. state[3] = state_cb(mapped_port, device, 0, count_id);
  1313. if (memcmp(preempt->ptrdev_state[port], state, sizeof(state)) == 0)
  1314. return false;
  1315. memcpy(preempt->ptrdev_state[port], state, sizeof(state));
  1316. return true;
  1317. }
  1318. static INLINE void preempt_input_poll(preempt_t *preempt,
  1319. runloop_state_t *runloop_st, settings_t *settings)
  1320. {
  1321. size_t p;
  1322. int16_t joypad_state;
  1323. retro_input_state_t state_cb = input_driver_state_wrapper;
  1324. unsigned max_users = settings->uints.input_max_users;
  1325. input_driver_poll();
  1326. /* Check for input state changes */
  1327. for (p = 0; p < max_users; p++)
  1328. {
  1329. unsigned mapped_port = settings->uints.input_remap_ports[p];
  1330. unsigned device = settings->uints.input_libretro_device[mapped_port]
  1331. & RETRO_DEVICE_MASK;
  1332. switch (device)
  1333. {
  1334. case RETRO_DEVICE_JOYPAD:
  1335. case RETRO_DEVICE_ANALOG:
  1336. /* Check full digital joypad */
  1337. joypad_state = state_cb(mapped_port, RETRO_DEVICE_JOYPAD,
  1338. 0, RETRO_DEVICE_ID_JOYPAD_MASK);
  1339. if (joypad_state != preempt->joypad_state[p])
  1340. {
  1341. preempt->joypad_state[p] = joypad_state;
  1342. runloop_st->flags |= RUNLOOP_FLAG_INPUT_IS_DIRTY;
  1343. }
  1344. /* Check requested analogs */
  1345. if ( preempt->analog_mask[p]
  1346. && preempt_analog_input_dirty(preempt, state_cb, (unsigned)p, mapped_port))
  1347. runloop_st->flags |= RUNLOOP_FLAG_INPUT_IS_DIRTY;
  1348. break;
  1349. case RETRO_DEVICE_MOUSE:
  1350. case RETRO_DEVICE_LIGHTGUN:
  1351. case RETRO_DEVICE_POINTER:
  1352. /* Check full device state */
  1353. if (preempt_ptr_input_dirty(
  1354. preempt, state_cb, preempt->ptr_dev[p], (unsigned)p, mapped_port))
  1355. runloop_st->flags |= RUNLOOP_FLAG_INPUT_IS_DIRTY;
  1356. break;
  1357. default:
  1358. break;
  1359. }
  1360. }
  1361. /* Clear requested inputs */
  1362. memset(preempt->analog_mask, 0, max_users * sizeof(uint32_t));
  1363. memset(preempt->ptr_dev, 0, max_users * sizeof(uint8_t));
  1364. }
  1365. /* macro for preempt_run */
  1366. #define PREEMPT_NEXT_PTR(x) ((x + 1) % preempt->frames)
  1367. /**
  1368. * preempt_run:
  1369. * @preempt : pointer to preemptive frames object
  1370. *
  1371. * Call in place of core_run() for preemptive frames.
  1372. **/
  1373. void preempt_run(preempt_t *preempt, void *data)
  1374. {
  1375. runloop_state_t *runloop_st = (runloop_state_t*)data;
  1376. struct retro_core_t *current_core = &runloop_st->current_core;
  1377. const char *failed_str = NULL;
  1378. settings_t *settings = config_get_ptr();
  1379. audio_driver_state_t *audio_st = audio_state_get_ptr();
  1380. video_driver_state_t *video_st = video_state_get_ptr();
  1381. /* Poll and check for dirty input */
  1382. preempt_input_poll(preempt, runloop_st, settings);
  1383. runloop_st->flags |= RUNLOOP_FLAG_REQUEST_SPECIAL_SAVESTATE;
  1384. if ((runloop_st->flags & RUNLOOP_FLAG_INPUT_IS_DIRTY)
  1385. && preempt->frame_count >= preempt->frames)
  1386. {
  1387. /* Suspend A/V and run preemptive frames */
  1388. audio_st->flags |= AUDIO_FLAG_SUSPENDED;
  1389. video_st->flags &= ~VIDEO_FLAG_ACTIVE;
  1390. if (!current_core->retro_unserialize(
  1391. preempt->buffer[preempt->start_ptr], preempt->state_size))
  1392. {
  1393. failed_str = msg_hash_to_str(MSG_PREEMPT_FAILED_TO_LOAD_STATE);
  1394. goto error;
  1395. }
  1396. current_core->retro_run();
  1397. preempt->replay_ptr = PREEMPT_NEXT_PTR(preempt->start_ptr);
  1398. while (preempt->replay_ptr != preempt->start_ptr)
  1399. {
  1400. if (!current_core->retro_serialize(
  1401. preempt->buffer[preempt->replay_ptr], preempt->state_size))
  1402. {
  1403. failed_str = msg_hash_to_str(MSG_PREEMPT_FAILED_TO_SAVE_STATE);
  1404. goto error;
  1405. }
  1406. current_core->retro_run();
  1407. preempt->replay_ptr = PREEMPT_NEXT_PTR(preempt->replay_ptr);
  1408. }
  1409. audio_st->flags &= ~AUDIO_FLAG_SUSPENDED;
  1410. video_st->flags |= VIDEO_FLAG_ACTIVE;
  1411. }
  1412. /* Save current state and set start_ptr to oldest state */
  1413. if (!current_core->retro_serialize(
  1414. preempt->buffer[preempt->start_ptr], preempt->state_size))
  1415. {
  1416. failed_str = msg_hash_to_str(MSG_PREEMPT_FAILED_TO_SAVE_STATE);
  1417. goto error;
  1418. }
  1419. preempt->start_ptr = PREEMPT_NEXT_PTR(preempt->start_ptr);
  1420. runloop_st->flags &= ~(RUNLOOP_FLAG_REQUEST_SPECIAL_SAVESTATE
  1421. | RUNLOOP_FLAG_INPUT_IS_DIRTY);
  1422. /* Run normal frame */
  1423. current_core->retro_run();
  1424. preempt->frame_count++;
  1425. return;
  1426. error:
  1427. runloop_st->flags &= ~(RUNLOOP_FLAG_REQUEST_SPECIAL_SAVESTATE
  1428. | RUNLOOP_FLAG_INPUT_IS_DIRTY);
  1429. audio_st->flags &= ~AUDIO_FLAG_SUSPENDED;
  1430. video_st->flags |= VIDEO_FLAG_ACTIVE;
  1431. preempt_deinit(runloop_st);
  1432. if (!settings->bools.preemptive_frames_hide_warnings)
  1433. runloop_msg_queue_push(
  1434. failed_str, 0, 2 * 60, true,
  1435. NULL, MESSAGE_QUEUE_ICON_DEFAULT, MESSAGE_QUEUE_CATEGORY_INFO);
  1436. RARCH_ERR("[Preemptive Frames]: %s\n", failed_str);
  1437. }
  1438. void runahead_clear_variables(void *data)
  1439. {
  1440. runloop_state_t *runloop_st = (runloop_state_t*)data;
  1441. video_driver_state_t *video_st = video_state_get_ptr();
  1442. runloop_st->runahead_save_state_size = 0;
  1443. runloop_st->flags &= ~RUNLOOP_FLAG_RUNAHEAD_SAVE_STATE_SIZE_KNOWN;
  1444. video_st->flags |= VIDEO_FLAG_RUNAHEAD_IS_ACTIVE;
  1445. runloop_st->flags |= RUNLOOP_FLAG_RUNAHEAD_AVAILABLE
  1446. | RUNLOOP_FLAG_RUNAHEAD_SECONDARY_CORE_AVAILABLE
  1447. | RUNLOOP_FLAG_RUNAHEAD_FORCE_INPUT_DIRTY;
  1448. runloop_st->runahead_last_frame_count = 0;
  1449. }