psxdump.c
上传用户:weiliju62
上传日期:2007-01-06
资源大小:619k
文件大小:7k
源码类别:

SCSI/ASPI

开发平台:

MultiPlatform

  1. /*
  2.  * psxdump.c - Dumps playstation disks to file
  3.  *
  4.  * Portions (c) 1999 Fabio Baracca <fabiobar@tiscalinet.it>
  5.  *
  6.  * *HEAVILY BASED* on code from readxa.c 
  7.  * that's (c) 1996,1997 Gerd Knorr <kraxel@cs.tu-berlin.de>
  8.  *
  9.  */
  10. #include <stdio.h>
  11. #include <stdlib.h>
  12. #include <unistd.h>
  13. #include <getopt.h>
  14. #include <fcntl.h>
  15. #include <errno.h>
  16. #include <sys/stat.h>
  17. #include <sys/ioctl.h>
  18. #include <linux/cdrom.h>
  19. #include <linux/fs.h>
  20. /* Ugly, I know.. */
  21. extern char *sys_errlist[];
  22. typedef unsigned char u8bit;
  23. typedef unsigned short u16bit;
  24. typedef unsigned u32bit;
  25. unsigned char psx_sign[] =
  26. {0x00, 0x00, 0x09, 0x00, 0x00, 0x00, 0x09, 0x00, 0x01,
  27.  0x43, 0x44, 0x30, 0x30, 0x31, 0x01, 0x00, 0x50, 0x4C,
  28.  0x41, 0x59, 0x53, 0x54, 0x41, 0x54, 0x49, 0x4F, 0x4E,
  29.  0x20, 0x20, 0x20, 0x20, 0x20};
  30. typedef struct tag_iso_dir_entry {
  31.     u8bit len_dr;
  32.     u8bit XAR_len;
  33.     u32bit loc_extentI;
  34.     u32bit loc_extentM;
  35.     u32bit data_lenI;
  36.     u32bit data_lenM;
  37.     u8bit record_time[7];
  38.     u8bit file_flags_iso;
  39.     u8bit il_size;
  40.     u8bit il_skip;
  41.     u16bit VSSNI;
  42.     u16bit VSSNM;
  43.     u8bit len_fi;
  44.     u8bit file_id[32];
  45.     u8bit padding;
  46. } iso_dir_entry;
  47. iso_dir_entry dir_entry;
  48. static const char *device_list[] =
  49. {
  50.     /* try most common first ... */
  51.     "/dev/cdrom",
  52.     "/dev/scd0",
  53.     "/dev/sr0",
  54.     "/dev/hdc",
  55.     "/dev/hdd",
  56.     "/dev/scd1",
  57.     "/dev/sr1",
  58.     "/dev/scd2",
  59.     "/dev/sr2",
  60.     "/dev/scd3",
  61.     "/dev/sr3",
  62.     "/dev/hda",
  63.     "/dev/hdb",
  64.     "/dev/hde",
  65.     "/dev/hdf",
  66.     "/dev/hdg",
  67.     "/dev/hdh",
  68.     NULL
  69. };
  70. int print_info = 0;
  71. int dump_raw = 0;
  72. void about(void)
  73. {
  74.     fprintf(stderr, "psxdump.c - Dumps playstation disks to filennA quick hack that's (c) 1999 Fabio Baracca <fabiobar@tiscalinet.it>nLicensed under GNU GPL - *HEAVILY BASED* on code from readxa.cnthat's (c) 1996,1997 Gerd Knorr <kraxel@cs.tu-berlin.de>nn");
  75. }
  76. void usage(void)
  77. {
  78.     fprintf(stderr,
  79.     "syntax: psxdump -d <device> -f <output file>nn"
  80.     "  -d <device>       give device namen"
  81.     "  -f <output file>  file to put track dumpn"
  82.     "  -F                force the program to proceed even if it's not a PSX diskn"
  83.     "  -T                test type of disc (PSX or non) and report it as exit coden"
  84.     "  -h                display this banner :-)n");
  85. }
  86. int read_raw_frame(int fd, int lba, unsigned char *buf)
  87. {
  88.     struct cdrom_msf *msf;
  89.     int rc;
  90.     msf = (struct cdrom_msf *) buf;
  91.     msf->cdmsf_min0 = (lba + CD_MSF_OFFSET) / CD_FRAMES / CD_SECS;
  92.     msf->cdmsf_sec0 = (lba + CD_MSF_OFFSET) / CD_FRAMES % CD_SECS;
  93.     msf->cdmsf_frame0 = (lba + CD_MSF_OFFSET) % CD_FRAMES;
  94.     rc = ioctl(fd, CDROMREADMODE2, buf);
  95.     if (-1 == rc)
  96. perror("ioctl CDROMREADMODE2");
  97.     return rc;
  98. }
  99. int main(int argc, char *argv[])
  100. {
  101.     int forcepsx = 0, ofile, cdrom, rc, c, size, percent, maxsize, testpsx = 0;
  102.     unsigned long block;
  103.     unsigned char *buf;
  104.     struct stat st, dev_st;
  105.     int device;
  106.     long seek = -1;
  107.     struct cdrom_tocentry toc, toc2;
  108.     char *outfile = NULL, *devname = NULL;
  109.     /* parse options */
  110.     for (;;) {
  111. c = getopt(argc, argv, "TFd:f:");
  112. if (c == -1)
  113.     break;
  114. switch (c) {
  115. case 'f':
  116.     outfile = optarg;
  117.     break;
  118. case 'd':
  119.     devname = optarg;
  120.     break;
  121. case 'F':
  122.     forcepsx = 1;
  123.     break;
  124. case 'T':
  125.     testpsx = 1;
  126.     break;
  127. case 'h':
  128. default:
  129.     usage();
  130.     exit(1);
  131. }
  132.     }
  133.     /* Malloc-ing memory */
  134.     if (NULL == (buf = malloc(CD_FRAMESIZE_RAW0))) {
  135. fprintf(stderr, "Out of memoryn");
  136. exit(1);
  137.     }
  138.     if ((testpsx) && (devname)) {
  139. if (-1 == (cdrom = open(devname ? devname : device_list[device], O_RDONLY | O_NONBLOCK))) {
  140.     fprintf(stderr, "open %s: %sn", devname ? devname : device_list[device], sys_errlist[errno]);
  141.     exit(2);
  142. }
  143. if (0 != (rc = read_raw_frame(cdrom, 16, buf))) {
  144.     perror("read error");
  145.     exit(2);
  146. }
  147. close(rc);
  148. if (memcmp(psx_sign, buf, sizeof(psx_sign)) == 0)
  149.     exit(0);
  150. else
  151.     exit(1);
  152.     }
  153.     
  154.     about();
  155.     if ((!outfile) || (!devname)) {
  156. fprintf(stderr, "Please specify *either* the file name (or -T flag) *and* the device of the CD reader.nn");
  157. usage();
  158. exit(2);
  159.     }
  160.     /* Opening the CDROM reader  */
  161.     if (-1 == (cdrom = open(devname ? devname : device_list[device], O_RDONLY | O_NONBLOCK))) {
  162. fprintf(stderr, "open %s: %sn", devname ? devname : device_list[device], sys_errlist[errno]);
  163. exit(1);
  164.     }
  165.     if (!forcepsx) {
  166. /* Checking if it's a PSX disk */
  167. printf("Checking if the disk is a PSX disk..");
  168. fflush(stdout);
  169. if (0 != (rc = read_raw_frame(cdrom, 16, buf))) { /* Safe PSX signature is at 0x9200 */
  170.     perror("read error");
  171.     exit(1);
  172. }
  173. /* Checking PSX signature */
  174. if (memcmp(psx_sign, buf, sizeof(psx_sign)) == 0) {
  175.     printf("okay, found a PSX disk.n");
  176. } else {
  177.     printf("sorry.. this doesn't seem a PSX disk.nnIf you think it's a bug, use -F flag and send a dump of the sector 16nto me, Fabio Baracca <fabiobar@tiscalinet.it>. Thanks!n");
  178.     exit(3);
  179. }
  180. close(rc);
  181.     } else {
  182. printf("-F specified: assuming that the disk is a PSX disk.n");
  183.     }
  184.     /* Checking the limits of the track */
  185.     if (-1 == (rc = open(devname, O_RDONLY | O_NONBLOCK))) {
  186. fprintf(stderr, "open %s: %sn", devname, sys_errlist[errno]);
  187. exit(1);
  188.     }
  189.     toc.cdte_track = 1;
  190.     toc.cdte_format = CDROM_LBA;
  191.     if (-1 == ioctl(rc, CDROMREADTOCENTRY, &toc)) {
  192. perror("ioctl CDROMREADTOCENTRY [start]");
  193. exit(1);
  194.     }
  195.     toc2.cdte_track = 2;
  196.     toc2.cdte_format = CDROM_LBA;
  197.     if (-1 == ioctl(rc, CDROMREADTOCENTRY, &toc2)) {
  198. toc2.cdte_track = CDROM_LEADOUT;
  199. toc2.cdte_format = CDROM_LBA;
  200. if (-1 == ioctl(rc, CDROMREADTOCENTRY, &toc2)) {
  201.     perror("ioctl CDROMREADTOCENTRY [stop]");
  202.     exit(1);
  203. }
  204.     }
  205.     block = toc.cdte_addr.lba; /* Should be zero */
  206.     if (block) {
  207. fprintf(stderr, "Hei!.. S-T-R-A-N-G-E.. starting sector is NOT zero !??!n");
  208.     }
  209.     size = (toc2.cdte_addr.lba - block) * 2048;
  210.     close(rc);
  211.     /* Opening the output file */
  212.     if (-1 == (ofile = open(outfile, O_WRONLY | O_CREAT))) {
  213. fprintf(stderr, "open %s: %sn", outfile, sys_errlist[errno]);
  214. exit(1);
  215.     }
  216.     /* Finnally dump the track */
  217.     if (-1 == (rc = open(devname ? devname : device_list[device], O_RDONLY | O_NONBLOCK))) {
  218. fprintf(stderr, "open %s: %sn", devname ? devname : device_list[device], sys_errlist[errno]);
  219. exit(1);
  220.     }
  221.     if (0 != (rc = read_raw_frame(cdrom, block, buf))) {
  222. perror("read error");
  223. exit(1);
  224.     }
  225.     printf("nDumping %d bytes (or maybe a bit less..) to disk..n", (toc2.cdte_addr.lba - block) * 2336);
  226.     printf("Please IGNORE any error! Your disk WILL BE OK! 100%% Assured!nn");
  227.     maxsize = size;
  228.     percent = 0; /* Status bar */
  229.     printf("Completed: %d%%r", percent);
  230.     fflush(stdout);
  231.     for (;;) {
  232. int offset, len, tmp;
  233. if (buf[0] == buf[4] &&
  234.     buf[1] == buf[5] &&
  235.     buf[2] == buf[6] &&
  236.     buf[3] == buf[7] &&
  237.     buf[2] != 0 &&
  238.     buf[0] < 8 &&
  239.     buf[1] < 8) {
  240.     offset = 8;
  241.     len = (buf[2] & 0x20) ? 2324 : 2048;
  242. } else {
  243.     offset = 0;
  244.     len = 2048;
  245. }
  246. write(ofile, buf, CD_FRAMESIZE_RAW0); /* dump to disk */
  247. size -= 2048 /* len */ ;
  248. block++;
  249. if (size <= 0)
  250.     break;
  251. tmp = (int) 100 - (((double) size / (double) maxsize) * 100);
  252. if (tmp != percent) {
  253.     percent = tmp;
  254.     printf("Completed: %d%%r", percent);
  255.     fflush(stdout);
  256. }
  257. if (0 != (rc = read_raw_frame(cdrom, block, buf))) {
  258.     perror("read error (hei! the disk is 99.9%% ok if we are in the last part of the disk)");
  259.     exit(1);
  260. }
  261.     }
  262.     printf("PSX data track dump complete.n");
  263.     free(buf);
  264.     exit(0);
  265. }