PageRenderTime 59ms CodeModel.GetById 26ms RepoModel.GetById 0ms app.codeStats 0ms

/src/iOS/fronthlp.cpp

http://imame4all.googlecode.com/
C++ | 1364 lines | 1141 code | 177 blank | 46 comment | 416 complexity | ae2220192fc276fb8d5cd72041d7542c MD5 | raw file
Possible License(s): GPL-2.0
  1. #include "driver.h"
  2. #include "info.h"
  3. #include "audit.h"
  4. #include <stdio.h>
  5. #include <stdlib.h>
  6. #include <string.h>
  7. #include <sys/stat.h>
  8. #include <sys/errno.h>
  9. #include <dirent.h>
  10. #include <unzip.h>
  11. #include "zlib.h"
  12. #ifdef MESS
  13. #include "mess/msdos.h"
  14. #endif
  15. #ifdef printf
  16. #undef printf
  17. #endif
  18. int silentident,knownstatus;
  19. #define KNOWN_START 0
  20. #define KNOWN_ALL 1
  21. #define KNOWN_NONE 2
  22. #define KNOWN_SOME 3
  23. //extern unsigned int crc32 (unsigned int crc, const unsigned char *buf, unsigned int len);
  24. void get_rom_sample_path (int argc, char **argv, int game_index);
  25. static const struct GameDriver *gamedrv;
  26. /* compare string[8] using standard(?) DOS wildchars ('?' & '*') */
  27. /* for this to work correctly, the shells internal wildcard expansion */
  28. /* mechanism has to be disabled. Look into msdos.c */
  29. int strwildcmp(const char *sp1, const char *sp2)
  30. {
  31. char s1[9], s2[9];
  32. int i, l1, l2;
  33. char *p;
  34. strncpy(s1, sp1, 8); s1[8] = 0; if (s1[0] == 0) strcpy(s1, "*");
  35. strncpy(s2, sp2, 8); s2[8] = 0; if (s2[0] == 0) strcpy(s2, "*");
  36. p = strchr(s1, '*');
  37. if (p)
  38. {
  39. for (i = p - s1; i < 8; i++) s1[i] = '?';
  40. s1[8] = 0;
  41. }
  42. p = strchr(s2, '*');
  43. if (p)
  44. {
  45. for (i = p - s2; i < 8; i++) s2[i] = '?';
  46. s2[8] = 0;
  47. }
  48. l1 = strlen(s1);
  49. if (l1 < 8)
  50. {
  51. for (i = l1 + 1; i < 8; i++) s1[i] = ' ';
  52. s1[8] = 0;
  53. }
  54. l2 = strlen(s2);
  55. if (l2 < 8)
  56. {
  57. for (i = l2 + 1; i < 8; i++) s2[i] = ' ';
  58. s2[8] = 0;
  59. }
  60. for (i = 0; i < 8; i++)
  61. {
  62. if (s1[i] == '?' && s2[i] != '?') s1[i] = s2[i];
  63. if (s2[i] == '?' && s1[i] != '?') s2[i] = s1[i];
  64. }
  65. return strcasecmp(s1, s2);
  66. }
  67. /* Identifies a rom from from this checksum */
  68. void identify_rom(const char* name, int checksum, int length)
  69. {
  70. /* Nicola output format */
  71. #if 1
  72. int found = 0;
  73. /* remove directory name */
  74. int i;
  75. for (i = strlen(name)-1;i >= 0;i--)
  76. {
  77. if (name[i] == '/' || name[i] == '\\')
  78. {
  79. i++;
  80. break;
  81. }
  82. }
  83. if (!silentident)
  84. printf("%-12s ",&name[i]);
  85. for (i = 0; drivers[i]; i++)
  86. {
  87. const struct RomModule *romp;
  88. romp = drivers[i]->rom;
  89. while (romp && (romp->name || romp->offset || romp->length))
  90. {
  91. if (romp->name && romp->name != (char *)-1 && checksum == romp->crc)
  92. {
  93. if (!silentident)
  94. {
  95. if (found != 0)
  96. printf(" ");
  97. printf("= %-12s %s\n",romp->name,drivers[i]->description);
  98. }
  99. found++;
  100. }
  101. romp++;
  102. }
  103. }
  104. if (found == 0)
  105. {
  106. unsigned size = length;
  107. while (size && (size & 1) == 0) size >>= 1;
  108. if (size & ~1)
  109. {
  110. if (!silentident)
  111. printf("NOT A ROM\n");
  112. }
  113. else
  114. {
  115. if (!silentident)
  116. printf("NO MATCH\n");
  117. if (knownstatus == KNOWN_START)
  118. knownstatus = KNOWN_NONE;
  119. else if (knownstatus == KNOWN_ALL)
  120. knownstatus = KNOWN_SOME;
  121. }
  122. }
  123. else
  124. {
  125. if (knownstatus == KNOWN_START)
  126. knownstatus = KNOWN_ALL;
  127. else if (knownstatus == KNOWN_NONE)
  128. knownstatus = KNOWN_SOME;
  129. }
  130. #else
  131. /* New output format */
  132. int i;
  133. printf("%s\n",name);
  134. for (i = 0; drivers[i]; i++) {
  135. const struct RomModule *romp;
  136. romp = drivers[i]->rom;
  137. while (romp && (romp->name || romp->offset || romp->length))
  138. {
  139. if (romp->name && romp->name != (char *)-1 && checksum == romp->crc)
  140. {
  141. printf("\t%s/%s %s, %s, %s\n",drivers[i]->name,romp->name,
  142. drivers[i]->description,
  143. drivers[i]->manufacturer,
  144. drivers[i]->year);
  145. }
  146. romp++;
  147. }
  148. }
  149. #endif
  150. }
  151. /* Identifies a file from from this checksum */
  152. void identify_file(const char* name)
  153. {
  154. FILE *f;
  155. int length;
  156. char* data;
  157. f = fopen(name,"rb");
  158. if (!f) {
  159. return;
  160. }
  161. /* determine length of file */
  162. if (fseek (f, 0L, SEEK_END)!=0) {
  163. fclose(f);
  164. return;
  165. }
  166. length = ftell(f);
  167. if (length == -1L) {
  168. fclose(f);
  169. return;
  170. }
  171. /* empty file */
  172. if (!length) {
  173. fclose(f);
  174. return;
  175. }
  176. /* allocate space for entire file */
  177. data = (char*)malloc(length);
  178. if (!data) {
  179. fclose(f);
  180. return;
  181. }
  182. if (fseek (f, 0L, SEEK_SET)!=0) {
  183. free(data);
  184. fclose(f);
  185. return;
  186. }
  187. if (fread(data, 1, length, f) != length) {
  188. free(data);
  189. fclose(f);
  190. return;
  191. }
  192. fclose(f);
  193. identify_rom(name, crc32(0L,(const unsigned char*)data,length),length);
  194. free(data);
  195. }
  196. void identify_zip(const char* zipname)
  197. {
  198. struct zipent* ent;
  199. ZIP* zip = openzip( zipname );
  200. if (!zip)
  201. return;
  202. while ((ent = readzip(zip))) {
  203. /* Skip empty file and directory */
  204. if (ent->uncompressed_size!=0) {
  205. char* buf = (char*)malloc(strlen(zipname)+1+strlen(ent->name)+1);
  206. sprintf(buf,"%s/%s",zipname,ent->name);
  207. identify_rom(buf,ent->crc32,ent->uncompressed_size);
  208. free(buf);
  209. }
  210. }
  211. closezip(zip);
  212. }
  213. void romident(const char* name, int enter_dirs);
  214. void identify_dir(const char* dirname)
  215. {
  216. DIR *dir;
  217. struct dirent *ent;
  218. dir = opendir(dirname);
  219. if (!dir) {
  220. return;
  221. }
  222. ent = readdir(dir);
  223. while (ent) {
  224. /* Skip special files */
  225. if (ent->d_name[0]!='.') {
  226. char* buf = (char*)malloc(strlen(dirname)+1+strlen(ent->d_name)+1);
  227. sprintf(buf,"%s/%s",dirname,ent->d_name);
  228. romident(buf,0);
  229. free(buf);
  230. }
  231. ent = readdir(dir);
  232. }
  233. closedir(dir);
  234. }
  235. void romident(const char* name,int enter_dirs) {
  236. struct stat s;
  237. if (stat(name,&s) != 0) {
  238. printf("%s: %s\n",name,strerror(errno));
  239. return;
  240. }
  241. if (S_ISDIR(s.st_mode)) {
  242. if (enter_dirs)
  243. identify_dir(name);
  244. } else {
  245. unsigned l = strlen(name);
  246. if (l>=4 && strcasecmp(name+l-4,".zip")==0)
  247. identify_zip(name);
  248. else
  249. identify_file(name);
  250. return;
  251. }
  252. }
  253. #ifndef MESS
  254. enum { LIST_LIST = 1, LIST_LISTINFO, LIST_LISTFULL, LIST_LISTSAMDIR, LIST_LISTROMS, LIST_LISTSAMPLES,
  255. LIST_LMR, LIST_LISTDETAILS, LIST_GAMELISTHEADER, LIST_GAMELISTFOOTER, LIST_GAMELIST,
  256. LIST_LISTGAMES, LIST_LISTCLONES,
  257. LIST_WRONGORIENTATION, LIST_WRONGFPS, LIST_LISTCRC, LIST_LISTDUPCRC, LIST_WRONGMERGE,
  258. LIST_LISTROMSIZE, LIST_LISTCPU, LIST_SOURCEFILE };
  259. #else
  260. enum { LIST_LIST = 1, LIST_LISTINFO, LIST_LISTFULL, LIST_LISTSAMDIR, LIST_LISTROMS, LIST_LISTSAMPLES,
  261. LIST_LMR, LIST_LISTDETAILS, LIST_GAMELISTHEADER, LIST_GAMELISTFOOTER, LIST_GAMELIST,
  262. LIST_LISTGAMES, LIST_LISTCLONES,
  263. LIST_WRONGORIENTATION, LIST_WRONGFPS, LIST_LISTCRC, LIST_LISTDUPCRC, LIST_WRONGMERGE,
  264. LIST_LISTROMSIZE, LIST_LISTCPU, LIST_SOURCEFILE, LIST_MESSINFO };
  265. #endif
  266. #define VERIFY_ROMS 0x00000001
  267. #define VERIFY_SAMPLES 0x00000002
  268. #define VERIFY_VERBOSE 0x00000004
  269. #define VERIFY_TERSE 0x00000008
  270. void CLIB_DECL terse_printf(char *fmt,...)
  271. {
  272. /* no-op */
  273. }
  274. int frontend_help (int argc, char **argv)
  275. {
  276. int i, j;
  277. int list = 0;
  278. int listclones = 1;
  279. int verify = 0;
  280. int ident = 0;
  281. int help = 1; /* by default is TRUE */
  282. char gamename[9];
  283. /* covert '/' in '-' */
  284. for (i = 1;i < argc;i++) if (argv[i][0] == '/') argv[i][0] = '-';
  285. /* by default display the help unless */
  286. /* a game or an utility are specified */
  287. strcpy(gamename, "");
  288. for (i = 1;i < argc;i++)
  289. {
  290. /* find the FIRST "gamename" field (without '-') */
  291. if ((strlen(gamename) == 0) && (argv[i][0] != '-'))
  292. {
  293. /* check if a filename was entered as the game name */
  294. /* and remove any remaining portion of file extension */
  295. for (j = 0;j < 8 && argv[i][j] && argv[i][j] != '.';j++)
  296. gamename[j] = argv[i][j];
  297. gamename[j] = 0;
  298. }
  299. }
  300. for (i = 1; i < argc; i++)
  301. {
  302. /* check for front-end utilities */
  303. if (!strcasecmp(argv[i],"-list")) list = LIST_LIST;
  304. if (!strcasecmp(argv[i],"-listinfo")) list = LIST_LISTINFO;
  305. if (!strcasecmp(argv[i],"-listfull")) list = LIST_LISTFULL;
  306. if (!strcasecmp(argv[i],"-listdetails")) list = LIST_LISTDETAILS; /* A detailed MAMELIST.TXT type roms lister */
  307. if (!strcasecmp(argv[i],"-gamelistheader")) list = LIST_GAMELISTHEADER; /* GAMELIST.TXT */
  308. if (!strcasecmp(argv[i],"-gamelistfooter")) list = LIST_GAMELISTFOOTER; /* GAMELIST.TXT */
  309. if (!strcasecmp(argv[i],"-gamelist")) list = LIST_GAMELIST; /* GAMELIST.TXT */
  310. if (!strcasecmp(argv[i],"-listgames")) list = LIST_LISTGAMES;
  311. if (!strcasecmp(argv[i],"-listclones")) list = LIST_LISTCLONES;
  312. if (!strcasecmp(argv[i],"-listsamdir")) list = LIST_LISTSAMDIR;
  313. if (!strcasecmp(argv[i],"-listcrc")) list = LIST_LISTCRC;
  314. if (!strcasecmp(argv[i],"-listdupcrc")) list = LIST_LISTDUPCRC;
  315. if (!strcasecmp(argv[i],"-listwrongmerge")) list = LIST_WRONGMERGE;
  316. if (!strcasecmp(argv[i],"-listromsize")) list = LIST_LISTROMSIZE;
  317. if (!strcasecmp(argv[i],"-listcpu")) list = LIST_LISTCPU;
  318. if (!strcasecmp(argv[i],"-wrongorientation")) list = LIST_WRONGORIENTATION;
  319. if (!strcasecmp(argv[i],"-wrongfps")) list = LIST_WRONGFPS;
  320. if (!strcasecmp(argv[i],"-noclones")) listclones = 0;
  321. #ifdef MESS
  322. if (!strcasecmp(argv[i],"-listdevices")) list = LIST_MESSINFO;
  323. if (!strcasecmp(argv[i],"-listtext")) list = LIST_MESSINFO;
  324. if (!strcasecmp(argv[i],"-createdir")) list = LIST_MESSINFO;
  325. #endif
  326. /* these options REQUIRES gamename field to work */
  327. if (strlen(gamename) > 0)
  328. {
  329. if (!strcasecmp(argv[i],"-listroms")) list = LIST_LISTROMS;
  330. if (!strcasecmp(argv[i],"-listsamples")) list = LIST_LISTSAMPLES;
  331. if (!strcasecmp(argv[i],"-verifyroms")) verify = VERIFY_ROMS;
  332. if (!strcasecmp(argv[i],"-verifysets")) verify = VERIFY_ROMS|VERIFY_VERBOSE|VERIFY_TERSE;
  333. if (!strcasecmp(argv[i],"-vset")) verify = VERIFY_ROMS|VERIFY_VERBOSE;
  334. if (!strcasecmp(argv[i],"-verifysamples")) verify = VERIFY_SAMPLES|VERIFY_VERBOSE;
  335. if (!strcasecmp(argv[i],"-vsam")) verify = VERIFY_SAMPLES|VERIFY_VERBOSE;
  336. if (!strcasecmp(argv[i],"-romident")) ident = 1;
  337. if (!strcasecmp(argv[i],"-isknown")) ident = 2;
  338. if (!strcasecmp(argv[i],"-sourcefile")) list = LIST_SOURCEFILE;
  339. }
  340. }
  341. if ((strlen(gamename)> 0) || list || verify) help = 0;
  342. for (i = 1;i < argc;i++)
  343. {
  344. /* ...however, I WANT the help! */
  345. if (!strcasecmp(argv[i],"-?") || !strcasecmp(argv[i],"-h") || !strcasecmp(argv[i],"-help"))
  346. help = 1;
  347. }
  348. if (help) /* brief help - useful to get current version info */
  349. {
  350. #ifndef MESS
  351. printf("M.A.M.E. v%s - Multiple Arcade Machine Emulator\n"
  352. "Copyright (C) 1997-2000 by Nicola Salmoria and the MAME Team\n\n",build_version);
  353. showdisclaimer();
  354. printf("Usage: MAME gamename [options]\n\n"
  355. " MAME -list for a brief list of supported games\n"
  356. " MAME -listfull for a full list of supported games\n\n"
  357. "See readme.txt for a complete list of options.\n");
  358. #else
  359. showmessinfo();
  360. #endif
  361. return 0;
  362. }
  363. switch (list) /* front-end utilities ;) */
  364. {
  365. #ifdef MESS
  366. case LIST_MESSINFO: /* all mess specific calls here */
  367. {
  368. for (i=1;i<argc;i++)
  369. {
  370. /* list all mess info options here */
  371. if (
  372. !strcasecmp(argv[i],"-listdevices") |
  373. !strcasecmp(argv[i],"-listtext") |
  374. !strcasecmp(argv[i],"-createdir")
  375. )
  376. {
  377. /* send the gamename and arg to mess.c */
  378. list_mess_info(gamename, argv[i], listclones);
  379. }
  380. }
  381. return 0;
  382. break;
  383. }
  384. #endif
  385. case LIST_LIST: /* simple games list */
  386. #ifndef MESS
  387. printf("\nMAME currently supports the following games:\n\n");
  388. #else
  389. printf("\nMESS currently supports the following systems:\n\n");
  390. #endif
  391. i = 0; j = 0;
  392. while (drivers[i])
  393. {
  394. if ((listclones || drivers[i]->clone_of == 0
  395. || (drivers[i]->clone_of->flags & NOT_A_DRIVER)
  396. ) && !strwildcmp(gamename, drivers[i]->name))
  397. {
  398. printf("%-8s",drivers[i]->name);
  399. j++;
  400. if (!(j % 8)) printf("\n");
  401. else printf(" ");
  402. }
  403. i++;
  404. }
  405. if (j % 8) printf("\n");
  406. printf("\n");
  407. if (j != i) printf("Total ROM sets displayed: %4d - ", j);
  408. #ifndef MESS
  409. printf("Total ROM sets supported: %4d\n", i);
  410. #else
  411. printf("Total Systems supported: %4d\n", i);
  412. #endif
  413. return 0;
  414. break;
  415. case LIST_LISTFULL: /* games list with descriptions */
  416. printf("Name: Description:\n");
  417. i = 0;
  418. while (drivers[i])
  419. {
  420. if ((listclones || drivers[i]->clone_of == 0
  421. || (drivers[i]->clone_of->flags & NOT_A_DRIVER)
  422. ) && !strwildcmp(gamename, drivers[i]->name))
  423. {
  424. char name[200];
  425. printf("%-10s",drivers[i]->name);
  426. strcpy(name,drivers[i]->description);
  427. /* Move leading "The" to the end */
  428. if (strstr(name," (")) *strstr(name," (") = 0;
  429. if (strncmp(name,"The ",4) == 0)
  430. {
  431. printf("\"%s",name+4);
  432. printf(", The");
  433. }
  434. else
  435. printf("\"%s",name);
  436. /* print the additional description only if we are listing clones */
  437. if (listclones)
  438. {
  439. if (strchr(drivers[i]->description,'('))
  440. printf(" %s",strchr(drivers[i]->description,'('));
  441. }
  442. printf("\"\n");
  443. }
  444. i++;
  445. }
  446. return 0;
  447. break;
  448. case LIST_LISTSAMDIR: /* games list with samples directories */
  449. printf("Name: Samples dir:\n");
  450. i = 0;
  451. while (drivers[i])
  452. {
  453. if ((listclones || drivers[i]->clone_of == 0
  454. || (drivers[i]->clone_of->flags & NOT_A_DRIVER)
  455. ) && !strwildcmp(gamename, drivers[i]->name))
  456. {
  457. #if (HAS_SAMPLES)
  458. for( j = 0; drivers[i]->drv->sound[j].sound_type && j < MAX_SOUND; j++ )
  459. {
  460. const char **samplenames;
  461. if( drivers[i]->drv->sound[j].sound_type != SOUND_SAMPLES )
  462. continue;
  463. samplenames = ((struct Samplesinterface *)drivers[i]->drv->sound[j].sound_interface)->samplenames;
  464. if (samplenames != 0 && samplenames[0] != 0)
  465. {
  466. printf("%-10s",drivers[i]->name);
  467. if (samplenames[0][0] == '*')
  468. printf("%s\n",samplenames[0]+1);
  469. else
  470. printf("%s\n",drivers[i]->name);
  471. }
  472. }
  473. #endif
  474. }
  475. i++;
  476. }
  477. return 0;
  478. break;
  479. case LIST_LISTROMS: /* game roms list or */
  480. case LIST_LISTSAMPLES: /* game samples list */
  481. j = 0;
  482. while (drivers[j] && (strcasecmp(gamename,drivers[j]->name) != 0))
  483. j++;
  484. if (drivers[j] == 0)
  485. {
  486. printf("Game \"%s\" not supported!\n",gamename);
  487. return 1;
  488. }
  489. gamedrv = drivers[j];
  490. if (list == LIST_LISTROMS)
  491. printromlist(gamedrv->rom,gamename);
  492. else
  493. {
  494. #if (HAS_SAMPLES)
  495. int k;
  496. for( k = 0; gamedrv->drv->sound[k].sound_type && k < MAX_SOUND; k++ )
  497. {
  498. const char **samplenames;
  499. if( gamedrv->drv->sound[k].sound_type != SOUND_SAMPLES )
  500. continue;
  501. samplenames = ((struct Samplesinterface *)gamedrv->drv->sound[k].sound_interface)->samplenames;
  502. if (samplenames != 0 && samplenames[0] != 0)
  503. {
  504. i = 0;
  505. while (samplenames[i] != 0)
  506. {
  507. printf("%s\n",samplenames[i]);
  508. i++;
  509. }
  510. }
  511. }
  512. #endif
  513. }
  514. return 0;
  515. break;
  516. case LIST_LMR:
  517. {
  518. int total;
  519. total = 0;
  520. for (i = 0; drivers[i]; i++)
  521. total++;
  522. for (i = 0; drivers[i]; i++)
  523. {
  524. static int first_missing = 1;
  525. get_rom_sample_path (argc, argv, i);
  526. if (RomsetMissing (i))
  527. {
  528. if (first_missing)
  529. {
  530. first_missing = 0;
  531. printf ("game clone of description\n");
  532. printf ("-------- -------- -----------\n");
  533. }
  534. printf ("%-10s%-10s%s\n",
  535. drivers[i]->name,
  536. (drivers[i]->clone_of) ? drivers[i]->clone_of->name : "",
  537. drivers[i]->description);
  538. }
  539. fprintf(stderr,"%d%%\r",100 * (i+1) / total);
  540. }
  541. }
  542. return 0;
  543. break;
  544. case LIST_LISTDETAILS: /* A detailed MAMELIST.TXT type roms lister */
  545. /* First, we shall print the header */
  546. printf(" romname driver ");
  547. for(j=0;j<MAX_CPU;j++) printf("cpu %d ",j+1);
  548. for(j=0;j<MAX_SOUND;j++) printf("sound %d ",j+1);
  549. printf("name\n");
  550. printf("-------- ---------- ");
  551. for(j=0;j<MAX_CPU;j++) printf("-------- ");
  552. for(j=0;j<MAX_SOUND;j++) printf("----------- ");
  553. printf("--------------------------\n");
  554. /* Let's cycle through the drivers */
  555. i = 0;
  556. while (drivers[i])
  557. {
  558. if ((listclones || drivers[i]->clone_of == 0
  559. || (drivers[i]->clone_of->flags & NOT_A_DRIVER)
  560. ) && !strwildcmp(gamename, drivers[i]->name))
  561. {
  562. /* Dummy structs to fetch the information from */
  563. const struct MachineDriver *x_driver = drivers[i]->drv;
  564. const struct MachineCPU *x_cpu = x_driver->cpu;
  565. const struct MachineSound *x_sound = x_driver->sound;
  566. /* First, the rom name */
  567. printf("%-8s ",drivers[i]->name);
  568. #ifndef MESS
  569. /* source file (skip the leading "src/drivers/" */
  570. printf("%-10s ",&drivers[i]->source_file[12]);
  571. #else
  572. /* source file (skip the leading "src/mess/systems/" */
  573. printf("%-10s ",&drivers[i]->source_file[17]);
  574. #endif
  575. /* Then, cpus */
  576. for(j=0;j<MAX_CPU;j++)
  577. {
  578. if (x_cpu[j].cpu_type & CPU_AUDIO_CPU)
  579. printf("[%-6s] ",cputype_name(x_cpu[j].cpu_type));
  580. else
  581. printf("%-8s ",cputype_name(x_cpu[j].cpu_type));
  582. }
  583. /* Then, sound chips */
  584. for(j=0;j<MAX_SOUND;j++)
  585. {
  586. if (sound_num(&x_sound[j]))
  587. {
  588. printf("%dx",sound_num(&x_sound[j]));
  589. printf("%-9s ",sound_name(&x_sound[j]));
  590. }
  591. else
  592. printf("%-11s ",sound_name(&x_sound[j]));
  593. }
  594. /* Lastly, the name of the game and a \newline */
  595. printf("%s\n",drivers[i]->description);
  596. }
  597. i++;
  598. }
  599. return 0;
  600. break;
  601. case LIST_GAMELISTHEADER: /* GAMELIST.TXT */
  602. printf("This is the complete list of games supported by MAME %s\n",build_version);
  603. if (!listclones)
  604. printf("Variants of the same game are not included, you can use the -listclones command\n"
  605. "to get a list of the alternate versions of a given game.\n");
  606. printf("\n"
  607. "The list is generated automatically and is not 100%% accurate, particularly in\n"
  608. "the \"Screen Flip\" column. Please let us know of any errors you find so we can\n"
  609. "correct them.\n"
  610. "\n"
  611. "The meanings of the columns are as follows:\n"
  612. "Working - \"No\" means that the emulation has shortcomings that cause the game\n"
  613. " not to work correctly. This can be anywhere from just showing a black screen\n"
  614. " to being playable with major problems.\n"
  615. "Correct Colors - \"Yes\" means that colors should be identical to the original,\n"
  616. " \"Close\" that they are very similar but wrong in places, \"No\" that they are\n"
  617. " completely wrong. In some cases, we were not able to find the color PROMs of\n"
  618. " the game. Those PROMs will be reported as \"NO GOOD DUMP KNOWN\" on startup,\n"
  619. " and the game will have wrong colors. The game is still reported as \"Yes\" in\n"
  620. " this column, because the code to handle the color PROMs is in the driver and\n"
  621. " if you provide them colors will be correct.\n"
  622. "Sound - \"Partial\" means that sound support is either incomplete or not entirely\n"
  623. " accurate. Note that, due to analog circuitry which is difficult to emulate,\n"
  624. " sound may be significantly different from the real board. A common case is\n"
  625. " the presence of low pass filters that make the real board sound less harsh\n"
  626. " than the emulation.\n"
  627. "Screen Flip - A large number of games have a dip switch setting for \"Cocktail\"\n"
  628. " cabinet, meaning that the players sit in front of each other, and the screen\n"
  629. " is flipped when player 2 is playing. Some games also have a \"Flip Screen\" dip\n"
  630. " switch. Those need special support in the driver, which is missing in many\n"
  631. " cases.\n"
  632. "Internal Name - This is the unique name that should be specified on the command\n"
  633. " line to run the game. ROMs must be placed in the ROM path, either in a .zip\n"
  634. " file or in a subdirectory of the same name. The former is suggested, because\n"
  635. " the files will be identified by their CRC instead of requiring specific\n"
  636. " names.\n\n");
  637. printf("+----------------------------------+-------+-------+-------+-------+----------+\n");
  638. printf("| | |Correct| |Screen | Internal |\n");
  639. printf("| Game Name |Working|Colors | Sound | Flip | Name |\n");
  640. printf("+----------------------------------+-------+-------+-------+-------+----------+\n");
  641. return 0;
  642. break;
  643. case LIST_GAMELISTFOOTER: /* GAMELIST.TXT */
  644. printf("+----------------------------------+-------+-------+-------+-------+----------+\n\n");
  645. printf("(1) There are variants of the game (usually bootlegs) that work correctly\n");
  646. #if (HAS_SAMPLES)
  647. printf("(2) Needs samples provided separately\n");
  648. #endif
  649. return 0;
  650. break;
  651. case LIST_GAMELIST: /* GAMELIST.TXT */
  652. i = 0;
  653. while (drivers[i])
  654. {
  655. if ((listclones || drivers[i]->clone_of == 0
  656. || (drivers[i]->clone_of->flags & NOT_A_DRIVER)
  657. ) && !strwildcmp(gamename, drivers[i]->name))
  658. {
  659. char name[200],name_ref[200];
  660. strcpy(name,drivers[i]->description);
  661. /* Move leading "The" to the end */
  662. if (strstr(name," (")) *strstr(name," (") = 0;
  663. if (strncmp(name,"The ",4) == 0)
  664. {
  665. sprintf(name_ref,"%s, The ",name+4);
  666. }
  667. else
  668. sprintf(name_ref,"%s ",name);
  669. /* print the additional description only if we are listing clones */
  670. if (listclones)
  671. {
  672. if (strchr(drivers[i]->description,'('))
  673. strcat(name_ref,strchr(drivers[i]->description,'('));
  674. }
  675. printf("| %-33.33s",name_ref);
  676. if (drivers[i]->flags & (GAME_NOT_WORKING | GAME_UNEMULATED_PROTECTION))
  677. {
  678. const struct GameDriver *maindrv;
  679. int foundworking;
  680. if (drivers[i]->clone_of && !(drivers[i]->clone_of->flags & NOT_A_DRIVER))
  681. maindrv = drivers[i]->clone_of;
  682. else maindrv = drivers[i];
  683. foundworking = 0;
  684. j = 0;
  685. while (drivers[j])
  686. {
  687. if (drivers[j] == maindrv || drivers[j]->clone_of == maindrv)
  688. {
  689. if ((drivers[j]->flags & (GAME_NOT_WORKING | GAME_UNEMULATED_PROTECTION)) == 0)
  690. {
  691. foundworking = 1;
  692. break;
  693. }
  694. }
  695. j++;
  696. }
  697. if (foundworking)
  698. printf("| No(1) ");
  699. else
  700. printf("| No ");
  701. }
  702. else
  703. printf("| Yes ");
  704. if (drivers[i]->flags & GAME_WRONG_COLORS)
  705. printf("| No ");
  706. else if (drivers[i]->flags & GAME_IMPERFECT_COLORS)
  707. printf("| Close ");
  708. else
  709. printf("| Yes ");
  710. {
  711. const char **samplenames = 0;
  712. #if (HAS_SAMPLES)
  713. for (j = 0;drivers[i]->drv->sound[j].sound_type && j < MAX_SOUND; j++)
  714. {
  715. if (drivers[i]->drv->sound[j].sound_type == SOUND_SAMPLES)
  716. {
  717. samplenames = ((struct Samplesinterface *)drivers[i]->drv->sound[j].sound_interface)->samplenames;
  718. break;
  719. }
  720. }
  721. #endif
  722. if (drivers[i]->flags & GAME_NO_SOUND)
  723. printf("| No ");
  724. else if (drivers[i]->flags & GAME_IMPERFECT_SOUND)
  725. {
  726. if (samplenames)
  727. printf("|Part(2)");
  728. else
  729. printf("|Partial");
  730. }
  731. else
  732. {
  733. if (samplenames)
  734. printf("| Yes(2)");
  735. else
  736. printf("| Yes ");
  737. }
  738. }
  739. if (drivers[i]->flags & GAME_NO_COCKTAIL)
  740. printf("| No ");
  741. else
  742. printf("| Yes ");
  743. printf("| %-8s |\n",drivers[i]->name);
  744. }
  745. i++;
  746. }
  747. return 0;
  748. break;
  749. case LIST_LISTGAMES: /* list games, production year, manufacturer */
  750. i = 0;
  751. while (drivers[i])
  752. {
  753. if ((listclones || drivers[i]->clone_of == 0
  754. || (drivers[i]->clone_of->flags & NOT_A_DRIVER)
  755. ) && !strwildcmp(gamename, drivers[i]->description))
  756. {
  757. char name[200];
  758. printf("%-5s%-36s ",drivers[i]->year,drivers[i]->manufacturer);
  759. strcpy(name,drivers[i]->description);
  760. /* Move leading "The" to the end */
  761. if (strstr(name," (")) *strstr(name," (") = 0;
  762. if (strncmp(name,"The ",4) == 0)
  763. {
  764. printf("%s",name+4);
  765. printf(", The");
  766. }
  767. else
  768. printf("%s",name);
  769. /* print the additional description only if we are listing clones */
  770. if (listclones)
  771. {
  772. if (strchr(drivers[i]->description,'('))
  773. printf(" %s",strchr(drivers[i]->description,'('));
  774. }
  775. printf("\n");
  776. }
  777. i++;
  778. }
  779. return 0;
  780. break;
  781. case LIST_LISTCLONES: /* list clones */
  782. printf("Name: Clone of:\n");
  783. i = 0;
  784. while (drivers[i])
  785. {
  786. if (drivers[i]->clone_of && !(drivers[i]->clone_of->flags & NOT_A_DRIVER) &&
  787. (!strwildcmp(gamename,drivers[i]->name)
  788. || !strwildcmp(gamename,drivers[i]->clone_of->name)))
  789. printf("%-8s %-8s\n",drivers[i]->name,drivers[i]->clone_of->name);
  790. i++;
  791. }
  792. return 0;
  793. break;
  794. case LIST_WRONGORIENTATION: /* list drivers which incorrectly use the orientation and visible area fields */
  795. while (drivers[i])
  796. {
  797. if ((drivers[i]->drv->video_attributes & VIDEO_TYPE_VECTOR) == 0 &&
  798. (drivers[i]->clone_of == 0
  799. || (drivers[i]->clone_of->flags & NOT_A_DRIVER)) &&
  800. drivers[i]->drv->default_visible_area.max_x - drivers[i]->drv->default_visible_area.min_x + 1 <=
  801. drivers[i]->drv->default_visible_area.max_y - drivers[i]->drv->default_visible_area.min_y + 1)
  802. {
  803. if (strcmp(drivers[i]->name,"crater") &&
  804. strcmp(drivers[i]->name,"mpatrol") &&
  805. strcmp(drivers[i]->name,"troangel") &&
  806. strcmp(drivers[i]->name,"travrusa") &&
  807. strcmp(drivers[i]->name,"kungfum") &&
  808. strcmp(drivers[i]->name,"battroad") &&
  809. strcmp(drivers[i]->name,"vigilant") &&
  810. strcmp(drivers[i]->name,"sonson") &&
  811. strcmp(drivers[i]->name,"brkthru") &&
  812. strcmp(drivers[i]->name,"darwin") &&
  813. strcmp(drivers[i]->name,"exprraid") &&
  814. strcmp(drivers[i]->name,"sidetrac") &&
  815. strcmp(drivers[i]->name,"targ") &&
  816. strcmp(drivers[i]->name,"spectar") &&
  817. strcmp(drivers[i]->name,"venture") &&
  818. strcmp(drivers[i]->name,"mtrap") &&
  819. strcmp(drivers[i]->name,"pepper2") &&
  820. strcmp(drivers[i]->name,"hardhat") &&
  821. strcmp(drivers[i]->name,"fax") &&
  822. strcmp(drivers[i]->name,"circus") &&
  823. strcmp(drivers[i]->name,"robotbwl") &&
  824. strcmp(drivers[i]->name,"crash") &&
  825. strcmp(drivers[i]->name,"ripcord") &&
  826. strcmp(drivers[i]->name,"starfire") &&
  827. strcmp(drivers[i]->name,"fireone") &&
  828. strcmp(drivers[i]->name,"renegade") &&
  829. strcmp(drivers[i]->name,"battlane") &&
  830. strcmp(drivers[i]->name,"megatack") &&
  831. strcmp(drivers[i]->name,"killcom") &&
  832. strcmp(drivers[i]->name,"challeng") &&
  833. strcmp(drivers[i]->name,"kaos") &&
  834. strcmp(drivers[i]->name,"formatz") &&
  835. strcmp(drivers[i]->name,"bankp") &&
  836. strcmp(drivers[i]->name,"liberatr") &&
  837. strcmp(drivers[i]->name,"toki") &&
  838. strcmp(drivers[i]->name,"stactics") &&
  839. strcmp(drivers[i]->name,"sprint1") &&
  840. strcmp(drivers[i]->name,"sprint2") &&
  841. strcmp(drivers[i]->name,"nitedrvr") &&
  842. strcmp(drivers[i]->name,"punchout") &&
  843. strcmp(drivers[i]->name,"spnchout") &&
  844. strcmp(drivers[i]->name,"armwrest") &&
  845. strcmp(drivers[i]->name,"route16") &&
  846. strcmp(drivers[i]->name,"stratvox") &&
  847. strcmp(drivers[i]->name,"irobot") &&
  848. strcmp(drivers[i]->name,"leprechn") &&
  849. strcmp(drivers[i]->name,"starcrus") &&
  850. strcmp(drivers[i]->name,"astrof") &&
  851. strcmp(drivers[i]->name,"tomahawk") &&
  852. 1)
  853. printf("%s %dx%d\n",drivers[i]->name,
  854. drivers[i]->drv->default_visible_area.max_x - drivers[i]->drv->default_visible_area.min_x + 1,
  855. drivers[i]->drv->default_visible_area.max_y - drivers[i]->drv->default_visible_area.min_y + 1);
  856. }
  857. i++;
  858. }
  859. return 0;
  860. break;
  861. case LIST_WRONGFPS: /* list drivers with too high frame rate */
  862. while (drivers[i])
  863. {
  864. if ((drivers[i]->drv->video_attributes & VIDEO_TYPE_VECTOR) == 0 &&
  865. (drivers[i]->clone_of == 0
  866. || (drivers[i]->clone_of->flags & NOT_A_DRIVER)) &&
  867. drivers[i]->drv->frames_per_second > 57 &&
  868. drivers[i]->drv->default_visible_area.max_y - drivers[i]->drv->default_visible_area.min_y + 1 > 244 &&
  869. drivers[i]->drv->default_visible_area.max_y - drivers[i]->drv->default_visible_area.min_y + 1 <= 256)
  870. {
  871. printf("%s %dx%d %fHz\n",drivers[i]->name,
  872. drivers[i]->drv->default_visible_area.max_x - drivers[i]->drv->default_visible_area.min_x + 1,
  873. drivers[i]->drv->default_visible_area.max_y - drivers[i]->drv->default_visible_area.min_y + 1,
  874. drivers[i]->drv->frames_per_second);
  875. }
  876. i++;
  877. }
  878. return 0;
  879. break;
  880. case LIST_SOURCEFILE:
  881. i = 0;
  882. while (drivers[i])
  883. {
  884. if (!strwildcmp(gamename,drivers[i]->name))
  885. printf("%-8s %s\n",drivers[i]->name,drivers[i]->source_file);
  886. i++;
  887. }
  888. return 0;
  889. break;
  890. case LIST_LISTCRC: /* list all crc-32 */
  891. i = 0;
  892. while (drivers[i])
  893. {
  894. const struct RomModule *romp;
  895. romp = drivers[i]->rom;
  896. while (romp && (romp->name || romp->offset || romp->length))
  897. {
  898. if (romp->name && romp->name != (char *)-1)
  899. printf("%08x %-12s %s\n",romp->crc,romp->name,drivers[i]->description);
  900. romp++;
  901. }
  902. i++;
  903. }
  904. return 0;
  905. break;
  906. case LIST_LISTDUPCRC: /* list duplicate crc-32 (with different ROM name) */
  907. i = 0;
  908. while (drivers[i])
  909. {
  910. const struct RomModule *romp;
  911. romp = drivers[i]->rom;
  912. while (romp && (romp->name || romp->offset || romp->length))
  913. {
  914. if (romp->name && romp->name != (char *)-1 && romp->crc)
  915. {
  916. j = i+1;
  917. while (drivers[j])
  918. {
  919. const struct RomModule *romp1;
  920. romp1 = drivers[j]->rom;
  921. while (romp1 && (romp1->name || romp1->offset || romp1->length))
  922. {
  923. if (romp1->name && romp1->name != (char *)-1 &&
  924. strcmp(romp->name,romp1->name) &&
  925. romp1->crc == romp->crc)
  926. {
  927. printf("%08x %-12s %-8s <-> %-12s %-8s\n",romp->crc,
  928. romp->name,drivers[i]->name,
  929. romp1->name,drivers[j]->name);
  930. }
  931. romp1++;
  932. }
  933. j++;
  934. }
  935. }
  936. romp++;
  937. }
  938. i++;
  939. }
  940. return 0;
  941. break;
  942. case LIST_WRONGMERGE: /* list duplicate crc-32 with different ROM name in clone sets */
  943. i = 0;
  944. while (drivers[i])
  945. {
  946. const struct RomModule *romp;
  947. romp = drivers[i]->rom;
  948. while (romp && (romp->name || romp->offset || romp->length))
  949. {
  950. if (romp->name && romp->name != (char *)-1 && romp->crc)
  951. {
  952. j = 0;
  953. while (drivers[j])
  954. {
  955. if (j != i &&
  956. drivers[j]->clone_of &&
  957. (drivers[j]->clone_of->flags & NOT_A_DRIVER) == 0 &&
  958. (drivers[j]->clone_of == drivers[i] ||
  959. (i < j && drivers[j]->clone_of == drivers[i]->clone_of)))
  960. {
  961. const struct RomModule *romp1;
  962. int match;
  963. romp1 = drivers[j]->rom;
  964. match = 0;
  965. while (romp1 && (romp1->name || romp1->offset || romp1->length))
  966. {
  967. if (romp1->name && romp1->name != (char *)-1 &&
  968. !strcmp(romp->name,romp1->name))
  969. {
  970. match = 1;
  971. break;
  972. }
  973. romp1++;
  974. }
  975. if (match == 0)
  976. {
  977. romp1 = drivers[j]->rom;
  978. while (romp1 && (romp1->name || romp1->offset || romp1->length))
  979. {
  980. if (romp1->name && romp1->name != (char *)-1 &&
  981. strcmp(romp->name,romp1->name) &&
  982. romp1->crc == romp->crc)
  983. {
  984. printf("%08x %-12s %-8s <-> %-12s %-8s\n",romp->crc,
  985. romp->name,drivers[i]->name,
  986. romp1->name,drivers[j]->name);
  987. }
  988. romp1++;
  989. }
  990. }
  991. }
  992. j++;
  993. }
  994. }
  995. romp++;
  996. }
  997. i++;
  998. }
  999. return 0;
  1000. break;
  1001. case LIST_LISTROMSIZE: /* I used this for statistical analysis */
  1002. i = 0;
  1003. while (drivers[i])
  1004. {
  1005. if (drivers[i]->clone_of == 0 || (drivers[i]->clone_of->flags & NOT_A_DRIVER))
  1006. {
  1007. const struct RomModule *romp;
  1008. j = 0;
  1009. romp = drivers[i]->rom;
  1010. while (romp && (romp->name || romp->offset || romp->length))
  1011. {
  1012. j += romp->length & ~ROMFLAG_MASK;
  1013. romp++;
  1014. }
  1015. printf("%-8s\t%-5s\t%u\n",drivers[i]->name,drivers[i]->year,j);
  1016. }
  1017. i++;
  1018. }
  1019. return 0;
  1020. break;
  1021. case LIST_LISTCPU: /* I used this for statistical analysis */
  1022. {
  1023. int year;
  1024. for (j = 1;j < CPU_COUNT;j++)
  1025. printf("\t%s",cputype_name(j));
  1026. printf("\n");
  1027. for (year = 1980;year <= 1995;year++)
  1028. {
  1029. int count[CPU_COUNT];
  1030. for (j = 0;j < CPU_COUNT;j++)
  1031. count[j] = 0;
  1032. i = 0;
  1033. while (drivers[i])
  1034. {
  1035. if (drivers[i]->clone_of == 0 || (drivers[i]->clone_of->flags & NOT_A_DRIVER))
  1036. {
  1037. const struct MachineDriver *x_driver = drivers[i]->drv;
  1038. const struct MachineCPU *x_cpu = x_driver->cpu;
  1039. if (atoi(drivers[i]->year) == year)
  1040. {
  1041. // for (j = 0;j < MAX_CPU;j++)
  1042. j = 0; // count only the main cpu
  1043. count[x_cpu[j].cpu_type & ~CPU_FLAGS_MASK]++;
  1044. }
  1045. }
  1046. i++;
  1047. }
  1048. printf("%d",year);
  1049. for (j = 1;j < CPU_COUNT;j++)
  1050. printf("\t%d",count[j]);
  1051. printf("\n");
  1052. }
  1053. }
  1054. return 0;
  1055. break;
  1056. case LIST_LISTINFO: /* list all info */
  1057. print_mame_info( stdout, drivers );
  1058. return 0;
  1059. }
  1060. if (verify) /* "verify" utilities */
  1061. {
  1062. int err = 0;
  1063. int correct = 0;
  1064. int incorrect = 0;
  1065. int res = 0;
  1066. int total = 0;
  1067. int checked = 0;
  1068. int notfound = 0;
  1069. for (i = 0; drivers[i]; i++)
  1070. {
  1071. if (!strwildcmp(gamename, drivers[i]->name))
  1072. total++;
  1073. }
  1074. for (i = 0; drivers[i]; i++)
  1075. {
  1076. if (strwildcmp(gamename, drivers[i]->name))
  1077. continue;
  1078. /* set rom and sample path correctly */
  1079. get_rom_sample_path (argc, argv, i);
  1080. if (verify & VERIFY_ROMS)
  1081. {
  1082. res = VerifyRomSet (i,(verify & VERIFY_TERSE) ? terse_printf : (verify_printf_proc)printf);
  1083. if (res == CLONE_NOTFOUND || res == NOTFOUND)
  1084. {
  1085. notfound++;
  1086. goto nextloop;
  1087. }
  1088. if (res == INCORRECT || res == BEST_AVAILABLE || (verify & VERIFY_VERBOSE))
  1089. {
  1090. printf ("romset %s ", drivers[i]->name);
  1091. if (drivers[i]->clone_of && !(drivers[i]->clone_of->flags & NOT_A_DRIVER))
  1092. printf ("[%s] ", drivers[i]->clone_of->name);
  1093. }
  1094. }
  1095. if (verify & VERIFY_SAMPLES)
  1096. {
  1097. const char **samplenames = NULL;
  1098. #if (HAS_SAMPLES)
  1099. for( j = 0; drivers[i]->drv->sound[j].sound_type && j < MAX_SOUND; j++ )
  1100. if( drivers[i]->drv->sound[j].sound_type == SOUND_SAMPLES )
  1101. samplenames = ((struct Samplesinterface *)drivers[i]->drv->sound[j].sound_interface)->samplenames;
  1102. #endif
  1103. /* ignore games that need no samples */
  1104. if (samplenames == 0 || samplenames[0] == 0)
  1105. goto nextloop;
  1106. res = VerifySampleSet (i,(verify_printf_proc)printf);
  1107. if (res == NOTFOUND)
  1108. {
  1109. notfound++;
  1110. goto nextloop;
  1111. }
  1112. printf ("sampleset %s ", drivers[i]->name);
  1113. }
  1114. if (res == NOTFOUND)
  1115. {
  1116. printf ("oops, should never come along here\n");
  1117. }
  1118. else if (res == INCORRECT)
  1119. {
  1120. printf ("is bad\n");
  1121. incorrect++;
  1122. }
  1123. else if (res == CORRECT)
  1124. {
  1125. if (verify & VERIFY_VERBOSE)
  1126. printf ("is good\n");
  1127. correct++;
  1128. }
  1129. else if (res == BEST_AVAILABLE)
  1130. {
  1131. printf ("is best available\n");
  1132. correct++;
  1133. }
  1134. if (res)
  1135. err = res;
  1136. nextloop:
  1137. checked++;
  1138. fprintf(stderr,"%d%%\r",100 * checked / total);
  1139. }
  1140. if (correct+incorrect == 0)
  1141. {
  1142. printf ("%s ", (verify & VERIFY_ROMS) ? "romset" : "sampleset" );
  1143. if (notfound > 0)
  1144. printf("\"%8s\" not found!\n",gamename);
  1145. else
  1146. printf("\"%8s\" not supported!\n",gamename);
  1147. return 1;
  1148. }
  1149. else
  1150. {
  1151. printf("%d %s found, %d were OK.\n", correct+incorrect,
  1152. (verify & VERIFY_ROMS)? "romsets" : "samplesets", correct);
  1153. if (incorrect > 0)
  1154. return 2;
  1155. else
  1156. return 0;
  1157. }
  1158. }
  1159. if (ident)
  1160. {
  1161. if (ident == 2) silentident = 1;
  1162. else silentident = 0;
  1163. for (i = 1;i < argc;i++)
  1164. {
  1165. /* find the FIRST "name" field (without '-') */
  1166. if (argv[i][0] != '-')
  1167. {
  1168. knownstatus = KNOWN_START;
  1169. romident(argv[i],1);
  1170. if (ident == 2)
  1171. {
  1172. switch (knownstatus)
  1173. {
  1174. case KNOWN_START: printf("ERROR %s\n",argv[i]); break;
  1175. case KNOWN_ALL: printf("KNOWN %s\n",argv[i]); break;
  1176. case KNOWN_NONE: printf("UNKNOWN %s\n",argv[i]); break;
  1177. case KNOWN_SOME: printf("PARTKNOWN %s\n",argv[i]); break;
  1178. }
  1179. }
  1180. break;
  1181. }
  1182. }
  1183. return 0;
  1184. }
  1185. /* use a special return value if no frontend function used */
  1186. return 1234;
  1187. }