PageRenderTime 41ms CodeModel.GetById 16ms RepoModel.GetById 1ms app.codeStats 0ms

/pc/iso2opl/src/iso2opl.c

https://bitbucket.org/ifcaro/open-ps2-loader/
C | 608 lines | 413 code | 82 blank | 113 comment | 91 complexity | 3d5751501a71fa0450906ac71372783e MD5 | raw file
Possible License(s): CC-BY-SA-3.0, MPL-2.0-no-copyleft-exception, GPL-2.0
  1. /*
  2. Copyright 2009, jimmikaelkael
  3. Copyright (c) 2002, A.Lee & Nicholas Van Veen
  4. Licenced under Academic Free License version 3.0
  5. Review OpenUsbLd README & LICENSE files for further details.
  6. Some parts of the code are taken from libcdvd by A.Lee & Nicholas Van Veen
  7. Review license_libcdvd file for further details.
  8. */
  9. #include "iso2opl.h"
  10. #define WR_SIZE 524288
  11. u32 crctab[0x400];
  12. u8 systemcnf_buf[65536];
  13. //-----------------------------------------------------------------------
  14. void printVer(void)
  15. {
  16. #ifdef _WIN32
  17. printf("%s version %s (Win32 Build)\n", PROGRAM_EXTNAME, PROGRAM_VER);
  18. #else
  19. printf("%s version %s\n", PROGRAM_EXTNAME, PROGRAM_VER);
  20. #endif
  21. }
  22. //-----------------------------------------------------------------------
  23. void printUsage(void)
  24. {
  25. printVer();
  26. printf("Usage: %s [SOURCE_ISO] [DEST_DRIVE] [GAME_NAME] [TYPE]\n", PROGRAM_NAME);
  27. printf("%s command-line version %s\n\n", PROGRAM_EXTNAME, PROGRAM_VER);
  28. #ifdef _WIN32
  29. printf("Example 1: %s C:\\ISO\\WORMS4.ISO E WORMS_4_MAYHEM DVD\n", PROGRAM_NAME);
  30. printf("Example 2: %s \"C:\\ISO\\WORMS 4.ISO\" E \"WORMS 4: MAYHEM\" DVD\n", PROGRAM_NAME);
  31. printf("Example 3: %s \"C:\\ISO\\MICRO MACHINES V4.ISO\" E \"Micro Machines v4\" CD\n", PROGRAM_NAME);
  32. printf("Example 4: %s \"C:\\ISO\\WORMS 4.ISO\" E:\\MyDir WORMS_4 DVD\n", PROGRAM_NAME);
  33. printf("Example 5: %s \"C:\\ISO\\WORMS 4.ISO\" \\\\MyComputer\\PS2SMB WORMS_4 DVD\n", PROGRAM_NAME);
  34. #else
  35. printf("Example 1: %s /home/user/WORMS4.ISO /media/disk WORMS_4_MAYHEM DVD\n", PROGRAM_NAME);
  36. printf("Example 2: %s \"/home/user/WORMS 4.ISO\" /media/disk \"WORMS 4: MAYHEM\" DVD\n", PROGRAM_NAME);
  37. printf("Example 3: %s \"/home/user/MICRO MACHINES V4.ISO\" /media/disk \"Micro Machines v4\" CD\n", PROGRAM_NAME);
  38. #endif
  39. }
  40. //-----------------------------------------------------------------------
  41. u32 crc32(const char *string)
  42. {
  43. int crc, table, count, byte;
  44. for (table=0; table<256; table++) {
  45. crc = table << 24;
  46. for (count=8; count>0; count--) {
  47. if (crc < 0) crc = crc << 1;
  48. else crc = (crc << 1) ^ 0x04C11DB7;
  49. }
  50. crctab[255-table] = crc;
  51. }
  52. do {
  53. byte = string[count++];
  54. crc = crctab[byte ^ ((crc >> 24) & 0xFF)] ^ ((crc << 8) & 0xFFFFFF00);
  55. } while (string[count-1] != 0);
  56. return crc;
  57. }
  58. //-----------------------------------------------------------------------
  59. int check_cfg(const char *drive, const char *game_name, const char *game_id)
  60. {
  61. int r;
  62. //int fh_cfg;
  63. FILE *fh_cfg;
  64. cfg_t cfg;
  65. char cfg_path[256];
  66. char cfg_image[256];
  67. #ifdef DEBUG
  68. printf("check_cfg drive:%s name:%s id:%s\n", drive, game_name, game_id);
  69. #endif
  70. #ifdef _WIN32
  71. sprintf(cfg_path, "%s:\\ul.cfg", drive);
  72. #else
  73. sprintf(cfg_path, "%s/ul.cfg", drive);
  74. #endif
  75. sprintf(cfg_image, "ul.%s", game_id);
  76. /*fh_cfg = open(cfg_path, O_RDONLY);
  77. if (fh_cfg >= 0) {
  78. while ((r = read(fh_cfg, &cfg, sizeof(cfg_t))) != 0) {
  79. if (r != sizeof(cfg_t)) {
  80. close(fh_cfg);
  81. return -3;
  82. }
  83. if (!strcmp(cfg.name, game_name)) {
  84. close(fh_cfg);
  85. return -1;
  86. }
  87. if (!strcmp(cfg.image, cfg_image)) {
  88. close(fh_cfg);
  89. return -2;
  90. }
  91. }
  92. close(fh_cfg);
  93. }*/
  94. fh_cfg = fopen(cfg_path, "rb");
  95. if (fh_cfg) {
  96. while ((r = fread(&cfg, 1, sizeof(cfg_t), fh_cfg)) != 0) {
  97. if (r != sizeof(cfg_t)) {
  98. fclose(fh_cfg);
  99. return -3;
  100. }
  101. if (!strcmp(cfg.name, game_name)) {
  102. fclose(fh_cfg);
  103. return -1;
  104. }
  105. if (!strcmp(cfg.image, cfg_image)) {
  106. fclose(fh_cfg);
  107. return -2;
  108. }
  109. }
  110. fclose(fh_cfg);
  111. }
  112. return 0;
  113. }
  114. //-----------------------------------------------------------------------
  115. int write_cfg(const char *drive, const char *game_name, const char *game_id, const char *media, int parts)
  116. {
  117. //int fh_cfg;
  118. FILE *fh_cfg;
  119. cfg_t cfg;
  120. char cfg_path[256];
  121. int r;
  122. #ifdef DEBUG
  123. printf("write_cfg drive:%s name:%s id:%s media:%s parts:%d\n", drive, game_name, game_id, media, parts);
  124. #endif
  125. #ifdef _WIN32
  126. if (strlen(drive) == 1)
  127. sprintf(cfg_path, "%s:\\ul.cfg", drive);
  128. else
  129. sprintf(cfg_path, "%s\\ul.cfg", drive);
  130. #else
  131. sprintf(cfg_path, "%s/ul.cfg", drive);
  132. #endif
  133. memset(&cfg, 0, sizeof(cfg_t));
  134. strncpy(cfg.name, game_name, 32);
  135. sprintf(cfg.image, "ul.%s", game_id);
  136. cfg.parts = parts;
  137. cfg.pad[4] = 0x08; // To be like USBA
  138. if (!strcmp(media, "CD"))
  139. cfg.media = 0x12;
  140. else if (!strcmp(media, "DVD"))
  141. cfg.media = 0x14;
  142. /*
  143. fh_cfg = open(cfg_path, O_WRONLY|O_CREAT|O_APPEND);
  144. if (fh_cfg < 0)
  145. return -1;
  146. r = write(fh_cfg, &cfg, sizeof(cfg_t));
  147. if (r != sizeof(cfg_t)) {
  148. close(fh_cfg);
  149. return -2;
  150. }
  151. close(fh_cfg);
  152. */
  153. fh_cfg = fopen(cfg_path, "ab");
  154. if (!fh_cfg)
  155. return -1;
  156. r = fwrite(&cfg, 1, sizeof(cfg_t), fh_cfg);
  157. if (r != sizeof(cfg_t)) {
  158. fclose(fh_cfg);
  159. return -2;
  160. }
  161. fclose(fh_cfg);
  162. return 0;
  163. }
  164. //----------------------------------------------------------------
  165. int write_parts(const char *drive, const char *game_name, const char *game_id, s64 filesize, int parts)
  166. {
  167. //int fh_part;
  168. FILE *fh_part;
  169. char part_path[256];
  170. int i, r;
  171. u8 *buf;
  172. u32 size;
  173. s64 nbytes, rpos, iso_pos;
  174. #ifdef DEBUG
  175. printf("write_parts drive:%s name:%s id:%s filesize:0x%llx parts:%d\n", drive, game_name, game_id, filesize, parts);
  176. #endif
  177. iso_pos = 0;
  178. buf = malloc(WR_SIZE+2048);
  179. if (!buf)
  180. return -1;
  181. for (i=0; i<parts; i++) {
  182. #ifdef _WIN32
  183. if (strlen(drive) == 1)
  184. sprintf(part_path, "%s:\\ul.%08X.%s.%02d", drive, crc32(game_name), game_id, i);
  185. else
  186. sprintf(part_path, "%s\\ul.%08X.%s.%02d", drive, crc32(game_name), game_id, i);
  187. #else
  188. sprintf(part_path, "%s/ul.%08X.%s.%02d", drive, crc32(game_name), game_id, i);
  189. #endif
  190. /*
  191. fh_part = open(part_path, O_WRONLY|O_TRUNC|O_CREAT);
  192. if (fh_part < 0) {
  193. free(buf);
  194. return -2;
  195. }
  196. nbytes = filesize;
  197. if (nbytes > 1073741824)
  198. nbytes = 1073741824;
  199. rpos = 0;
  200. if (nbytes) {
  201. do {
  202. if (nbytes > WR_SIZE)
  203. size = WR_SIZE;
  204. else
  205. size = nbytes;
  206. r = isofs_ReadISO(iso_pos, size, buf);
  207. if (r != size) {
  208. free(buf);
  209. close(fh_part);
  210. return -3;
  211. }
  212. printf("Writing %d sectors to %s - LBA: %d\n", WR_SIZE >> 11, part_path, (int)(iso_pos >> 11));
  213. // write to file
  214. r = write(fh_part, buf, size);
  215. if (r != size) {
  216. free(buf);
  217. close(fh_part);
  218. return -4;
  219. }
  220. size = r;
  221. rpos += size;
  222. iso_pos += size;
  223. nbytes -= size;
  224. } while (nbytes);
  225. }
  226. filesize -= rpos;
  227. close(fh_part);
  228. }
  229. */
  230. fh_part = fopen(part_path, "wb");
  231. if (!fh_part) {
  232. free(buf);
  233. return -2;
  234. }
  235. nbytes = filesize;
  236. if (nbytes > 1073741824)
  237. nbytes = 1073741824;
  238. rpos = 0;
  239. if (nbytes) {
  240. do {
  241. if (nbytes > WR_SIZE)
  242. size = WR_SIZE;
  243. else
  244. size = nbytes;
  245. r = isofs_ReadISO(iso_pos, size, buf);
  246. if (r != size) {
  247. free(buf);
  248. fclose(fh_part);
  249. return -3;
  250. }
  251. printf("Writing %d sectors to %s - LBA: %d\n", WR_SIZE >> 11, part_path, (int)(iso_pos >> 11));
  252. // write to file
  253. r = fwrite(buf, 1, size, fh_part);
  254. if (r != size) {
  255. free(buf);
  256. fclose(fh_part);
  257. return -4;
  258. }
  259. size = r;
  260. rpos += size;
  261. iso_pos += size;
  262. nbytes -= size;
  263. } while (nbytes);
  264. }
  265. filesize -= rpos;
  266. fclose(fh_part);
  267. }
  268. free(buf);
  269. return 0;
  270. }
  271. //----------------------------------------------------------------
  272. int ParseSYSTEMCNF(char *system_cnf, char *boot_path)
  273. {
  274. int fd, r, fsize;
  275. char *p, *p2;
  276. int path_found = 0;
  277. #ifdef DEBUG
  278. printf("ParseSYSTEMCNF %s\n", system_cnf);
  279. #endif
  280. fd = isofs_Open("\\SYSTEM.CNF;1");
  281. if (fd < 0)
  282. return -1;
  283. fsize = isofs_Seek(fd, 0, SEEK_END);
  284. isofs_Seek(fd, 0, SEEK_SET);
  285. r = isofs_Read(fd, systemcnf_buf, fsize);
  286. if (r != fsize) {
  287. isofs_Close(fd);
  288. return -2;
  289. }
  290. isofs_Close(fd);
  291. #ifdef DEBUG
  292. printf("ParseSYSTEMCNF trying to retrieve elf path...\n");
  293. #endif
  294. p = strtok((char *)systemcnf_buf, "\n");
  295. while (p) {
  296. p2 = strstr(p, "BOOT2");
  297. if (p2) {
  298. p2 += 5;
  299. while ((*p2 <= ' ') && (*p2 > '\0'))
  300. p2++;
  301. if (*p2 != '=')
  302. return -3;
  303. p2++;
  304. while ((*p2 <= ' ') && (*p2 > '\0') && (*p2!='\r') && (*p2!='\n'))
  305. p2++;
  306. if (*p2 == '\0')
  307. return -3;
  308. path_found = 1;
  309. strcpy(boot_path, p2);
  310. }
  311. p = strtok(NULL, "\n");
  312. }
  313. if (!path_found)
  314. return -4;
  315. return 0;
  316. }
  317. //-----------------------------------------------------------------------
  318. s64 GetGameID(char *isofile, int isBigEndian, short closeOnEnd, char *GameID)
  319. {
  320. int ret;
  321. char ElfPath[256];
  322. char *p;
  323. s64 filesize;
  324. // Init isofs
  325. filesize = isofs_Init(isofile, isBigEndian);
  326. if (!filesize) {
  327. printf("Error: failed to open ISO file: %s\n", isofile);
  328. return 0;
  329. }
  330. // parse system.cnf in ISO file
  331. ret = ParseSYSTEMCNF("\\SYSTEM.CNF;1", ElfPath);
  332. if (ret < 0) {
  333. switch (ret) {
  334. case -1:
  335. printf("Error: can't open SYSTEM.CNF from ISO file: %s\n", isofile);
  336. break;
  337. case -2:
  338. printf("Error: failed to read SYSTEM.CNF from ISO file: %s\n", isofile);
  339. break;
  340. case -3:
  341. printf("Error: failed to parse SYSTEM.CNF from ISO file: %s\n", isofile);
  342. break;
  343. case -4:
  344. printf("Error: failed to locate elf path from ISO file: %s\n", isofile);
  345. break;
  346. }
  347. return 0;
  348. }
  349. #ifdef DEBUG
  350. printf("Elf Path: %s\n", ElfPath);
  351. #endif
  352. // get GameID
  353. strcpy(GameID, &ElfPath[8]);
  354. p = strstr(GameID, ";1");
  355. *p = 0;
  356. #ifdef DEBUG
  357. printf("Game ID: %s\n", GameID);
  358. #endif
  359. if (closeOnEnd)
  360. isofs_Reset();
  361. return filesize;
  362. }
  363. //----------------------------------------------------------------
  364. int compute_name(const char *drive, const char *game_name, const char *game_id)
  365. {
  366. #ifdef DEBUG
  367. printf("rename_iso drive:%s name:%s id:%s\n", drive, game_name, game_id);
  368. #endif
  369. #ifdef _WIN32
  370. if (strlen(drive) == 1)
  371. printf("%s:\\ul.%08X.%s.00\n", drive, crc32(game_name), game_id);
  372. else
  373. printf("%s\\ul.%08X.%s.00\n", drive, crc32(game_name), game_id);
  374. #else
  375. printf("%s/ul.%08X.%s.00\n", drive, crc32(game_name), game_id);
  376. #endif
  377. return 0;
  378. }
  379. //----------------------------------------------------------------
  380. void scan_dir(int isBigEndian)
  381. {
  382. struct dirent* ent;
  383. int size;
  384. char GameID[256];
  385. char *name;
  386. char fullname[512];
  387. char newname[512];
  388. struct stat buf;
  389. DIR* rep = opendir(".");
  390. if (rep != NULL) {
  391. while ((ent = readdir(rep)) != NULL) {
  392. name = ent->d_name;
  393. size = strlen(name);
  394. sprintf(fullname,"./%s", name);
  395. if ( ! stat(fullname, &buf) && ! S_ISDIR(buf.st_mode) ) {
  396. if (strstr(name, ".iso")) {
  397. if ((size >= 17) && (name[4] == '_') && (name[8] == '.') && (name[11] == '.')) {
  398. printf("%s seems to be correctly named\n", fullname);
  399. }
  400. else if (GetGameID(fullname, isBigEndian, 1, GameID)) {
  401. sprintf(newname,"./%s.%s", GameID, name);
  402. if (rename(fullname, newname) == 0)
  403. {
  404. printf("%s renamed to: %s\n", fullname, newname);
  405. }
  406. }
  407. }
  408. }
  409. }
  410. closedir(rep);
  411. }
  412. }
  413. //-----------------------------------------------------------------------
  414. int main(int argc, char **argv, char **env)
  415. {
  416. int ret;
  417. char GameID[256];
  418. s64 num_parts;
  419. char *p;
  420. s64 filesize;
  421. int isBigEnd;
  422. // Big Endianness test
  423. p = (char *)&isBigEnd;
  424. memset(p, 0, 4);
  425. p[3] = 1;
  426. if (isBigEnd != 1)
  427. isBigEnd = 0;
  428. #ifdef DEBUG
  429. printf("DEBUG_MODE ON\n");
  430. printf("Endianness: %d\n", isBigEnd);
  431. printf("isofs Init...\n");
  432. #endif
  433. // args check
  434. if ((argc > 1) && (strcmp(argv[1], "SCAN") == 0))
  435. {
  436. scan_dir(isBigEnd);
  437. exit(EXIT_SUCCESS);
  438. }
  439. if ((argc < 5) || (strcmp(argv[4], "CD") && strcmp(argv[4], "DVD")) || (strlen(argv[3]) > 32)) {
  440. printUsage();
  441. exit(EXIT_FAILURE);
  442. }
  443. #ifdef DEBUG
  444. printf("DEBUG_MODE ON\n");
  445. #endif
  446. filesize = GetGameID(argv[1], isBigEnd, 0, GameID);
  447. if (filesize==0) {
  448. isofs_Reset();
  449. exit(EXIT_FAILURE);
  450. }
  451. // check for existing game
  452. ret = check_cfg(argv[2], argv[3], GameID);
  453. if (ret < 0) {
  454. switch (ret) {
  455. case -1:
  456. printf("Error: a game with the same name is already installed on drive!\n");
  457. break;
  458. case -2:
  459. printf("Error: a game with the same ID is already installed on drive!\n");
  460. break;
  461. case -3:
  462. printf("Error: can't read ul.cfg on drive!\n");
  463. break;
  464. }
  465. isofs_Reset();
  466. exit(EXIT_FAILURE);
  467. }
  468. // get needed number of parts
  469. num_parts = filesize / 1073741824;
  470. if (filesize & 0x3fffffff)
  471. num_parts++;
  472. #ifdef DEBUG
  473. printf("ISO filesize: 0x%llx\n", filesize);
  474. printf("Number of parts: %d\n", num_parts);
  475. //return 0;
  476. #endif
  477. // write ISO parts to drive
  478. ret = write_parts(argv[2], argv[3], GameID, filesize, num_parts);
  479. if (ret < 0) {
  480. switch (ret) {
  481. case -1:
  482. printf("Error: failed to allocate memory to read ISO!\n");
  483. break;
  484. case -2:
  485. printf("Error: game part creation failed!\n");
  486. break;
  487. case -3:
  488. printf("Error: failed to read datas from ISO file!\n");
  489. break;
  490. case -4:
  491. printf("Error: failed to write datas to part file!\n");
  492. break;
  493. }
  494. isofs_Reset();
  495. exit(EXIT_FAILURE);
  496. }
  497. // append the game to ul.cfg
  498. ret = write_cfg(argv[2], argv[3], GameID, argv[4], num_parts);
  499. if (ret < 0) {
  500. switch (ret) {
  501. case -1:
  502. printf("Error: can't open ul.cfg!\n");
  503. break;
  504. case -2:
  505. printf("Error: write to ul.cfg failed!\n");
  506. break;
  507. }
  508. isofs_Reset();
  509. exit(EXIT_FAILURE);
  510. }
  511. isofs_Reset();
  512. printf("%s is installed!\n", argv[3]);
  513. // End program
  514. exit(EXIT_SUCCESS);
  515. return 0;
  516. }