psxdump.c
上传用户:weiliju62
上传日期:2007-01-06
资源大小:619k
文件大小:7k
- /*
- * psxdump.c - Dumps playstation disks to file
- *
- * Portions (c) 1999 Fabio Baracca <fabiobar@tiscalinet.it>
- *
- * *HEAVILY BASED* on code from readxa.c
- * that's (c) 1996,1997 Gerd Knorr <kraxel@cs.tu-berlin.de>
- *
- */
- #include <stdio.h>
- #include <stdlib.h>
- #include <unistd.h>
- #include <getopt.h>
- #include <fcntl.h>
- #include <errno.h>
- #include <sys/stat.h>
- #include <sys/ioctl.h>
- #include <linux/cdrom.h>
- #include <linux/fs.h>
- /* Ugly, I know.. */
- extern char *sys_errlist[];
- typedef unsigned char u8bit;
- typedef unsigned short u16bit;
- typedef unsigned u32bit;
- unsigned char psx_sign[] =
- {0x00, 0x00, 0x09, 0x00, 0x00, 0x00, 0x09, 0x00, 0x01,
- 0x43, 0x44, 0x30, 0x30, 0x31, 0x01, 0x00, 0x50, 0x4C,
- 0x41, 0x59, 0x53, 0x54, 0x41, 0x54, 0x49, 0x4F, 0x4E,
- 0x20, 0x20, 0x20, 0x20, 0x20};
- typedef struct tag_iso_dir_entry {
- u8bit len_dr;
- u8bit XAR_len;
- u32bit loc_extentI;
- u32bit loc_extentM;
- u32bit data_lenI;
- u32bit data_lenM;
- u8bit record_time[7];
- u8bit file_flags_iso;
- u8bit il_size;
- u8bit il_skip;
- u16bit VSSNI;
- u16bit VSSNM;
- u8bit len_fi;
- u8bit file_id[32];
- u8bit padding;
- } iso_dir_entry;
- iso_dir_entry dir_entry;
- static const char *device_list[] =
- {
- /* try most common first ... */
- "/dev/cdrom",
- "/dev/scd0",
- "/dev/sr0",
- "/dev/hdc",
- "/dev/hdd",
- "/dev/scd1",
- "/dev/sr1",
- "/dev/scd2",
- "/dev/sr2",
- "/dev/scd3",
- "/dev/sr3",
- "/dev/hda",
- "/dev/hdb",
- "/dev/hde",
- "/dev/hdf",
- "/dev/hdg",
- "/dev/hdh",
- NULL
- };
- int print_info = 0;
- int dump_raw = 0;
- void about(void)
- {
- 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");
- }
- void usage(void)
- {
- fprintf(stderr,
- "syntax: psxdump -d <device> -f <output file>nn"
- " -d <device> give device namen"
- " -f <output file> file to put track dumpn"
- " -F force the program to proceed even if it's not a PSX diskn"
- " -T test type of disc (PSX or non) and report it as exit coden"
- " -h display this banner :-)n");
- }
- int read_raw_frame(int fd, int lba, unsigned char *buf)
- {
- struct cdrom_msf *msf;
- int rc;
- msf = (struct cdrom_msf *) buf;
- msf->cdmsf_min0 = (lba + CD_MSF_OFFSET) / CD_FRAMES / CD_SECS;
- msf->cdmsf_sec0 = (lba + CD_MSF_OFFSET) / CD_FRAMES % CD_SECS;
- msf->cdmsf_frame0 = (lba + CD_MSF_OFFSET) % CD_FRAMES;
- rc = ioctl(fd, CDROMREADMODE2, buf);
- if (-1 == rc)
- perror("ioctl CDROMREADMODE2");
- return rc;
- }
- int main(int argc, char *argv[])
- {
- int forcepsx = 0, ofile, cdrom, rc, c, size, percent, maxsize, testpsx = 0;
- unsigned long block;
- unsigned char *buf;
- struct stat st, dev_st;
- int device;
- long seek = -1;
- struct cdrom_tocentry toc, toc2;
- char *outfile = NULL, *devname = NULL;
- /* parse options */
- for (;;) {
- c = getopt(argc, argv, "TFd:f:");
- if (c == -1)
- break;
- switch (c) {
- case 'f':
- outfile = optarg;
- break;
- case 'd':
- devname = optarg;
- break;
- case 'F':
- forcepsx = 1;
- break;
- case 'T':
- testpsx = 1;
- break;
- case 'h':
- default:
- usage();
- exit(1);
- }
- }
- /* Malloc-ing memory */
- if (NULL == (buf = malloc(CD_FRAMESIZE_RAW0))) {
- fprintf(stderr, "Out of memoryn");
- exit(1);
- }
- if ((testpsx) && (devname)) {
- if (-1 == (cdrom = open(devname ? devname : device_list[device], O_RDONLY | O_NONBLOCK))) {
- fprintf(stderr, "open %s: %sn", devname ? devname : device_list[device], sys_errlist[errno]);
- exit(2);
- }
- if (0 != (rc = read_raw_frame(cdrom, 16, buf))) {
- perror("read error");
- exit(2);
- }
- close(rc);
- if (memcmp(psx_sign, buf, sizeof(psx_sign)) == 0)
- exit(0);
- else
- exit(1);
- }
-
- about();
- if ((!outfile) || (!devname)) {
- fprintf(stderr, "Please specify *either* the file name (or -T flag) *and* the device of the CD reader.nn");
- usage();
- exit(2);
- }
- /* Opening the CDROM reader */
- if (-1 == (cdrom = open(devname ? devname : device_list[device], O_RDONLY | O_NONBLOCK))) {
- fprintf(stderr, "open %s: %sn", devname ? devname : device_list[device], sys_errlist[errno]);
- exit(1);
- }
- if (!forcepsx) {
- /* Checking if it's a PSX disk */
- printf("Checking if the disk is a PSX disk..");
- fflush(stdout);
- if (0 != (rc = read_raw_frame(cdrom, 16, buf))) { /* Safe PSX signature is at 0x9200 */
- perror("read error");
- exit(1);
- }
- /* Checking PSX signature */
- if (memcmp(psx_sign, buf, sizeof(psx_sign)) == 0) {
- printf("okay, found a PSX disk.n");
- } else {
- 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");
- exit(3);
- }
- close(rc);
- } else {
- printf("-F specified: assuming that the disk is a PSX disk.n");
- }
- /* Checking the limits of the track */
- if (-1 == (rc = open(devname, O_RDONLY | O_NONBLOCK))) {
- fprintf(stderr, "open %s: %sn", devname, sys_errlist[errno]);
- exit(1);
- }
- toc.cdte_track = 1;
- toc.cdte_format = CDROM_LBA;
- if (-1 == ioctl(rc, CDROMREADTOCENTRY, &toc)) {
- perror("ioctl CDROMREADTOCENTRY [start]");
- exit(1);
- }
- toc2.cdte_track = 2;
- toc2.cdte_format = CDROM_LBA;
- if (-1 == ioctl(rc, CDROMREADTOCENTRY, &toc2)) {
- toc2.cdte_track = CDROM_LEADOUT;
- toc2.cdte_format = CDROM_LBA;
- if (-1 == ioctl(rc, CDROMREADTOCENTRY, &toc2)) {
- perror("ioctl CDROMREADTOCENTRY [stop]");
- exit(1);
- }
- }
- block = toc.cdte_addr.lba; /* Should be zero */
- if (block) {
- fprintf(stderr, "Hei!.. S-T-R-A-N-G-E.. starting sector is NOT zero !??!n");
- }
- size = (toc2.cdte_addr.lba - block) * 2048;
- close(rc);
- /* Opening the output file */
- if (-1 == (ofile = open(outfile, O_WRONLY | O_CREAT))) {
- fprintf(stderr, "open %s: %sn", outfile, sys_errlist[errno]);
- exit(1);
- }
- /* Finnally dump the track */
- if (-1 == (rc = open(devname ? devname : device_list[device], O_RDONLY | O_NONBLOCK))) {
- fprintf(stderr, "open %s: %sn", devname ? devname : device_list[device], sys_errlist[errno]);
- exit(1);
- }
- if (0 != (rc = read_raw_frame(cdrom, block, buf))) {
- perror("read error");
- exit(1);
- }
- printf("nDumping %d bytes (or maybe a bit less..) to disk..n", (toc2.cdte_addr.lba - block) * 2336);
- printf("Please IGNORE any error! Your disk WILL BE OK! 100%% Assured!nn");
- maxsize = size;
- percent = 0; /* Status bar */
- printf("Completed: %d%%r", percent);
- fflush(stdout);
- for (;;) {
- int offset, len, tmp;
- if (buf[0] == buf[4] &&
- buf[1] == buf[5] &&
- buf[2] == buf[6] &&
- buf[3] == buf[7] &&
- buf[2] != 0 &&
- buf[0] < 8 &&
- buf[1] < 8) {
- offset = 8;
- len = (buf[2] & 0x20) ? 2324 : 2048;
- } else {
- offset = 0;
- len = 2048;
- }
- write(ofile, buf, CD_FRAMESIZE_RAW0); /* dump to disk */
- size -= 2048 /* len */ ;
- block++;
- if (size <= 0)
- break;
- tmp = (int) 100 - (((double) size / (double) maxsize) * 100);
- if (tmp != percent) {
- percent = tmp;
- printf("Completed: %d%%r", percent);
- fflush(stdout);
- }
- if (0 != (rc = read_raw_frame(cdrom, block, buf))) {
- perror("read error (hei! the disk is 99.9%% ok if we are in the last part of the disk)");
- exit(1);
- }
- }
- printf("PSX data track dump complete.n");
- free(buf);
- exit(0);
- }