libdm_misc.c 24 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823824825826827828829830831832833834835836837838839840841842843844845846847848849850851852853854855856857858859860861862863864865866867868869870871872873874875876877878879880881882883884885886887888889890891892893894895896897898899900901902903
  1. /*
  2. libdm_misc.c - libdiscmage miscellaneous
  3. Copyright (c) 2002 - 2004 NoisyB
  4. This library is free software; you can redistribute it and/or
  5. modify it under the terms of the GNU Lesser General Public
  6. License as published by the Free Software Foundation; either
  7. version 2.1 of the License, or (at your option) any later version.
  8. This library is distributed in the hope that it will be useful,
  9. but WITHOUT ANY WARRANTY; without even the implied warranty of
  10. MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
  11. Lesser General Public License for more details.
  12. You should have received a copy of the GNU Lesser General Public
  13. License along with this library; if not, write to the Free Software
  14. Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
  15. */
  16. #ifdef HAVE_CONFIG_H
  17. #include "config.h"
  18. #endif
  19. #ifdef HAVE_UNISTD_H
  20. #include <unistd.h>
  21. #endif
  22. #include <ctype.h>
  23. #include <stdio.h>
  24. #include <stdlib.h>
  25. #include <string.h>
  26. #ifdef _MSC_VER
  27. #pragma warning(push)
  28. #pragma warning(disable: 4820) // 'bytes' bytes padding added after construct 'member_name'
  29. #endif
  30. #include <time.h>
  31. #include <sys/stat.h>
  32. #ifdef _MSC_VER
  33. #pragma warning(pop)
  34. #endif
  35. #ifdef DEBUG
  36. #ifdef __GNUC__
  37. #warning DEBUG active
  38. #else
  39. #pragma message ("DEBUG active")
  40. #endif
  41. #endif
  42. #include "misc.h"
  43. #include "libdiscmage.h"
  44. #include "libdm_misc.h"
  45. #include "format/format.h"
  46. #ifdef DJGPP // DXEs are specific to DJGPP
  47. #include "dxedll_priv.h"
  48. #endif
  49. #include "misc_wav.h"
  50. #ifndef CD_MINS
  51. #define CD_MINS 74 /* max. minutes per CD, not really a limit */
  52. #define CD_SECS 60 /* seconds per minute */
  53. #define CD_FRAMES 75 /* frames per second */
  54. #endif
  55. #define MBIT (131072)
  56. #define TOMBIT(x) ((int)(x) / MBIT)
  57. #define TOMBIT_F(x) ((float)(x) / MBIT)
  58. const char pvd_magic[] = {0x01, 'C', 'D', '0', '0', '1', 0x01, 0};
  59. const char svd_magic[] = {0x02, 'C', 'D', '0', '0', '1', 0x01, 0};
  60. const char vdt_magic[] = {0xff, 'C', 'D', '0', '0', '1', 0x01, 0};
  61. #define ISODCL(from, to) (to - from + 1)
  62. typedef struct
  63. {
  64. char type[ISODCL (1, 1)]; /* 711 */
  65. char id[ISODCL (2, 6)];
  66. char version[ISODCL (7, 7)]; /* 711 */
  67. char unused1[ISODCL (8, 8)];
  68. char system_id[ISODCL (9, 40)]; /* achars */
  69. char volume_id[ISODCL (41, 72)]; /* dchars */
  70. char unused2[ISODCL (73, 80)];
  71. char volume_space_size[ISODCL (81, 88)]; /* 733 */
  72. char unused3[ISODCL (89, 120)];
  73. char volume_set_size[ISODCL (121, 124)]; /* 723 */
  74. char volume_sequence_number[ISODCL (125, 128)]; /* 723 */
  75. char logical_block_size[ISODCL (129, 132)]; /* 723 */
  76. char path_table_size[ISODCL (133, 140)]; /* 733 */
  77. char type_l_path_table[ISODCL (141, 144)]; /* 731 */
  78. char opt_type_l_path_table[ISODCL (145, 148)]; /* 731 */
  79. char type_m_path_table[ISODCL (149, 152)]; /* 732 */
  80. char opt_type_m_path_table[ISODCL (153, 156)]; /* 732 */
  81. char root_directory_record[ISODCL (157, 190)]; /* 9.1 */
  82. char volume_set_id[ISODCL (191, 318)]; /* dchars */
  83. char publisher_id[ISODCL (319, 446)]; /* achars */
  84. char preparer_id[ISODCL (447, 574)]; /* achars */
  85. char application_id[ISODCL (575, 702)]; /* achars */
  86. char copyright_file_id[ISODCL (703, 739)]; /* 7.5 dchars */
  87. char abstract_file_id[ISODCL (740, 776)]; /* 7.5 dchars */
  88. char bibliographic_file_id[ISODCL (777, 813)]; /* 7.5 dchars */
  89. char creation_date[ISODCL (814, 830)]; /* 8.4.26.1 */
  90. char modification_date[ISODCL (831, 847)]; /* 8.4.26.1 */
  91. char expiration_date[ISODCL (848, 864)]; /* 8.4.26.1 */
  92. char effective_date[ISODCL (865, 881)]; /* 8.4.26.1 */
  93. char file_structure_version[ISODCL (882, 882)]; /* 711 */
  94. char unused4[ISODCL (883, 883)];
  95. char application_data[ISODCL (884, 1395)];
  96. char unused5[ISODCL (1396, 2048)];
  97. } st_iso_header_t;
  98. /*
  99. * A CD-ROM physical sector size is 2048, 2052, 2056, 2324, 2332, 2336,
  100. * 2340, or 2352 bytes long.
  101. * Sector types of the standard CD-ROM data formats:
  102. *
  103. * format sector type user data size (bytes)
  104. * -----------------------------------------------------------------------------
  105. * 1 (Red Book) CD-DA 2352 (CD_FRAMESIZE_RAW)
  106. * 2 (Yellow Book) Mode1 Form1 2048 (CD_FRAMESIZE)
  107. * 3 (Yellow Book) Mode1 Form2 2336 (CD_FRAMESIZE_RAW0)
  108. * 4 (Green Book) Mode2 Form1 2048 (CD_FRAMESIZE)
  109. * 5 (Green Book) Mode2 Form2 2328 (2324+4 spare bytes)
  110. *
  111. *
  112. * The layout of the standard CD-ROM data formats:
  113. * -----------------------------------------------------------------------------
  114. * - audio (red): | audio_sample_bytes |
  115. * | 2352 |
  116. *
  117. * - data (yellow, mode1): | sync - head - data - EDC - zero - ECC |
  118. * | 12 - 4 - 2048 - 4 - 8 - 276 |
  119. *
  120. * - data (yellow, mode2): | sync - head - data |
  121. * | 12 - 4 - 2336 |
  122. *
  123. * - XA data (green, mode2 form1): | sync - head - sub - data - EDC - ECC |
  124. * | 12 - 4 - 8 - 2048 - 4 - 276 |
  125. *
  126. * - XA data (green, mode2 form2): | sync - head - sub - data - Spare |
  127. * | 12 - 4 - 8 - 2324 - 4 |
  128. *
  129. */
  130. /*
  131. from CDmage
  132. m1_2048=iso
  133. m1_2352=tao
  134. m2_2336=mm2
  135. m2_2352=tao
  136. cf_2048=fcd
  137. a1_2352=pcm
  138. a2_2352=wav
  139. cg_2448=cdg
  140. ci_2336=mci
  141. ci_2352=cdi
  142. cv_2048=vcd
  143. CDRWin cuesheet file (*.cue)|*.cue
  144. M1/2048 track (*.iso)|*.iso
  145. M1/2352 track (*.bin;*.tao;*.iso;*.img;*.bwi)|*.bin;*.tao;*.iso;*.img;*.bwi
  146. M2/2336 track (*.mm2)|*.mm2
  147. M2/2352 track (*.bin;*.tao;*.iso;*.img;*.bwi)|*.bin;*.tao;*.iso;*.img;*.bwi
  148. VirtualCD uncompressed container file (*.fcd)|*.fcd
  149. Audio track image file (*.pcm;*.bin;*.img;*.bwi)|*.pcm;*.bin;*img;*.bwi
  150. Wave file 44.1KHz 16-bit stereo (*.wav)|*.wav
  151. Virtual Drive uncomp. container file (*.vcd)|*.vcd
  152. Nero Burning Rom image file (*.nrg)|*.nrg
  153. CloneCD image control file (*.ccd)|*.ccd
  154. Raw Image (*.iso;*.bin;*.tao;*.img;*.bwi;*.mm2)|*.iso;*.bin;*.tao;*.img;*.bwi;*.mm2
  155. BlindWrite TOC file (*.bwt)|*.bwt
  156. DiscJuggler CD image file (*.cdi)|*.cdi
  157. Gear image files (*.rdb;*.md1;*.xa)|*.rdb;*.md1;*.xa
  158. NTI CD image files (*.cdp;*.ncd)|*.cdp;*.ncd
  159. Prassi Global-CD image file (*.gcd)|*.gcd
  160. WinOnCD full CD image file (*.c2d)|*.c2d
  161. Easy CD Creator image file (*.cif)|*.cif
  162. */
  163. const st_track_probe_t track_probe[] =
  164. {
  165. {1, 0, 2048, 0, DM_MODE1_2048, ".iso"}, // MODE2_FORM1
  166. {1, 16, 2352, 288, DM_MODE1_2352, ".bin.tao.iso.img.bwi"},
  167. {2, 8, 2336, 280, DM_MODE2_2336, ".mm2"}, // MODE2_FORM_MIX
  168. {2, 24, 2352, 280, DM_MODE2_2352, ".bin.tao.iso.img.bwi"},
  169. #if 0
  170. {2, 24, 2324, 4, DM_UNKNOWN, NULL}, // MODE2/2328, MODE2_FORM2
  171. {2, 0, 2340, 0, DM_UNKNOWN, NULL},
  172. {2, 0, 2368, 0, DM_UNKNOWN, NULL},
  173. {2, 0, 2448, 0, DM_UNKNOWN, NULL},
  174. {2, 0, 2646, 0, DM_UNKNOWN, NULL},
  175. {2, 0, 2647, 0, DM_UNKNOWN, NULL},
  176. {2, 0, 2336, 280, DM_UNKNOWN, NULL}, // MODE2/2336, Macintosh
  177. {2, 16, 2352, 280, DM_UNKNOWN, NULL}, // MODE2/2352, Macintosh
  178. {2, 0, 2056, 0, DM_UNKNOWN, NULL}, // MODE2/2056, Macintosh
  179. {0, 0, 0, 0, DM_UNKNOWN, NULL},
  180. {0, 0, 0, 0, DM_UNKNOWN, NULL},
  181. #endif
  182. {0, 0, 2352, 0, DM_AUDIO, ".pcm.bin.img.bwi"},
  183. // TODO: remove this!
  184. // {0, 0, 1, 0, DM_AUDIO, ".pcm.bin.img.bwi"},
  185. {0, 0, 0, 0, 0, NULL}
  186. };
  187. const char *dm_msg[] = {
  188. "ERROR: %s has been deprecated\n",
  189. "ERROR: Unknown/unsupported track mode\n",
  190. "ERROR: The images track mode is already MODE1/2048\n",
  191. "WARNING: This function is still in ALPHA stage. It might not work properly\n",
  192. NULL
  193. };
  194. static void (*dm_gauge_ptr) (int pos, int size) = NULL;
  195. int
  196. dm_get_track_mode_id (int mode, int sector_size)
  197. {
  198. int x = 0;
  199. for (x = 0; track_probe[x].sector_size; x++)
  200. if (track_probe[x].mode == mode &&
  201. track_probe[x].sector_size == sector_size)
  202. return track_probe[x].id;
  203. return 0; // no id
  204. }
  205. void
  206. dm_get_track_mode_by_id (int id, int8_t *mode, uint16_t *sector_size)
  207. {
  208. int x = 0;
  209. for (x = 0; track_probe[x].sector_size; x++)
  210. if (track_probe[x].id == id)
  211. {
  212. *mode = (int8_t) track_probe[x].mode;
  213. *sector_size = (uint16_t) track_probe[x].sector_size;
  214. return;
  215. }
  216. }
  217. int
  218. dm_bcd_to_int (int b)
  219. {
  220. // return (b & 0x0F) + 10 * (((b) >> 4) & 0x0F);
  221. return (b & 15) + ((b & 240) >> 4) * 10;
  222. }
  223. int
  224. dm_int_to_bcd (int i)
  225. {
  226. #if 0
  227. #if 1
  228. return i % 10 | ((i / 10) % 10) << 4;
  229. #else
  230. return ((i / 10) * 16) + (i % 10);
  231. #endif
  232. #else
  233. return ((i / 10) << 4) | (i % 10);
  234. #endif
  235. }
  236. int
  237. dm_is_bcd (int b)
  238. {
  239. return ((b & 15) < 10) && ((b >> 4) < 10);
  240. }
  241. int
  242. dm_lba_to_msf (int lba, int *m0, int *s0, int *f0)
  243. #if 1
  244. {
  245. static int m, s, f;
  246. m = s = f = -1;
  247. #ifdef __follow_redbook__
  248. if (lba >= -150 && lba < 405000) /* lba <= 404849 */
  249. #else
  250. if (lba >= -150)
  251. #endif
  252. {
  253. m = (lba + 150) / CD_SECS / CD_FRAMES;
  254. s = (lba + 150 - m * CD_SECS * CD_FRAMES) / CD_FRAMES;
  255. f = (lba + 150 - m * CD_SECS * CD_FRAMES - s * CD_FRAMES);
  256. }
  257. else if (lba >= -45150 && lba <= -151)
  258. {
  259. m = (lba + 450150) / CD_SECS / CD_FRAMES;
  260. s = (lba + 450150 - m * CD_SECS * CD_FRAMES) / CD_FRAMES;
  261. f = (lba + 450150 - m * CD_SECS * CD_FRAMES - s * CD_FRAMES);
  262. }
  263. *m0 = m;
  264. *s0 = s;
  265. *f0 = f;
  266. if (lba > 404849 || *m0 == -1 || *s0 == -1 || *f0 == -1) /* 404850 -> 404999: lead out */
  267. return FALSE;
  268. return TRUE;
  269. }
  270. #else
  271. {
  272. static int m, s, f;
  273. m = s = f = -1;
  274. if (lba >= -150)
  275. {
  276. m = (lba + 150) / (CD_SECS * CD_FRAMES);
  277. lba -= m * CD_SECS * CD_FRAMES;
  278. s = (lba + 150) / CD_FRAMES;
  279. lba -= s * CD_FRAMES;
  280. f = (lba + 150);
  281. }
  282. else
  283. {
  284. m = (lba + 450150) / (CD_SECS * CD_FRAMES);
  285. lba -= m * CD_SECS * CD_FRAMES;
  286. s = (lba + 450150) / CD_FRAMES;
  287. lba -= s * CD_FRAMES;
  288. f = (lba + 450150);
  289. }
  290. *m0 = m;
  291. *s0 = s;
  292. *f0 = f;
  293. return TRUE;
  294. }
  295. #endif
  296. int
  297. dm_msf_to_lba (int m, int s, int f, int force_positive)
  298. #if 1
  299. {
  300. long ret = (m * CD_SECS + s)
  301. #if 0
  302. * CD_FRAMES + f;
  303. #else
  304. ;
  305. ret *= CD_FRAMES;
  306. ret += f;
  307. #endif
  308. if (m < 90 || force_positive)
  309. ret -= 150;
  310. else
  311. ret -= 450150;
  312. return ret;
  313. }
  314. #else
  315. {
  316. return m * CD_SECS * CD_FRAMES + s * CD_FRAMES + f;
  317. }
  318. #endif
  319. void
  320. dm_clean (dm_image_t *image)
  321. {
  322. int x = 0;
  323. memset (image, 0, sizeof (dm_image_t));
  324. for (x = 0; x < DM_MAX_TRACKS; x++)
  325. image->track[x].iso_header_start = (-1);
  326. }
  327. uint32_t
  328. dm_get_version (void)
  329. {
  330. static const uint32_t dm_version = LIB_VERSION (DM_VERSION_MAJOR,
  331. DM_VERSION_MINOR,
  332. DM_VERSION_STEP);
  333. return dm_version;
  334. }
  335. const char *
  336. dm_get_version_s (void)
  337. {
  338. return "supported: BIN, ISO, CDI";
  339. }
  340. void
  341. dm_set_gauge (void (*gauge) (int, int))
  342. {
  343. dm_gauge_ptr = gauge;
  344. }
  345. void
  346. dm_gauge (int pos, int size)
  347. {
  348. if (dm_gauge_ptr)
  349. dm_gauge_ptr (pos, size);
  350. }
  351. FILE *
  352. dm_fdopen (dm_image_t *image, int track_num, const char *mode)
  353. {
  354. dm_track_t *track = (dm_track_t *) &image->track[track_num];
  355. FILE *fh;
  356. if ((fh = fopen (image->fname, mode)) == NULL)
  357. return NULL;
  358. if (!fseek (fh, track->track_start, SEEK_SET))
  359. return fh;
  360. fclose (fh);
  361. return NULL;
  362. }
  363. int
  364. dm_rip (const dm_image_t *image, int track_num, uint32_t flags)
  365. {
  366. dm_track_t *track = (dm_track_t * ) &image->track[track_num];
  367. #if FILENAME_MAX > MAXBUFSIZE
  368. char buf[FILENAME_MAX], buf2[FILENAME_MAX];
  369. #else
  370. char buf[MAXBUFSIZE], buf2[MAXBUFSIZE];
  371. #endif
  372. unsigned int x = 0;
  373. int result = 0, m = 0, s = 0, f = 0;
  374. char *p = NULL;
  375. FILE *fh = NULL, *fh2 = NULL;
  376. if (flags & DM_FIX || flags & DM_2048)
  377. fprintf (stderr, dm_msg[ALPHA]);
  378. // set dest. name
  379. strcpy (buf, basename (image->fname));
  380. p = (char *) get_suffix (buf);
  381. if (p)
  382. buf[strlen (buf) - strlen (p)] = 0;
  383. sprintf (buf2, "%s_%d", buf, track_num + 1);
  384. switch (track->mode)
  385. {
  386. case 0:
  387. if (flags & DM_WAV)
  388. set_suffix (buf2, ".WAV");
  389. else
  390. set_suffix (buf2, ".RAW");
  391. break;
  392. case 1:
  393. case 2:
  394. default:
  395. if (flags & DM_2048 || track->sector_size == 2048)
  396. set_suffix (buf2, ".ISO");
  397. else
  398. set_suffix (buf2, ".BIN");
  399. break;
  400. }
  401. #if 0
  402. if (track->total_len < track->track_len + track->pregap_len)
  403. {
  404. fprintf (stderr, "SKIPPING: track seems truncated\n");
  405. return -1;
  406. }
  407. #endif
  408. #if 0
  409. // this is not a problem
  410. if (flags & DM_2048 && track->mode == 1 && track->sector_size == 2048)
  411. {
  412. fprintf (stderr, dm_msg[ALREADY_2048]);
  413. return -1;
  414. }
  415. #endif
  416. if (track->pregap_len != 150) // 0x96
  417. fprintf (stderr, "WARNING: track seems to have a non-standard pregap (%d Bytes)\n",
  418. track->pregap_len);
  419. #if 0
  420. if (image->pregap && track->mode == 0 && remaining_tracks > 1) // quick hack to save next track pregap (audio tracks only)
  421. track->track_len += pregap_length; // if this isn't last track in current session
  422. // does this mean i shouldn't skip pregrap if it's a audio track?
  423. #endif
  424. // open source and check
  425. if ((fh = fopen (image->fname, "rb")) == NULL)
  426. return -1;
  427. // open dest.
  428. if ((fh2 = fopen (buf2, "wb")) == NULL)
  429. {
  430. fclose (fh);
  431. return -1;
  432. }
  433. if (!track->mode && flags & DM_WAV)
  434. misc_wav_write_header_v3 (fh2, track->track_len * 2352); //TODO: get that 2352 value from somewhere
  435. fseek (fh, track->track_start, SEEK_SET); // start of track
  436. // skip pregap (always?)
  437. fseek (fh, track->pregap_len * track->sector_size, SEEK_CUR);
  438. for (x = 0; x < track->track_len; x++)
  439. {
  440. memset (buf, 0, sizeof (buf));
  441. fread (&buf, 1, track->sector_size, fh);
  442. if (flags & DM_2048)
  443. result = fwrite (&buf[track->seek_header], 1, 2048, fh2);
  444. else
  445. {
  446. const char sync_data[] = {0, 0xff, 0xff,
  447. 0xff, 0xff,
  448. 0xff, 0xff,
  449. 0xff, 0xff,
  450. 0xff, 0xff, 0};
  451. // uint32_t value_32 = 0;
  452. memset (&buf2, 0, sizeof (buf2));
  453. result = 0;
  454. result += fwrite (&sync_data, 1, 12, fh2);
  455. dm_lba_to_msf (150 + x, &m, &s, &f);
  456. #ifdef DEBUG
  457. fprintf (stderr, "%d: %d %d %d\n", track->sector_size, m, s, f);
  458. fflush (stderr);
  459. #endif
  460. result += fwrite (&buf2, 1, 3, fh2); //TODO: MSF
  461. if (fputc (track->mode, fh2))
  462. result++;
  463. result += fwrite (&buf2, 1, track->seek_header, fh2); // padding
  464. result += fwrite (&buf, 1, track->sector_size, fh2);
  465. result += fwrite (&buf2, 1, track->seek_ecc, fh2); // padding
  466. }
  467. if (!result)
  468. {
  469. fprintf (stderr, "ERROR: writing sector %d\n", x);
  470. fclose (fh);
  471. fclose (fh2);
  472. return -1;
  473. }
  474. if (!(x % 100))
  475. dm_gauge (x * track->sector_size, track->track_len * track->sector_size);
  476. }
  477. dm_gauge (x * track->sector_size, track->track_len * track->sector_size);
  478. // fseek (fh, track->total_len * track->sector_size, SEEK_CUR);
  479. fclose (fh);
  480. fclose (fh2);
  481. return 0;
  482. }
  483. #if 0
  484. // TODO: merge into dm_rip
  485. int
  486. dm_isofix (const dm_image_t * image, int start_lba, int track_num)
  487. {
  488. #define BOOTFILE_S "bootfile.bin"
  489. #define HEADERFILE_S "header.iso"
  490. int32_t size_left, last_pos, i, size;
  491. dm_track_t *track = (dm_track_t *) &image->track[track_num];
  492. char buf[MAXBUFSIZE], buf2[FILENAME_MAX];
  493. FILE *dest = NULL, *src = NULL, *boot = NULL, *header = NULL;
  494. int mac = FALSE;
  495. const char sub_header[] = {0, 0, 0x08, 0, 0, 0, 0x08, 0};
  496. if (start_lba <= 0)
  497. {
  498. fprintf (stderr, "ERROR: Bad LBA value");
  499. return -1;
  500. }
  501. if (!track)
  502. return -1;
  503. mac = (track->sector_size == 2056 ? TRUE : FALSE);
  504. if (!(src = fopen (image->fname, "rb")))
  505. return -1;
  506. strcpy (buf2, basename (image->fname));
  507. set_suffix (buf2, ".FIX");
  508. if (!(dest = fopen (buf2, "wb")))
  509. {
  510. fclose (src);
  511. return -1;
  512. }
  513. // Saving boot area to file 'bootfile.bin'...
  514. if (!(boot = fopen (BOOTFILE_S, "wb")))
  515. {
  516. fclose (src);
  517. fclose (dest);
  518. remove (buf);
  519. return -1;
  520. }
  521. // Saving ISO header to file 'header.iso'...
  522. if (!(header = fopen (HEADERFILE_S, "wb")))
  523. {
  524. fclose (src);
  525. fclose (dest);
  526. remove (buf);
  527. fclose (boot);
  528. remove (BOOTFILE_S);
  529. return -1;
  530. }
  531. // save boot area
  532. for (i = 0; i < 16; i++)
  533. {
  534. fseek (src, track->seek_header, SEEK_CUR);
  535. fread (buf, 2048, 1, src);
  536. fseek (src, track->seek_ecc, SEEK_CUR);
  537. if (mac)
  538. fwrite (sub_header, 8, 1, dest);
  539. fwrite (buf, 2048, 1, dest);
  540. if (mac)
  541. fwrite (sub_header, 8, 1, boot);
  542. fwrite (buf, 2048, 1, boot);
  543. if (mac)
  544. fwrite (sub_header, 8, 1, header);
  545. fwrite (buf, 2048, 1, header);
  546. }
  547. fclose (boot); // boot area written
  548. // seek & copy pvd etc.
  549. // last_pos = ftell (src); // start of pvd
  550. for (last_pos = ftell (src); memcmp (vdt_magic, buf, 8) != 0; last_pos = ftell (src))
  551. {
  552. fseek (src, track->seek_header, SEEK_CUR);
  553. fread (buf, 2048, 1, src);
  554. fseek (src, track->seek_ecc, SEEK_CUR);
  555. if (memcmp (pvd_magic, buf, 8) != 0 &&
  556. memcmp (svd_magic, buf, 8) != 0 &&
  557. memcmp (vdt_magic, buf, 8) != 0)
  558. {
  559. fprintf (stderr, "ERROR: Found unknown Volume Descriptor");
  560. // which sector?
  561. return -1;
  562. }
  563. printf ("Found %s at sector %d\n",
  564. !memcmp (pvd_magic, buf, 8) ? "PVD" :
  565. !memcmp (svd_magic, buf, 8) ? "SVD" :
  566. !memcmp (vdt_magic, buf, 8) ? "VDT" : "unknown Volume Descriptor",
  567. last_pos / track->sector_size);
  568. if (mac)
  569. fwrite (sub_header, 8, 1, dest);
  570. fwrite (buf, 2048, 1, dest);
  571. if (mac)
  572. fwrite (sub_header, 8, 1, header);
  573. fwrite (buf, 2048, 1, header);
  574. }
  575. // add padding data to header file
  576. memset (&buf, 0, sizeof (buf));
  577. size_left = 300 - (last_pos / track->sector_size);
  578. for (i = 0; i < size_left; i++)
  579. {
  580. if (mac == TRUE)
  581. fwrite (sub_header, 8, 1, header);
  582. fwrite (buf, 2048, 1, header);
  583. }
  584. fclose (header);
  585. // add padding data to iso image
  586. if (last_pos > (int) (start_lba * track->sector_size))
  587. {
  588. fprintf (stderr, "ERROR: LBA value is too small\n"
  589. " It should be at least %d for current ISO image (probably greater)",
  590. last_pos / track->sector_size);
  591. return -1;
  592. }
  593. if (start_lba < 11700)
  594. fprintf (stderr,
  595. "WARNING: LBA value should be greater or equal to 11700 for multisession\n"
  596. " images\n");
  597. // adding padding data up to start LBA value...
  598. size_left = start_lba - (last_pos / track->sector_size);
  599. memset (&buf, 0, sizeof (buf));
  600. for (i = 0; i < size_left; i++)
  601. {
  602. if (mac)
  603. fwrite (sub_header, 8, 1, dest);
  604. if (!fwrite (buf, 2048, 1, dest))
  605. return -1;
  606. }
  607. // append original iso image
  608. fseek (src, 0L, SEEK_SET);
  609. size = q_fsize (buf2);
  610. size_left = size / track->sector_size;
  611. for (i = 0; i < size_left; i++)
  612. {
  613. fseek (src, track->seek_header, SEEK_CUR);
  614. if (!fread (buf, 2048, 1, src))
  615. break;
  616. fseek (src, track->seek_ecc, SEEK_CUR);
  617. if (mac)
  618. fwrite (sub_header, 8, 1, dest);
  619. if (!fwrite (buf, 2048, 1, dest))
  620. return -1;
  621. }
  622. fclose (src);
  623. fclose (dest);
  624. return 0;
  625. }
  626. #endif
  627. void
  628. dm_nfo (const dm_image_t *image, int verbose, int ansi_color)
  629. {
  630. #define COLS 80
  631. int t = 0, s = 0, x = 0, min = 0, sec = 0, frames = 0,
  632. filesize = q_fsize (image->fname);
  633. char buf[MAXBUFSIZE];
  634. st_iso_header_t iso_header;
  635. FILE *fh = NULL;
  636. #ifndef USE_ANSI_COLOR
  637. (void) ansi_color; // warning remover
  638. #endif
  639. #if 0
  640. if (image->console_usage != NULL)
  641. {
  642. strcpy (buf, rominfo->console_usage[0].desc);
  643. puts (to_func (buf, strlen (buf), toprint2));
  644. #if 0
  645. if (image->console_usage[1].desc)
  646. {
  647. strcpy (buf, rominfo->console_usage[1].desc);
  648. printf (" %s\n", to_func (buf, strlen (buf), toprint2));
  649. }
  650. #endif
  651. }
  652. #endif
  653. printf ("%d Bytes (%.4f MB)\n\n", filesize, (float) filesize / (1024 * 1024));
  654. printf ("Type: %s\n", image->desc);
  655. if (image->misc[0])
  656. puts (image->misc);
  657. printf ("Sessions: %d\n", image->sessions);
  658. printf ("Tracks: %d\n", image->tracks);
  659. if ((COLS / image->tracks) > 1 && image->sessions && image->tracks)
  660. {
  661. printf ("Layout: ");
  662. for (s = t = 0; s < image->sessions; s++)
  663. {
  664. #ifdef USE_ANSI_COLOR
  665. if (ansi_color)
  666. printf ("\x1b[0m[\x1b[30;41m%2d \x1b[0m", s + 1);
  667. // printf ("\x1b[0m[\x1b[30;41m");
  668. else
  669. #endif
  670. printf ("[%2d ", s + 1);
  671. // printf ("[");
  672. for (x = 0; x < image->session[s]; x++, t++)
  673. #ifdef USE_ANSI_COLOR
  674. if (ansi_color)
  675. printf ("\x1b[0m[\x1b[30;42m%2d \x1b[0m]", t + 1);
  676. else
  677. #endif
  678. printf ("[%2d ]", t + 1);
  679. #ifdef USE_ANSI_COLOR
  680. if (ansi_color)
  681. printf ("\x1b[0m] ");
  682. else
  683. #endif
  684. printf ("] ");
  685. }
  686. fputc ('\n', stdout);
  687. }
  688. for (t = 0; t < image->tracks; t++)
  689. {
  690. const dm_track_t *track = (const dm_track_t *) &image->track[t];
  691. if (!track)
  692. continue;
  693. if (!track->mode && track->sector_size == 2352)
  694. strcpy (buf, "AUDIO");
  695. else
  696. sprintf (buf, "MODE%d/%d", track->mode, track->sector_size);
  697. printf ("Track: %d %s", t + 1, buf);
  698. dm_lba_to_msf (track->track_len, &min, &sec, &frames);
  699. printf ("\n %d Sectors, %d:%02d/%02d MSF, %d Bytes (%.4f MB)",
  700. (int) track->total_len,
  701. min, sec, frames,
  702. (int) (track->total_len * track->sector_size),
  703. (float) (track->total_len * track->sector_size) / (1024 * 1024));
  704. fputc ('\n', stdout);
  705. if (verbose)
  706. {
  707. printf (" Pregap: %d, Start Sector: %d, End Sector: %d, Postgap: %d\n",
  708. track->pregap_len,
  709. (int) (track->track_start / track->sector_size),
  710. (int) ((track->track_start / track->sector_size) + track->total_len),
  711. track->postgap_len);
  712. dm_lba_to_msf (track->track_len, &min, &sec, &frames);
  713. printf (" Total Time: %d:%02d/%02d MSF, File Start Pos: %d, End Pos: %d\n",
  714. min, sec, frames,
  715. (int) track->track_start,
  716. (int) track->track_end);
  717. }
  718. memset (&iso_header, 0, sizeof (st_iso_header_t));
  719. if (track->iso_header_start != -1)
  720. if ((fh = fopen (image->fname, "rb")) != NULL)
  721. if (fread (&iso_header, track->iso_header_start, sizeof (st_iso_header_t), fh))
  722. {
  723. if (verbose)
  724. mem_hexdump (&iso_header, sizeof (st_iso_header_t), track->iso_header_start);
  725. // name, maker, country and size
  726. // some have a name with control chars in it -> replace control chars
  727. strncpy2 (buf, NULL_TO_EMPTY (iso_header.volume_id),
  728. sizeof (iso_header.volume_id));
  729. to_func (buf, strlen (buf), toprint2);
  730. if (*strtrim (buf))
  731. printf (" %s\n", buf);
  732. strncpy2 (buf, NULL_TO_EMPTY (iso_header.publisher_id),
  733. sizeof (iso_header.publisher_id));
  734. to_func (buf, strlen (buf), toprint2);
  735. if (*strtrim (buf))
  736. printf (" %s\n", buf);
  737. strncpy2 (buf, NULL_TO_EMPTY (iso_header.preparer_id),
  738. sizeof (iso_header.preparer_id));
  739. to_func (buf, strlen (buf), toprint2);
  740. if (*strtrim (buf))
  741. printf (" %s\n", buf);
  742. #if 0
  743. strncpy2 (buf, NULL_TO_EMPTY (iso_header.logical_block_size),
  744. sizeof (iso_header.logical_block_size));
  745. to_func (buf, strlen (buf), toprint2);
  746. if (*strtrim (buf))
  747. printf (" %s\n", buf);
  748. #endif
  749. strncpy2 (buf, NULL_TO_EMPTY (iso_header.application_id),
  750. sizeof (iso_header.application_id));
  751. to_func (buf, strlen (buf), toprint2);
  752. if (*strtrim (buf))
  753. printf (" %s\n", buf);
  754. }
  755. }
  756. }