home *** CD-ROM | disk | FTP | other *** search
/ Collection of Hack-Phreak Scene Programs / cleanhpvac.zip / cleanhpvac / FAQSYS18.ZIP / FAQS.DAT / READCDA.C < prev    next >
C/C++ Source or Header  |  1996-08-05  |  13KB  |  588 lines

  1. /*
  2.  
  3.   GOAL:
  4.     This program is intended to read CD audio data into a disk file.
  5.  
  6.   Author:
  7.     Yeng-Chee Su (yenchee@csie.nctu.edu.tw)
  8.     Department of Computer Science and Information Engineering
  9.     National Chiao Tung University
  10.     &
  11.     Klaas Hemstra (hst@mh.nl)
  12.     Gouda, the Netherlands
  13.  
  14.   Notice:
  15.     Most CD-ROM drive doesn't have the capability to read raw
  16.     data on compact disk, but some drives can work.  These includes
  17.     Panasonic CR-562B/563B and Toshiba XM-3401B.  This program
  18.     is designed on CR-562B and should work well on it.  If it
  19.     can't work for you, find a better driver around.
  20.     Yeng-Chee Su wrote the first attempt, but the program depended on
  21.     the speed of the file-system for clean 'recordings'.
  22.  
  23.     The buffered read + synchronisation is added later by me.
  24.  
  25. */
  26.  
  27. #include <stdio.h>
  28. #include <stdlib.h>
  29. #include <conio.h>
  30. #include <dos.h>
  31. #include <dir.h>
  32. #include <string.h>
  33. #include <ctype.h>
  34. #include <fcntl.h>
  35. #include <sys/stat.h>
  36. #include <io.h>
  37.  
  38. #define RAW_MODE 1
  39. #define COOKED_MODE 0
  40. #define READ_MODE RAW_MODE
  41. #if READ_MODE == COOKED_MODE
  42.   #define FRAME_SIZE 2048
  43. #else
  44.   #define FRAME_SIZE 2352
  45. #endif
  46. #define NBLOCK 16
  47. #define NBUF   10
  48. #define SYNCH_SIZE 128  /* Bytes synch pattern */
  49.  
  50. typedef unsigned char BYTE;
  51. typedef unsigned int WORD;
  52. typedef unsigned long int DWORD;
  53.  
  54. struct ReqHdr {
  55.   BYTE len;
  56.   BYTE unit;
  57.   BYTE command;
  58.   WORD status;
  59.   BYTE reserved[8];
  60. };
  61.  
  62. struct IOCTLI {
  63.   struct ReqHdr req;
  64.   BYTE descriptor;
  65.   void far *address;
  66.   WORD len;
  67.   WORD secnum;
  68.   void far *ptr;
  69. };
  70.  
  71. struct DeviceStatus {
  72.   BYTE control;
  73.   DWORD param;
  74. };
  75.  
  76. struct DiskInfo {
  77.   BYTE control;
  78.   BYTE lowest;
  79.   BYTE highest;
  80.   DWORD total;
  81. };
  82.  
  83. struct TrackInfo {
  84.   BYTE control;
  85.   BYTE track;
  86.   DWORD loc;
  87.   BYTE info;
  88. };
  89.  
  90. struct SEEK {
  91.   struct ReqHdr req;
  92.   BYTE mode;
  93.   DWORD address;
  94.   WORD secnum;
  95.   DWORD loc;
  96. };
  97.  
  98. struct PlayReq {
  99.   struct ReqHdr req;
  100.   BYTE mode;
  101.   DWORD loc;
  102.   DWORD secnum;
  103. };
  104.  
  105. int CDROM;
  106. int lowest, highest;
  107. DWORD total_time;
  108. char image[MAXPATH];
  109.  
  110. void CallDevice(void *ptr)
  111. {
  112.   static union REGS reg;
  113.   static struct SREGS seg;
  114.  
  115.   segread(&seg);
  116.   seg.es=FP_SEG(ptr);
  117.   reg.x.ax=0x1510;
  118.   reg.x.bx=FP_OFF(ptr);
  119.   reg.x.cx=CDROM;
  120.   int86x(0x2f, ®, ®, &seg);
  121. }
  122.  
  123. int check_mscdex(void)
  124. {
  125.   union REGS reg;
  126.  
  127.   reg.x.ax=0x1500;
  128.   reg.x.bx=0;
  129.   int86(0x2f, ®, ®);
  130.   if (!reg.x.bx)
  131.      return 0;
  132.   else {
  133.      CDROM=reg.x.cx;
  134.      return 1;
  135.   }
  136. }
  137.  
  138. int GetDeviceStatus(void)
  139. {
  140.   struct IOCTLI cmd;
  141.   struct DeviceStatus buf;
  142.  
  143.   cmd.req.len=26;
  144.   cmd.req.unit=0;
  145.   cmd.req.command=3;
  146.   cmd.descriptor=0;
  147.   cmd.address=&buf;
  148.   cmd.len=5;
  149.   cmd.secnum=0;
  150.   cmd.ptr=NULL;
  151.   buf.control=6;
  152.   CallDevice(&cmd);
  153.   return cmd.req.status;
  154. }
  155.  
  156. int GetDiskInfo(void)
  157. {
  158.   struct IOCTLI cmd;
  159.   struct DiskInfo buf;
  160.  
  161.   cmd.req.len=26;
  162.   cmd.req.unit=0;
  163.   cmd.req.command=3;
  164.   cmd.descriptor=0;
  165.   cmd.address=&buf;
  166.   cmd.len=7;
  167.   cmd.secnum=0;
  168.   cmd.ptr=NULL;
  169.   buf.control=10;
  170.   CallDevice(&cmd);
  171.   lowest=buf.lowest;
  172.   highest=buf.highest;
  173.   total_time=buf.total;
  174.   return cmd.req.status;
  175. }
  176.  
  177. int GetTrackInfo(int track, DWORD *loc, BYTE *info)
  178. {
  179.   struct IOCTLI cmd;
  180.   struct TrackInfo buf;
  181.  
  182.   cmd.req.len=26;
  183.   cmd.req.unit=0;
  184.   cmd.req.command=3;
  185.   cmd.descriptor=0;
  186.   cmd.address=&buf;
  187.   cmd.len=7;
  188.   cmd.secnum=0;
  189.   cmd.ptr=NULL;
  190.   buf.control=11;
  191.   buf.track=track;
  192.   CallDevice(&cmd);
  193.   *loc=buf.loc;
  194.   *info=buf.info;
  195.   return cmd.req.status;
  196. }
  197.  
  198. int SeekTrack(DWORD loc)
  199. {
  200.   struct SEEK cmd;
  201.  
  202.   cmd.req.len=24;
  203.   cmd.req.unit=0;
  204.   cmd.req.command=131;
  205.   cmd.mode=1;
  206.   cmd.address=NULL;
  207.   cmd.secnum=0;
  208.   cmd.loc=loc;
  209.   CallDevice(&cmd);
  210.   return cmd.req.status;
  211. }
  212.  
  213. int PlayAudio(DWORD loc, DWORD num)
  214. {
  215.   struct PlayReq cmd;
  216.  
  217.   cmd.req.len=22;
  218.   cmd.req.unit=0;
  219.   cmd.req.command=132;
  220.   cmd.mode=1;
  221.   cmd.loc=loc;
  222.   cmd.secnum=num;
  223.   CallDevice(&cmd);
  224.   return cmd.req.status;
  225. }
  226.  
  227. int StopAudio(void)
  228. {
  229.   struct ReqHdr cmd;
  230.  
  231.   cmd.len=13;
  232.   cmd.unit=0;
  233.   cmd.command=133;
  234.   CallDevice(&cmd);
  235.   return cmd.status;
  236. }
  237.  
  238. DWORD Red2Sierra(DWORD loc)
  239. {
  240.   BYTE min, sec, frame;
  241.  
  242.   min = (loc >> 16) & 0xff;
  243.   sec = (loc >> 8) & 0xff;
  244.   frame = loc & 0xff;
  245.   return (DWORD)min * 75 * 60 + (DWORD)sec * 75 + (DWORD)frame - 150;
  246. }
  247.  
  248. int ReadLong(DWORD loc, WORD secnum, char far *buf)
  249. {
  250.   struct ReadL {
  251.     struct ReqHdr req;
  252.     BYTE mode;
  253.     void far *address;
  254.     WORD secnum;
  255.     DWORD loc;
  256.     BYTE readmode;
  257.     BYTE skip[2];
  258.   } cmd;
  259.  
  260.   cmd.req.len=sizeof(cmd);
  261.   cmd.req.unit=0;
  262.   cmd.req.command=128;
  263.   cmd.mode=0;
  264.   cmd.address=buf;
  265.   cmd.secnum=secnum;
  266.   cmd.loc=loc;
  267.   cmd.readmode=READ_MODE;
  268.   cmd.skip[0]=cmd.skip[1]=0;
  269.   CallDevice(&cmd);
  270.   return cmd.req.status;
  271. }
  272.  
  273. int GetVolSize(DWORD *size)
  274. {
  275.   struct IOCTLI cmd;
  276.   struct {
  277.     BYTE control;
  278.     DWORD size;
  279.   } buf;
  280.  
  281.   cmd.req.len=sizeof(cmd);
  282.   cmd.req.unit=0;
  283.   cmd.req.command=3;
  284.   cmd.descriptor=0;
  285.   cmd.address=&buf;
  286.   cmd.len=sizeof(buf);
  287.   cmd.secnum=0;
  288.   cmd.ptr=NULL;
  289.   buf.control=8;
  290.   CallDevice(&cmd);
  291.   *size=buf.size;
  292.   return cmd.req.status;
  293. }
  294.  
  295. char *
  296. location_str( DWORD loc)
  297. {
  298.     static char ret_buf[256];
  299.     long min,sec,frames;
  300.  
  301.     frames = loc % 75;
  302.     sec = (loc+150) / 75;
  303.     min = sec / 60;
  304.     sec = sec % 60;
  305.  
  306.     sprintf(ret_buf,"High sierra %ld ; %02ld:%02ld.%02ld",loc,min,sec,frames);
  307.     return ret_buf;
  308. }
  309.  
  310. void
  311. read_location(char *question,DWORD *loc)
  312. {
  313. #define MAX_LOC 256
  314.     char buf[MAX_LOC],*p;
  315.     buf[0] = '\0';
  316.  
  317.     while (buf[0] == '\0') {
  318.     printf("%s",question);
  319.     fgets(buf,MAX_LOC,stdin);
  320.     }
  321.     for (p=buf;*p && (*p != ':'); p++)
  322.       ;
  323.     if (*p == ':') {
  324.       *loc = atol(buf)*75L*60L+atol(p+1)*75L;
  325.     } else {
  326.       *loc = atol(buf);
  327.     }
  328. }
  329.  
  330.  
  331. void main()
  332. {
  333.   WORD status;
  334.   char *buf[NBUF],*previous_end;
  335.   DWORD *track_loc, loc, end_pos, size;
  336.   DWORD i, j, offset,synch_size;
  337.   BYTE info;
  338.   int fd, key, n,first_time;
  339.   int retry, waveform;
  340.   struct RIFF {
  341.     char rID[4];
  342.     DWORD rLen;
  343.   } riff;
  344.   struct FORMAT {
  345.     char fID[4];
  346.     DWORD fLen;
  347.     WORD wTag;
  348.     WORD wChannel;
  349.     DWORD nSample;
  350.     DWORD nByte;
  351.     WORD align;
  352.     WORD sample;
  353.   };
  354.   struct DATA {
  355.     char dID[4];
  356.     DWORD dLen;
  357.   };
  358.   struct WAVE {
  359.     char wID[4];
  360.     struct FORMAT fmt;
  361.     struct DATA data;
  362.   } wave;
  363.  
  364.   printf("CD-ROM digital audio data extractor, Ver 1.1\n");
  365.   printf(" written by Yeng-Chee Su, CSIE, NCTU & Klaas Hemstra (hst@mh.nl)\n");
  366.   printf("\n");
  367.  
  368.    /*
  369.     * Allocate memory buffers
  370.    */
  371.   for (i=0; i< NBUF; i++)
  372.     buf[i] = (char*)malloc((long)FRAME_SIZE * NBLOCK);
  373.     if (buf[i] == NULL) {
  374.       printf("Out of memory!\n");
  375.       exit(1);
  376.     }
  377.   previous_end = (char*)malloc((long)FRAME_SIZE * NBLOCK);
  378.   if (previous_end == (char *) NULL) {
  379.     printf("Out of memory!\n");
  380.     exit(1);
  381.   }
  382.  
  383.    /*
  384.     * Get Disc info
  385.    */
  386.   if (!check_mscdex()) {
  387.     printf("No CD-ROM extension available!\n");
  388.     exit(1);
  389.   }
  390.   retry=0;
  391.   status=GetDiskInfo();
  392.   while (status != 0x0100) {
  393.     printf("Can't get CD-ROM information, status=%x\n", status);
  394.     delay(1000);
  395.     retry++;
  396.     if (retry == 3) {
  397.       printf("Get CD-ROM information failed\n");
  398.       exit(1);
  399.     }
  400.     status=GetDiskInfo();
  401.   }
  402.   track_loc=(DWORD*)malloc(sizeof(DWORD)*(highest-lowest+2));
  403.   if (track_loc==NULL) {
  404.     printf("Out of memory!\n");
  405.     exit(1);
  406.   }
  407.   track_loc = &track_loc[-lowest];
  408.   track_loc[highest+1]=total_time;
  409.   for (i=lowest; i<=highest; i++) {
  410.     status=GetTrackInfo(i, &loc, &info);
  411.     track_loc[i]=loc;
  412.   }
  413.   for (i=lowest; i<=highest; i++)
  414.     printf("Track %2ld : %02ld:%02ld.%02ld %6ld Len = %ld\n", i, (track_loc[i] >> 16) & 0xff,
  415.      (track_loc[i] >> 8) & 0xff, track_loc[i] & 0xff, Red2Sierra(track_loc[i]),
  416.      Red2Sierra(track_loc[i+1]) - Red2Sierra(track_loc[i]));
  417.   printf("Total time : %02ld:%02ld.%02ld\n", (total_time >> 16) & 0xff,
  418.    (total_time >> 8) & 0xff, total_time & 0xff);
  419.  
  420.    /*
  421.     * User interface
  422.    */
  423.   printf("Image filename:");
  424.   gets(image);
  425.   printf("(0) CDDA format, (1) WAV format :");
  426.   key = getch();
  427.   while (key != '0' && key != '1')
  428.     key = getch();
  429.   printf("%c\n", key);
  430.   if (key == '1') waveform = 1; else waveform = 0;
  431.  
  432.   printf("(0) Read Track, (1) Read A to B :");
  433.   key = getch();
  434.   while (key != '0' && key != '1')
  435.     key = getch();
  436.   printf("%c\n", key);
  437.   if (key == '1') {
  438.     read_location("Start location (High sierra or min:sec) : ",&loc);
  439.     read_location("Frame length (Sectors or min:sec) : ",&size);
  440.   } else {
  441. track_again:
  442.     printf("Which track :");
  443.     scanf("%d", &n);
  444.     if (n < lowest || n > highest) {
  445.       printf("illega track!\n");
  446.       goto track_again;
  447.     }
  448.     loc = Red2Sierra(track_loc[n]);
  449.     size = Red2Sierra(track_loc[n+1]) - Red2Sierra(track_loc[n]);
  450.   }
  451.   printf("Start location %s\n", location_str(loc));
  452.   printf("Stop location %s\n", location_str(loc+size));
  453.  
  454.    /*
  455.     * Create the file
  456.    */
  457.   _fmode = O_BINARY;
  458.   fd = creat(image, S_IREAD|S_IWRITE);
  459.   if (fd == -1) {
  460.     perror("open");
  461.     exit(1);
  462.   }
  463.  
  464.   if (waveform) {
  465.     strcpy(riff.rID, "RIFF");
  466.     riff.rLen = FRAME_SIZE * (DWORD)size + sizeof(struct WAVE);
  467.     strcpy(wave.wID, "WAVE");
  468.     strcpy(wave.fmt.fID, "fmt ");
  469.     wave.fmt.fLen = sizeof(struct FORMAT) - 8;
  470.     wave.fmt.wTag = 1;
  471.     wave.fmt.wChannel = 2;
  472.     wave.fmt.nSample = 44100L;
  473.     wave.fmt.nByte = 44100L * 4;
  474.     wave.fmt.align = 4;
  475.     wave.fmt.sample = 16;
  476.     strcpy(wave.data.dID, "data");
  477.     wave.data.dLen = FRAME_SIZE * (DWORD)size;
  478.     if (write(fd, &riff, sizeof(struct RIFF)) != sizeof(struct RIFF)) {
  479.       perror("write");
  480.       exit(1);
  481.     }
  482.     if (write(fd, &wave, sizeof(struct WAVE)) != sizeof(struct WAVE)) {
  483.       perror("write");
  484.       exit(1);
  485.     }
  486.   }
  487.  
  488.    /*
  489.     * Read the date in blocks, first in memory
  490.    */
  491.   wave.data.dLen = 0L;
  492.   first_time = 1;
  493.   end_pos = loc+size;
  494.   while (loc < end_pos) {
  495.  
  496.     for (i=0;(i < NBUF);i++) {
  497.       printf("\rReading frame %ld to %ld in memory                          \r",
  498.                                                                loc, loc+NBLOCK-1);
  499.       status = ReadLong(loc, NBLOCK, buf[i]);
  500.       if (status != 0x0100) {
  501.         printf("CDROM read with status %x\n", status);
  502.     exit(1);
  503.       }
  504.       loc += NBLOCK;
  505.     }
  506.  
  507.     if (first_time == 0) {
  508.       /*
  509.        * Synchronize data to previous block
  510.       */
  511.       offset = 0;
  512.       synch_size = SYNCH_SIZE;
  513.       while (offset == 0) {
  514.         for (i=(NBLOCK/4)*FRAME_SIZE;
  515.              i < (((unsigned int)NBLOCK*FRAME_SIZE)-synch_size);
  516.          i+=4) {
  517.       if (memcmp(previous_end+(NBLOCK/2)*FRAME_SIZE,buf[0]+i,synch_size) == 0) {
  518.         if (offset == 0)
  519.           offset = i;
  520.         else {
  521.           synch_size *= 2;
  522.           if (synch_size > 4096) {
  523.         fprintf(stderr,"Synchronisation failed, synch size to big !!\n");
  524.         exit(1);
  525.           }
  526.           break;
  527.         }
  528.       }
  529.     }
  530.     if (offset == 0) {
  531.       fprintf(stderr,"Synchronisation failed, no matching block found !!\n");
  532.       exit(1);
  533.     }
  534.       }
  535.     }
  536.     else
  537.       offset = 0;
  538.  
  539.     first_time = 0;
  540.  
  541.     memcpy(previous_end,buf[NBUF-1],(long)FRAME_SIZE*NBLOCK);
  542.  
  543.     printf("\rSynchronized write frame %ld to %ld to disk, offset = %ld    ",
  544.         loc-(NBUF*NBLOCK),loc-(NBLOCK/2),offset-(NBLOCK/2*FRAME_SIZE));
  545.  
  546.     for (i=0;(i < NBUF-1);i++) {
  547.       if (write(fd, buf[i]+offset, ((long) FRAME_SIZE * NBLOCK)-offset) == -1) {
  548.     perror("write");
  549.     exit(1);
  550.       }
  551.       wave.data.dLen += (((long) FRAME_SIZE * NBLOCK)-offset);
  552.       offset = 0;
  553.     }
  554.  
  555.        /*
  556.         * Write only half of last buffer,
  557.         * The next loop, after synchronisation the rest will be written
  558.        */
  559.  
  560.     if (write(fd, buf[NBUF-1], ((long) FRAME_SIZE * (NBLOCK/2))) == -1) {
  561.       perror("write");
  562.       exit(1);
  563.     }
  564.     wave.data.dLen += ((long) FRAME_SIZE * (NBLOCK/2));
  565.  
  566.     loc -= NBLOCK;
  567.     /* sleep(1); */
  568.   }
  569.  
  570.   if (waveform) {
  571.     lseek(fd,0L,SEEK_SET);
  572.     printf("\nCompleting header information of WAV file\n");
  573.     riff.rLen = wave.data.dLen + sizeof(struct WAVE);
  574.     if (write(fd, &riff, sizeof(struct RIFF)) != sizeof(struct RIFF)) {
  575.       perror("write");
  576.       exit(1);
  577.     }
  578.     if (write(fd, &wave, sizeof(struct WAVE)) != sizeof(struct WAVE)) {
  579.       perror("write");
  580.       exit(1);
  581.     }
  582.   }
  583.  
  584.   close(fd);
  585.   free(&track_loc[lowest]);
  586.   free(buf);
  587. }
  588.