database_info.c 32 KB

12345678910111213141516171819202122232425262728293031323334353637383940414243444546474849505152535455565758596061626364656667686970717273747576777879808182838485868788899091929394959697989910010110210310410510610710810911011111211311411511611711811912012112212312412512612712812913013113213313413513613713813914014114214314414514614714814915015115215315415515615715815916016116216316416516616716816917017117217317417517617717817918018118218318418518618718818919019119219319419519619719819920020120220320420520620720820921021121221321421521621721821922022122222322422522622722822923023123223323423523623723823924024124224324424524624724824925025125225325425525625725825926026126226326426526626726826927027127227327427527627727827928028128228328428528628728828929029129229329429529629729829930030130230330430530630730830931031131231331431531631731831932032132232332432532632732832933033133233333433533633733833934034134234334434534634734834935035135235335435535635735835936036136236336436536636736836937037137237337437537637737837938038138238338438538638738838939039139239339439539639739839940040140240340440540640740840941041141241341441541641741841942042142242342442542642742842943043143243343443543643743843944044144244344444544644744844945045145245345445545645745845946046146246346446546646746846947047147247347447547647747847948048148248348448548648748848949049149249349449549649749849950050150250350450550650750850951051151251351451551651751851952052152252352452552652752852953053153253353453553653753853954054154254354454554654754854955055155255355455555655755855956056156256356456556656756856957057157257357457557657757857958058158258358458558658758858959059159259359459559659759859960060160260360460560660760860961061161261361461561661761861962062162262362462562662762862963063163263363463563663763863964064164264364464564664764864965065165265365465565665765865966066166266366466566666766866967067167267367467567667767867968068168268368468568668768868969069169269369469569669769869970070170270370470570670770870971071171271371471571671771871972072172272372472572672772872973073173273373473573673773873974074174274374474574674774874975075175275375475575675775875976076176276376476576676776876977077177277377477577677777877978078178278378478578678778878979079179279379479579679779879980080180280380480580680780880981081181281381481581681781881982082182282382482582682782882983083183283383483583683783883984084184284384484584684784884985085185285385485585685785885986086186286386486586686786886987087187287387487587687787887988088188288388488588688788888989089189289389489589689789889990090190290390490590690790890991091191291391491591691791891992092192292392492592692792892993093193293393493593693793893994094194294394494594694794894995095195295395495595695795895996096196296396496596696796896997097197297397497597697797897998098198298398498598698798898999099199299399499599699799899910001001100210031004100510061007100810091010101110121013101410151016101710181019102010211022102310241025102610271028102910301031103210331034103510361037103810391040104110421043104410451046104710481049105010511052105310541055105610571058105910601061106210631064106510661067106810691070107110721073107410751076107710781079108010811082
  1. /* RetroArch - A frontend for libretro.
  2. * Copyright (C) 2010-2014 - Hans-Kristian Arntzen
  3. * Copyright (C) 2011-2017 - Daniel De Matteis
  4. * Copyright (C) 2016-2019 - Brad Parker
  5. *
  6. * RetroArch is free software: you can redistribute it and/or modify it under the terms
  7. * of the GNU General Public License as published by the Free Software Found-
  8. * ation, either version 3 of the License, or (at your option) any later version.
  9. *
  10. * RetroArch is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY;
  11. * without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR
  12. * PURPOSE. See the GNU General Public License for more details.
  13. *
  14. * You should have received a copy of the GNU General Public License along with RetroArch.
  15. * If not, see <http://www.gnu.org/licenses/>.
  16. */
  17. #include <stdio.h>
  18. #include <stdint.h>
  19. #include <compat/strl.h>
  20. #include <retro_endianness.h>
  21. #include <file/file_path.h>
  22. #include <lists/string_list.h>
  23. #include <lists/dir_list.h>
  24. #include <string/stdstring.h>
  25. #include "libretro-db/libretrodb.h"
  26. #include "core_info.h"
  27. #include "database_info.h"
  28. int database_info_build_query_enum(char *s, size_t len,
  29. enum database_query_type type,
  30. const char *path)
  31. {
  32. size_t pos = 0;
  33. switch (type)
  34. {
  35. case DATABASE_QUERY_ENTRY:
  36. s[0] = '{';
  37. s[1] = '\'';
  38. s[2] = 'n';
  39. s[3] = 'a';
  40. s[4] = 'm';
  41. s[5] = 'e';
  42. s[6] = '\'';
  43. s[7] = ':';
  44. s[8] = '"';
  45. s[9] = '\0';
  46. pos = strlcat(s, path, len);
  47. s[pos ] = '"';
  48. s[pos+1] = '}';
  49. s[pos+2] = '\0';
  50. break;
  51. case DATABASE_QUERY_ENTRY_PUBLISHER:
  52. s[0] = '{';
  53. s[1] = '\'';
  54. s[2] = 'p';
  55. s[3] = 'u';
  56. s[4] = 'b';
  57. s[5] = 'l';
  58. s[6] = 'i';
  59. s[7] = 's';
  60. s[8] = 'h';
  61. s[9] = 'e';
  62. s[10] = 'r';
  63. s[11] = '\'';
  64. s[12] = ':';
  65. s[13] = '"';
  66. s[14] = '\0';
  67. pos = strlcat(s, path, len);
  68. s[pos ] = '"';
  69. s[pos+1] = '}';
  70. s[pos+2] = '\0';
  71. break;
  72. case DATABASE_QUERY_ENTRY_DEVELOPER:
  73. s[0] = '{';
  74. s[1] = '\'';
  75. s[2] = 'd';
  76. s[3] = 'e';
  77. s[4] = 'v';
  78. s[5] = 'e';
  79. s[6] = 'l';
  80. s[7] = 'o';
  81. s[8] = 'p';
  82. s[9] = 'e';
  83. s[10] = 'r';
  84. s[11] = '\'';
  85. s[12] = ':';
  86. s[13] = 'g';
  87. s[14] = 'l';
  88. s[15] = 'o';
  89. s[16] = 'b';
  90. s[17] = '(';
  91. s[18] = '\'';
  92. s[19] = '*';
  93. s[20] = '\0';
  94. pos = strlcat(s, path, len);
  95. s[pos ] = '*';
  96. s[pos+1] = '\'';
  97. s[pos+2] = ')';
  98. s[pos+3] = '}';
  99. s[pos+4] = '\0';
  100. break;
  101. case DATABASE_QUERY_ENTRY_ORIGIN:
  102. s[0] = '{';
  103. s[1] = '\'';
  104. s[2] = 'o';
  105. s[3] = 'r';
  106. s[4] = 'i';
  107. s[5] = 'g';
  108. s[6] = 'i';
  109. s[7] = 'n';
  110. s[8] = '\'';
  111. s[9] = ':';
  112. s[10] = '"';
  113. s[11] = '\0';
  114. pos = strlcat(s, path, len);
  115. s[pos ] = '"';
  116. s[pos+1] = '}';
  117. s[pos+2] = '\0';
  118. break;
  119. case DATABASE_QUERY_ENTRY_FRANCHISE:
  120. s[0] = '{';
  121. s[1] = '\'';
  122. s[2] = 'f';
  123. s[3] = 'r';
  124. s[4] = 'a';
  125. s[5] = 'n';
  126. s[6] = 'c';
  127. s[7] = 'h';
  128. s[8] = 'i';
  129. s[9] = 's';
  130. s[10] = 'e';
  131. s[11] = '\'';
  132. s[12] = ':';
  133. s[13] = '"';
  134. s[14] = '\0';
  135. pos = strlcat(s, path, len);
  136. s[pos ] = '"';
  137. s[pos+1] = '}';
  138. s[pos+2] = '\0';
  139. break;
  140. case DATABASE_QUERY_ENTRY_RATING:
  141. s[0] = '{';
  142. s[1] = '\'';
  143. s[2] = 'e';
  144. s[3] = 's';
  145. s[4] = 'r';
  146. s[5] = 'b';
  147. s[6] = '_';
  148. s[7] = 'r';
  149. s[8] = 'a';
  150. s[9] = 't';
  151. s[10] = 'i';
  152. s[11] = 'n';
  153. s[12] = 'g';
  154. s[13] = '\'';
  155. s[14] = ':';
  156. s[15] = '"';
  157. pos = strlcat(s, path, len);
  158. s[pos ] = '"';
  159. s[pos+1] = '}';
  160. s[pos+2] = '\0';
  161. break;
  162. case DATABASE_QUERY_ENTRY_BBFC_RATING:
  163. s[0] = '{';
  164. s[1] = '\'';
  165. s[2] = 'b';
  166. s[3] = 'b';
  167. s[4] = 'f';
  168. s[5] = 'c';
  169. s[6] = '_';
  170. s[7] = 'r';
  171. s[8] = 'a';
  172. s[9] = 't';
  173. s[10] = 'i';
  174. s[11] = 'n';
  175. s[12] = 'g';
  176. s[13] = '\'';
  177. s[14] = ':';
  178. s[15] = '"';
  179. s[16] = '\0';
  180. pos = strlcat(s, path, len);
  181. s[pos ] = '"';
  182. s[pos+1] = '}';
  183. s[pos+2] = '\0';
  184. break;
  185. case DATABASE_QUERY_ENTRY_ELSPA_RATING:
  186. s[0] = '{';
  187. s[1] = '\'';
  188. s[2] = 'e';
  189. s[3] = 'l';
  190. s[4] = 's';
  191. s[5] = 'p';
  192. s[6] = 'a';
  193. s[7] = '_';
  194. s[8] = 'r';
  195. s[9] = 'a';
  196. s[10] = 't';
  197. s[11] = 'i';
  198. s[12] = 'n';
  199. s[13] = 'g';
  200. s[14] = '\'';
  201. s[15] = ':';
  202. s[16] = '"';
  203. s[17] = '\0';
  204. pos = strlcat(s, path, len);
  205. s[pos ] = '"';
  206. s[pos+1] = '}';
  207. s[pos+2] = '\0';
  208. break;
  209. case DATABASE_QUERY_ENTRY_ESRB_RATING:
  210. s[0] = '{';
  211. s[1] = '\'';
  212. s[2] = 'e';
  213. s[3] = 's';
  214. s[4] = 'r';
  215. s[5] = 'b';
  216. s[6] = '_';
  217. s[7] = 'r';
  218. s[8] = 'a';
  219. s[9 ] = 't';
  220. s[10] = 'i';
  221. s[11] = 'n';
  222. s[12] = 'g';
  223. s[13] = '\'';
  224. s[14] = ':';
  225. s[15] = '"';
  226. s[16] = '\0';
  227. pos = strlcat(s, path, len);
  228. s[pos ] = '"';
  229. s[pos+1] = '}';
  230. s[pos+2] = '\0';
  231. break;
  232. case DATABASE_QUERY_ENTRY_PEGI_RATING:
  233. s[0] = '{';
  234. s[1] = '\'';
  235. s[2] = 'p';
  236. s[3] = 'e';
  237. s[4] = 'g';
  238. s[5] = 'i';
  239. s[6] = '_';
  240. s[7] = 'r';
  241. s[8] = 'a';
  242. s[9] = 't';
  243. s[10] = 'i';
  244. s[11] = 'n';
  245. s[12] = 'g';
  246. s[13] = '\'';
  247. s[14] = ':';
  248. s[15] = '"';
  249. s[16] = '\0';
  250. pos = strlcat(s, path, len);
  251. s[pos ] = '"';
  252. s[pos+1] = '}';
  253. s[pos+2] = '\0';
  254. break;
  255. case DATABASE_QUERY_ENTRY_CERO_RATING:
  256. s[0] = '{';
  257. s[1] = '\'';
  258. s[2] = 'c';
  259. s[3] = 'e';
  260. s[4] = 'r';
  261. s[5] = 'o';
  262. s[6] = '_';
  263. s[7] = 'r';
  264. s[8] = 'a';
  265. s[9] = 't';
  266. s[10] = 'i';
  267. s[11] = 'n';
  268. s[12] = 'g';
  269. s[13] = '\'';
  270. s[14] = ':';
  271. s[15] = '"';
  272. s[16] = '\0';
  273. pos = strlcat(s, path, len);
  274. s[pos ] = '"';
  275. s[pos+1] = '}';
  276. s[pos+2] = '\0';
  277. break;
  278. case DATABASE_QUERY_ENTRY_ENHANCEMENT_HW:
  279. s[0] = '{';
  280. s[1] = '\'';
  281. s[2] = 'e';
  282. s[3] = 'n';
  283. s[4] = 'h';
  284. s[5] = 'a';
  285. s[6] = 'n';
  286. s[7] = 'c';
  287. s[8] = 'e';
  288. s[9] = 'm';
  289. s[10] = 'e';
  290. s[11] = 'n';
  291. s[12] = 't';
  292. s[13] = '_';
  293. s[14] = 'h';
  294. s[15] = 'w';
  295. s[16] = '\'';
  296. s[17] = ':';
  297. s[18] = '"';
  298. s[19] = '\0';
  299. pos = strlcat(s, path, len);
  300. s[pos ] = '"';
  301. s[pos+1] = '}';
  302. s[pos+2] = '\0';
  303. break;
  304. case DATABASE_QUERY_ENTRY_EDGE_MAGAZINE_RATING:
  305. s[0] = '{';
  306. s[1] = '\'';
  307. s[2] = 'e';
  308. s[3] = 'd';
  309. s[4] = 'g';
  310. s[5] = 'e';
  311. s[6] = '_';
  312. s[7] = 'r';
  313. s[8] = 'a';
  314. s[9] = 't';
  315. s[10] = 'i';
  316. s[11] = 'n';
  317. s[12] = 'g';
  318. s[13] = '\'';
  319. s[14] = ':';
  320. s[15] = '\0';
  321. pos = strlcat(s, path, len);
  322. s[pos ] = '}';
  323. s[pos+1] = '\0';
  324. break;
  325. case DATABASE_QUERY_ENTRY_EDGE_MAGAZINE_ISSUE:
  326. s[0] = '{';
  327. s[1] = '\'';
  328. s[2] = 'e';
  329. s[3] = 'd';
  330. s[4] = 'g';
  331. s[5] = 'e';
  332. s[6] = '_';
  333. s[7] = 'i';
  334. s[8] = 's';
  335. s[9] = 's';
  336. s[10] = 'u';
  337. s[11] = 'e';
  338. s[12] = '\'';
  339. s[13] = ':';
  340. s[14] = '\0';
  341. pos = strlcat(s, path, len);
  342. s[pos ] = '}';
  343. s[pos+1] = '\0';
  344. break;
  345. case DATABASE_QUERY_ENTRY_FAMITSU_MAGAZINE_RATING:
  346. s[0] = '{';
  347. s[1] = '\'';
  348. s[2] = 'f';
  349. s[3] = 'a';
  350. s[4] = 'm';
  351. s[5] = 'i';
  352. s[6] = 't';
  353. s[7] = 's';
  354. s[8] = 'u';
  355. s[9] = '_';
  356. s[10] = 'r';
  357. s[11] = 'a';
  358. s[12] = 't';
  359. s[13] = 'i';
  360. s[14] = 'n';
  361. s[15] = 'g';
  362. s[16] = '\'';
  363. s[17] = ':';
  364. s[18] = '\0';
  365. pos = strlcat(s, path, len);
  366. s[pos ] = '}';
  367. s[pos+1] = '\0';
  368. break;
  369. case DATABASE_QUERY_ENTRY_RELEASEDATE_MONTH:
  370. s[0] = '{';
  371. s[1] = '\'';
  372. s[2] = 'r';
  373. s[3] = 'e';
  374. s[4] = 'l';
  375. s[5] = 'e';
  376. s[6] = 'a';
  377. s[7] = 's';
  378. s[8] = 'e';
  379. s[9] = 'm';
  380. s[10] = 'o';
  381. s[11] = 'n';
  382. s[12] = 't';
  383. s[13] = 'h';
  384. s[14] = '\'';
  385. s[15] = ':';
  386. s[16] = '\0';
  387. pos = strlcat(s, path, len);
  388. s[pos ] = '}';
  389. s[pos+1] = '\0';
  390. break;
  391. case DATABASE_QUERY_ENTRY_RELEASEDATE_YEAR:
  392. s[0] = '{';
  393. s[1] = '\'';
  394. s[2] = 'r';
  395. s[3] = 'e';
  396. s[4] = 'l';
  397. s[5] = 'e';
  398. s[6] = 'a';
  399. s[7] = 's';
  400. s[8] = 'e';
  401. s[9] = 'y';
  402. s[10] = 'e';
  403. s[11] = 'a';
  404. s[12] = 'r';
  405. s[13] = '\'';
  406. s[14] = ':';
  407. s[15] = '\0';
  408. pos = strlcat(s, path, len);
  409. s[pos ] = '}';
  410. s[pos+1] = '\0';
  411. break;
  412. case DATABASE_QUERY_ENTRY_MAX_USERS:
  413. s[0] = '{';
  414. s[1] = '\'';
  415. s[2] = 'u';
  416. s[3] = 's';
  417. s[4] = 'e';
  418. s[5] = 'r';
  419. s[6] = 's';
  420. s[7] = '\'';
  421. s[8] = ':';
  422. s[9] = '\0';
  423. pos = strlcat(s, path, len);
  424. s[pos ] = '}';
  425. s[pos+1] = '\0';
  426. break;
  427. case DATABASE_QUERY_NONE:
  428. s[0] = '{';
  429. s[1] = '\'';
  430. s[2] = '\'';
  431. s[3] = ':';
  432. s[4] = '\'';
  433. s[5] = ':';
  434. s[6] = '"';
  435. s[7] = '\0';
  436. pos = strlcat(s, path, len);
  437. s[pos ] = '"';
  438. s[pos+1] = '}';
  439. s[pos+2] = '\0';
  440. break;
  441. }
  442. return 0;
  443. }
  444. /*
  445. * NOTE: Allocates memory, it is the caller's responsibility to free the
  446. * memory after it is no longer required.
  447. */
  448. char *bin_to_hex_alloc(const uint8_t *data, size_t len)
  449. {
  450. size_t i;
  451. char *ret = (char*)malloc(len * 2 + 1);
  452. if (len && !ret)
  453. return NULL;
  454. for (i = 0; i < len; i++)
  455. snprintf(ret+i * 2, 3, "%02X", data[i]);
  456. return ret;
  457. }
  458. static int database_cursor_iterate(libretrodb_cursor_t *cur,
  459. database_info_t *db_info)
  460. {
  461. unsigned i;
  462. struct rmsgpack_dom_value item;
  463. const char* str = NULL;
  464. if (libretrodb_cursor_read_item(cur, &item) != 0)
  465. return -1;
  466. if (item.type != RDT_MAP)
  467. {
  468. rmsgpack_dom_value_free(&item);
  469. return 1;
  470. }
  471. db_info->analog_supported = -1;
  472. db_info->rumble_supported = -1;
  473. db_info->coop_supported = -1;
  474. for (i = 0; i < item.val.map.len; i++)
  475. {
  476. struct rmsgpack_dom_value *key = &item.val.map.items[i].key;
  477. struct rmsgpack_dom_value *val = &item.val.map.items[i].value;
  478. const char *val_string = NULL;
  479. if (!key || !val)
  480. continue;
  481. val_string = val->val.string.buff;
  482. str = key->val.string.buff;
  483. if (string_is_equal(str, "publisher"))
  484. {
  485. if (!string_is_empty(val_string))
  486. db_info->publisher = strdup(val_string);
  487. }
  488. else if (string_is_equal(str, "developer"))
  489. {
  490. if (!string_is_empty(val_string))
  491. db_info->developer = string_split(val_string, "|");
  492. }
  493. else if (string_is_equal(str, "serial"))
  494. {
  495. if (!string_is_empty(val_string))
  496. db_info->serial = strdup(val_string);
  497. }
  498. else if (string_is_equal(str, "rom_name"))
  499. {
  500. if (!string_is_empty(val_string))
  501. db_info->rom_name = strdup(val_string);
  502. }
  503. else if (string_is_equal(str, "name"))
  504. {
  505. if (!string_is_empty(val_string))
  506. db_info->name = strdup(val_string);
  507. }
  508. else if (string_is_equal(str, "description"))
  509. {
  510. if (!string_is_empty(val_string))
  511. db_info->description = strdup(val_string);
  512. }
  513. else if (string_is_equal(str, "genre"))
  514. {
  515. if (!string_is_empty(val_string))
  516. db_info->genre = strdup(val_string);
  517. }
  518. else if (string_is_equal(str, "category"))
  519. {
  520. if (!string_is_empty(val_string))
  521. db_info->category = strdup(val_string);
  522. }
  523. else if (string_is_equal(str, "language"))
  524. {
  525. if (!string_is_empty(val_string))
  526. db_info->language = strdup(val_string);
  527. }
  528. else if (string_is_equal(str, "region"))
  529. {
  530. if (!string_is_empty(val_string))
  531. db_info->region = strdup(val_string);
  532. }
  533. else if (string_is_equal(str, "score"))
  534. {
  535. if (!string_is_empty(val_string))
  536. db_info->score = strdup(val_string);
  537. }
  538. else if (string_is_equal(str, "media"))
  539. {
  540. if (!string_is_empty(val_string))
  541. db_info->media = strdup(val_string);
  542. }
  543. else if (string_is_equal(str, "controls"))
  544. {
  545. if (!string_is_empty(val_string))
  546. db_info->controls = strdup(val_string);
  547. }
  548. else if (string_is_equal(str, "artstyle"))
  549. {
  550. if (!string_is_empty(val_string))
  551. db_info->artstyle = strdup(val_string);
  552. }
  553. else if (string_is_equal(str, "gameplay"))
  554. {
  555. if (!string_is_empty(val_string))
  556. db_info->gameplay = strdup(val_string);
  557. }
  558. else if (string_is_equal(str, "narrative"))
  559. {
  560. if (!string_is_empty(val_string))
  561. db_info->narrative = strdup(val_string);
  562. }
  563. else if (string_is_equal(str, "pacing"))
  564. {
  565. if (!string_is_empty(val_string))
  566. db_info->pacing = strdup(val_string);
  567. }
  568. else if (string_is_equal(str, "perspective"))
  569. {
  570. if (!string_is_empty(val_string))
  571. db_info->perspective = strdup(val_string);
  572. }
  573. else if (string_is_equal(str, "setting"))
  574. {
  575. if (!string_is_empty(val_string))
  576. db_info->setting = strdup(val_string);
  577. }
  578. else if (string_is_equal(str, "visual"))
  579. {
  580. if (!string_is_empty(val_string))
  581. db_info->visual = strdup(val_string);
  582. }
  583. else if (string_is_equal(str, "vehicular"))
  584. {
  585. if (!string_is_empty(val_string))
  586. db_info->vehicular = strdup(val_string);
  587. }
  588. else if (string_is_equal(str, "origin"))
  589. {
  590. if (!string_is_empty(val_string))
  591. db_info->origin = strdup(val_string);
  592. }
  593. else if (string_is_equal(str, "franchise"))
  594. {
  595. if (!string_is_empty(val_string))
  596. db_info->franchise = strdup(val_string);
  597. }
  598. else if (string_ends_with_size(str, "_rating",
  599. strlen(str), STRLEN_CONST("_rating")))
  600. {
  601. if (string_is_equal(str, "bbfc_rating"))
  602. {
  603. if (!string_is_empty(val_string))
  604. db_info->bbfc_rating = strdup(val_string);
  605. }
  606. else if (string_is_equal(str, "esrb_rating"))
  607. {
  608. if (!string_is_empty(val_string))
  609. db_info->esrb_rating = strdup(val_string);
  610. }
  611. else if (string_is_equal(str, "elspa_rating"))
  612. {
  613. if (!string_is_empty(val_string))
  614. db_info->elspa_rating = strdup(val_string);
  615. }
  616. else if (string_is_equal(str, "cero_rating"))
  617. {
  618. if (!string_is_empty(val_string))
  619. db_info->cero_rating = strdup(val_string);
  620. }
  621. else if (string_is_equal(str, "pegi_rating"))
  622. {
  623. if (!string_is_empty(val_string))
  624. db_info->pegi_rating = strdup(val_string);
  625. }
  626. else if (string_is_equal(str, "edge_rating"))
  627. db_info->edge_magazine_rating = (unsigned)val->val.uint_;
  628. else if (string_is_equal(str, "famitsu_rating"))
  629. db_info->famitsu_magazine_rating = (unsigned)val->val.uint_;
  630. else if (string_is_equal(str, "tgdb_rating"))
  631. db_info->tgdb_rating = (unsigned)val->val.uint_;
  632. }
  633. else if (string_is_equal(str, "enhancement_hw"))
  634. {
  635. if (!string_is_empty(val_string))
  636. db_info->enhancement_hw = strdup(val_string);
  637. }
  638. else if (string_is_equal(str, "edge_review"))
  639. {
  640. if (!string_is_empty(val_string))
  641. db_info->edge_magazine_review = strdup(val_string);
  642. }
  643. else if (string_is_equal(str, "edge_issue"))
  644. db_info->edge_magazine_issue = (unsigned)val->val.uint_;
  645. else if (string_is_equal(str, "users"))
  646. db_info->max_users = (unsigned)val->val.uint_;
  647. else if (string_is_equal(str, "releasemonth"))
  648. db_info->releasemonth = (unsigned)val->val.uint_;
  649. else if (string_is_equal(str, "releaseyear"))
  650. db_info->releaseyear = (unsigned)val->val.uint_;
  651. else if (string_is_equal(str, "rumble"))
  652. db_info->rumble_supported = (int)val->val.uint_;
  653. else if (string_is_equal(str, "achievements"))
  654. db_info->achievements = (int)val->val.uint_;
  655. else if (string_is_equal(str, "console_exclusive"))
  656. db_info->console_exclusive = (int)val->val.uint_;
  657. else if (string_is_equal(str, "platform_exclusive"))
  658. db_info->platform_exclusive = (int)val->val.uint_;
  659. else if (string_is_equal(str, "coop"))
  660. db_info->coop_supported = (int)val->val.uint_;
  661. else if (string_is_equal(str, "analog"))
  662. db_info->analog_supported = (int)val->val.uint_;
  663. else if (string_is_equal(str, "size"))
  664. db_info->size = (unsigned)val->val.uint_;
  665. else if (string_is_equal(str, "crc"))
  666. {
  667. switch (val->val.binary.len)
  668. {
  669. case 1:
  670. db_info->crc32 = *(uint8_t*)val->val.binary.buff;
  671. break;
  672. case 2:
  673. db_info->crc32 = swap_if_little16(*(uint16_t*)val->val.binary.buff);
  674. break;
  675. case 4:
  676. db_info->crc32 = swap_if_little32(*(uint32_t*)val->val.binary.buff);
  677. break;
  678. default:
  679. db_info->crc32 = 0;
  680. break;
  681. }
  682. }
  683. else if (string_is_equal(str, "sha1"))
  684. db_info->sha1 = bin_to_hex_alloc(
  685. (uint8_t*)val->val.binary.buff, val->val.binary.len);
  686. else if (string_is_equal(str, "md5"))
  687. db_info->md5 = bin_to_hex_alloc(
  688. (uint8_t*)val->val.binary.buff, val->val.binary.len);
  689. }
  690. rmsgpack_dom_value_free(&item);
  691. return 0;
  692. }
  693. static int database_cursor_open(libretrodb_t *db,
  694. libretrodb_cursor_t *cur, const char *path, const char *query)
  695. {
  696. const char *error = NULL;
  697. libretrodb_query_t *q = NULL;
  698. if ((libretrodb_open(path, db)) != 0)
  699. return -1;
  700. if (query)
  701. q = (libretrodb_query_t*)libretrodb_query_compile(db, query,
  702. strlen(query), &error);
  703. if (error)
  704. goto error;
  705. if ((libretrodb_cursor_open(db, cur, q)) != 0)
  706. goto error;
  707. if (q)
  708. libretrodb_query_free(q);
  709. return 0;
  710. error:
  711. if (q)
  712. libretrodb_query_free(q);
  713. libretrodb_close(db);
  714. return -1;
  715. }
  716. static bool type_is_prioritized(const char *path)
  717. {
  718. const char *ext = path_get_extension(path);
  719. if (string_is_equal_noncase(ext, "cue"))
  720. return true;
  721. if (string_is_equal_noncase(ext, "gdi"))
  722. return true;
  723. return false;
  724. }
  725. static int dir_entry_compare(const void *left, const void *right)
  726. {
  727. const struct string_list_elem *le = (const struct string_list_elem*)left;
  728. const struct string_list_elem *re = (const struct string_list_elem*)right;
  729. bool l = type_is_prioritized(le->data);
  730. bool r = type_is_prioritized(re->data);
  731. return (int) r - (int) l;
  732. }
  733. database_info_handle_t *database_info_dir_init(const char *dir,
  734. enum database_type type, retro_task_t *task,
  735. bool show_hidden_files)
  736. {
  737. core_info_list_t *core_info_list = NULL;
  738. struct string_list *list = NULL;
  739. database_info_handle_t *db = (database_info_handle_t*)
  740. malloc(sizeof(*db));
  741. if (!db)
  742. return NULL;
  743. core_info_get_list(&core_info_list);
  744. if (!(list = dir_list_new(dir, core_info_list ? core_info_list->all_ext : NULL,
  745. false, show_hidden_files,
  746. false, true)))
  747. {
  748. free(db);
  749. return NULL;
  750. }
  751. /* dir list prioritize */
  752. qsort(list->elems, list->size, sizeof(*list->elems), dir_entry_compare);
  753. db->status = DATABASE_STATUS_ITERATE;
  754. db->type = type;
  755. db->list_ptr = 0;
  756. db->list = list;
  757. return db;
  758. }
  759. database_info_handle_t *database_info_file_init(const char *path,
  760. enum database_type type, retro_task_t *task)
  761. {
  762. union string_list_elem_attr attr;
  763. struct string_list *list = NULL;
  764. database_info_handle_t *db = (database_info_handle_t*)
  765. malloc(sizeof(*db));
  766. if (!db)
  767. return NULL;
  768. if (!(list = string_list_new()))
  769. {
  770. free(db);
  771. return NULL;
  772. }
  773. attr.i = 0;
  774. string_list_append(list, path, attr);
  775. db->status = DATABASE_STATUS_ITERATE;
  776. db->type = type;
  777. db->list_ptr = 0;
  778. db->list = list;
  779. return db;
  780. }
  781. void database_info_free(database_info_handle_t *db)
  782. {
  783. if (db)
  784. string_list_free(db->list);
  785. }
  786. database_info_list_t *database_info_list_new(
  787. const char *rdb_path, const char *query)
  788. {
  789. int ret = 0;
  790. unsigned k = 0;
  791. database_info_t *database_info = NULL;
  792. database_info_list_t *database_info_list = NULL;
  793. libretrodb_t *db = libretrodb_new();
  794. libretrodb_cursor_t *cur = libretrodb_cursor_new();
  795. if (!db || !cur)
  796. goto end;
  797. if ((database_cursor_open(db, cur, rdb_path, query) != 0))
  798. goto end;
  799. database_info_list = (database_info_list_t*)
  800. malloc(sizeof(*database_info_list));
  801. if (!database_info_list)
  802. goto end;
  803. database_info_list->count = 0;
  804. database_info_list->list = NULL;
  805. while (ret != -1)
  806. {
  807. database_info_t db_info = {0};
  808. ret = database_cursor_iterate(cur, &db_info);
  809. if (ret == 0)
  810. {
  811. database_info_t *db_ptr = NULL;
  812. database_info_t *new_ptr = (database_info_t*)
  813. realloc(database_info, (k+1) * sizeof(database_info_t));
  814. if (!new_ptr)
  815. {
  816. if (db_info.bbfc_rating)
  817. free(db_info.bbfc_rating);
  818. if (db_info.cero_rating)
  819. free(db_info.cero_rating);
  820. if (db_info.description)
  821. free(db_info.description);
  822. if (db_info.edge_magazine_review)
  823. free(db_info.edge_magazine_review);
  824. if (db_info.elspa_rating)
  825. free(db_info.elspa_rating);
  826. if (db_info.enhancement_hw)
  827. free(db_info.enhancement_hw);
  828. if (db_info.esrb_rating)
  829. free(db_info.esrb_rating);
  830. if (db_info.franchise)
  831. free(db_info.franchise);
  832. if (db_info.genre)
  833. free(db_info.genre);
  834. if (db_info.category)
  835. free(db_info.category);
  836. if (db_info.language)
  837. free(db_info.language);
  838. if (db_info.region)
  839. free(db_info.region);
  840. if (db_info.score)
  841. free(db_info.score);
  842. if (db_info.media)
  843. free(db_info.media);
  844. if (db_info.controls)
  845. free(db_info.controls);
  846. if (db_info.artstyle)
  847. free(db_info.artstyle);
  848. if (db_info.gameplay)
  849. free(db_info.gameplay);
  850. if (db_info.narrative)
  851. free(db_info.narrative);
  852. if (db_info.pacing)
  853. free(db_info.pacing);
  854. if (db_info.perspective)
  855. free(db_info.perspective);
  856. if (db_info.setting)
  857. free(db_info.setting);
  858. if (db_info.visual)
  859. free(db_info.visual);
  860. if (db_info.vehicular)
  861. free(db_info.vehicular);
  862. if (db_info.name)
  863. free(db_info.name);
  864. if (db_info.origin)
  865. free(db_info.origin);
  866. if (db_info.pegi_rating)
  867. free(db_info.pegi_rating);
  868. if (db_info.publisher)
  869. free(db_info.publisher);
  870. if (db_info.rom_name)
  871. free(db_info.rom_name);
  872. if (db_info.serial)
  873. free(db_info.serial);
  874. if (db_info.md5)
  875. free(db_info.md5);
  876. if (db_info.sha1)
  877. free(db_info.sha1);
  878. db_info.name = NULL;
  879. db_info.rom_name = NULL;
  880. db_info.serial = NULL;
  881. db_info.genre = NULL;
  882. db_info.description = NULL;
  883. db_info.publisher = NULL;
  884. db_info.developer = NULL;
  885. db_info.origin = NULL;
  886. db_info.franchise = NULL;
  887. db_info.edge_magazine_review = NULL;
  888. db_info.cero_rating = NULL;
  889. db_info.pegi_rating = NULL;
  890. db_info.enhancement_hw = NULL;
  891. db_info.elspa_rating = NULL;
  892. db_info.esrb_rating = NULL;
  893. db_info.bbfc_rating = NULL;
  894. db_info.sha1 = NULL;
  895. db_info.md5 = NULL;
  896. database_info_list_free(database_info_list);
  897. free(database_info);
  898. free(database_info_list);
  899. database_info_list = NULL;
  900. goto end;
  901. }
  902. database_info = new_ptr;
  903. db_ptr = &database_info[k];
  904. memcpy(db_ptr, &db_info, sizeof(*db_ptr));
  905. k++;
  906. }
  907. }
  908. database_info_list->list = database_info;
  909. database_info_list->count = k;
  910. end:
  911. if (db)
  912. {
  913. libretrodb_cursor_close(cur);
  914. libretrodb_close(db);
  915. libretrodb_free(db);
  916. }
  917. if (cur)
  918. libretrodb_cursor_free(cur);
  919. return database_info_list;
  920. }
  921. void database_info_list_free(database_info_list_t *database_info_list)
  922. {
  923. size_t i;
  924. if (!database_info_list)
  925. return;
  926. for (i = 0; i < database_info_list->count; i++)
  927. {
  928. database_info_t *info = &database_info_list->list[i];
  929. if (info->name)
  930. free(info->name);
  931. if (info->rom_name)
  932. free(info->rom_name);
  933. if (info->serial)
  934. free(info->serial);
  935. if (info->genre)
  936. free(info->genre);
  937. if (info->category)
  938. free(info->category);
  939. if (info->language)
  940. free(info->language);
  941. if (info->region)
  942. free(info->region);
  943. if (info->score)
  944. free(info->score);
  945. if (info->media)
  946. free(info->media);
  947. if (info->controls)
  948. free(info->controls);
  949. if (info->artstyle)
  950. free(info->artstyle);
  951. if (info->gameplay)
  952. free(info->gameplay);
  953. if (info->narrative)
  954. free(info->narrative);
  955. if (info->pacing)
  956. free(info->pacing);
  957. if (info->perspective)
  958. free(info->perspective);
  959. if (info->setting)
  960. free(info->setting);
  961. if (info->visual)
  962. free(info->visual);
  963. if (info->vehicular)
  964. free(info->vehicular);
  965. if (info->description)
  966. free(info->description);
  967. if (info->publisher)
  968. free(info->publisher);
  969. if (info->developer)
  970. string_list_free(info->developer);
  971. if (info->origin)
  972. free(info->origin);
  973. if (info->franchise)
  974. free(info->franchise);
  975. if (info->edge_magazine_review)
  976. free(info->edge_magazine_review);
  977. if (info->cero_rating)
  978. free(info->cero_rating);
  979. if (info->pegi_rating)
  980. free(info->pegi_rating);
  981. if (info->enhancement_hw)
  982. free(info->enhancement_hw);
  983. if (info->elspa_rating)
  984. free(info->elspa_rating);
  985. if (info->esrb_rating)
  986. free(info->esrb_rating);
  987. if (info->bbfc_rating)
  988. free(info->bbfc_rating);
  989. if (info->sha1)
  990. free(info->sha1);
  991. if (info->md5)
  992. free(info->md5);
  993. info->name = NULL;
  994. info->rom_name = NULL;
  995. info->serial = NULL;
  996. info->genre = NULL;
  997. info->description = NULL;
  998. info->publisher = NULL;
  999. info->developer = NULL;
  1000. info->origin = NULL;
  1001. info->franchise = NULL;
  1002. info->edge_magazine_review = NULL;
  1003. info->cero_rating = NULL;
  1004. info->pegi_rating = NULL;
  1005. info->enhancement_hw = NULL;
  1006. info->elspa_rating = NULL;
  1007. info->esrb_rating = NULL;
  1008. info->bbfc_rating = NULL;
  1009. info->sha1 = NULL;
  1010. info->md5 = NULL;
  1011. }
  1012. free(database_info_list->list);
  1013. }