home *** CD-ROM | disk | FTP | other *** search
/ QBasic & Borland Pascal & C / Delphi5.iso / C / Samples / CD-ROM.ARJ / CD-ROM.C
Encoding:
C/C++ Source or Header  |  1994-07-29  |  36.9 KB  |  1,193 lines

  1. #include <conio.h>
  2. #include <stdio.h>
  3. #include <stdlib.h>
  4. #include <string.h>
  5. #include <dos.h>
  6. #include <time.h>
  7.  
  8. #define V1    75L
  9. #define V2    4500L
  10. #define V3    270000L
  11. /*--- bcd2 - bcd1 ---*/
  12.     unsigned long bcd_sub ( unsigned long bcd1 ,
  13.                 unsigned long bcd2 )
  14.     {
  15.       unsigned long t11 = 0 , t12 = 0 , t1r = 0 , t2r = 0 ;
  16.  
  17.       t11 = bcd1&0x000000FF ;  t12 = bcd2&0x000000FF ;
  18.       t1r += t11 ;  t2r += t12 ;
  19.  
  20.       t11 = (bcd1>>8)&0x000000FF ;  t12 = (bcd2>>8)&0x000000FF ;
  21.       t1r += ( t11 * V1 ) ;  t2r += ( t12 * V1 ) ;
  22.  
  23.       t11 = (bcd1>>16)&0x000000FF ;  t12 = (bcd2>>16)&0x000000FF ;
  24.       t1r += ( t11 * V2 ) ;  t2r += ( t12 * V2 ) ;
  25.  
  26.       t11 = (bcd1>>24)&0x000000FF ;  t12 = (bcd2>>24)&0x000000FF ;
  27.       t1r += ( t11 * V3 ) ;  t2r += ( t12 * V3 ) ;
  28.  
  29.       return ( t2r - t1r ) ;
  30.     }  /* END bcd_sub */
  31. /*---*/
  32. /*--- bcd1 + bcd2 ---*/
  33.     unsigned long bcd_add ( unsigned long bcd1 ,
  34.                 unsigned long bcd2 )
  35.     {
  36.       unsigned long t11 = 0 , t12 = 0 , t1r = 0 , t2r = 0 ;
  37.  
  38.       t11 = bcd1&0x000000FF ;  t12 = bcd2&0x000000FF ;
  39.       t1r += t11 ;  t2r += t12 ;
  40.  
  41.       t11 = (bcd1>>8)&0x000000FF ;  t12 = (bcd2>>8)&0x000000FF ;
  42.       t1r += ( t11 * V1 ) ;  t2r += ( t12 * V1 ) ;
  43.  
  44.       t11 = (bcd1>>16)&0x000000FF ;  t12 = (bcd2>>16)&0x000000FF ;
  45.       t1r += ( t11 * V2 ) ;  t2r += ( t12 * V2 ) ;
  46.  
  47.       t11 = (bcd1>>24)&0x000000FF ;  t12 = (bcd2>>24)&0x000000FF ;
  48.       t1r += ( t11 * V3 ) ;  t2r += ( t12 * V3 ) ;
  49.  
  50.       return ( t2r + t1r ) ;
  51.     }  /* END bcd_add */
  52. /*---*/
  53.     unsigned long dec2bcd ( unsigned long val )
  54.     {
  55.       unsigned long t1 , t2 = 0 , t3 = val ;
  56.  
  57.       t1 = t3 / V2 ;  t2 += ( t1 * 65536L ) ;  t3 = t3 % V2 ;
  58.       t1 = t3 / V1 ;  t2 += ( t1 * 256L ) ;   t3 = t3 % V1 ;
  59.       t2 += ( t1 % V1 ) ;
  60.  
  61.       return ( t2 ) ;
  62.     }  /* END dec2bcd */
  63. /*---*/
  64.     void dec_t_time ( unsigned long bcd , unsigned *min ,
  65.               unsigned *sec , unsigned *frame )
  66.     {
  67.       unsigned long t1 ;
  68.  
  69.       t1 = *min = bcd / V2 ;
  70.       t1 = bcd % V2 ;
  71.       *sec = t1 / V1 ;
  72.       *frame = t1 % V1 ;
  73.     }  /* END dec_t_time */
  74. /*---*/
  75.     unsigned error_code ( unsigned char b1 , unsigned char b2 )
  76.     {
  77.       if ( b2&0x80 )
  78.       {
  79.        if ( b1 == 0 ) return ( 3 ) ;        /* Write protect violation */
  80.        else if ( b1 == 1 ) return ( 4 ) ;   /* Unknown unit */
  81.        else if ( b1 == 2 ) return ( 5 ) ;   /* Drive not ready */
  82.        else if ( b1 == 3 ) return ( 6 ) ;   /* Unknown command */
  83.        else if ( b1 == 4 ) return ( 7 ) ;   /* CRC error */
  84.        else if ( b1 == 5 ) return ( 8 ) ;   /* Bad header length */
  85.        else if ( b1 == 6 ) return ( 9 ) ;   /* Seek error */
  86.        else if ( b1 == 7 ) return ( 10 ) ;  /* Unknown media */
  87.        else if ( b1 == 8 ) return ( 11 ) ;  /* Sector not found */
  88.        else if ( b1 == 9 ) return ( 12 ) ;  /* Printer out of paper */
  89.        else if ( b1 == 10 ) return ( 13 ) ; /* Write fault */
  90.        else if ( b1 == 11 ) return ( 14 ) ; /* Read fault */
  91.        else if ( b1 == 12 ) return ( 15 ) ; /* General failure */
  92.        else if ( b1 == 15 ) return ( 16 ) ; /* Invalid disk change */
  93.        else if ( b1 == 0xFE ) return ( 17 ) ; /* Invalid track */
  94.        else if ( b1 == 0xFD ) return ( 18 ) ; /* EOT reached */
  95.        else if ( b1 == 0xFF ) return ( 19 ) ; /* CD-ROM letter !found */
  96.        else return ( 0xFF ) ;                 /* Unknown error */
  97.       }  /* Error detected */
  98.       else
  99.       {
  100.         if ( b2&2 ) return ( 2 ) ;             /* Busy */
  101.         else if ( b2&1 ) return ( 1 ) ;        /* Done */
  102.         else return ( 0 ) ;                    /* OK */
  103.       }  /* No errors */
  104.     }  /* END error_code */
  105. /*---*/
  106.     unsigned cd_stat ( unsigned d_num , unsigned *status )
  107.     {
  108.       union REGS regs ;
  109.       struct SREGS sregs ;
  110.       unsigned char buf [30] , buf2 [10] ;
  111.       unsigned num , start ;
  112.       unsigned long tmp ;
  113. /* Attempt to detect CD-ROM */
  114.       regs.x.ax = 0x1500 ;  regs.x.bx = 0 ;
  115.  
  116.       int86x ( 0x2F , ®s , ®s , &sregs ) ;
  117.  
  118.       num = regs.x.bx ;  start = regs.x.cx ;
  119.  
  120.       if ( num == 0 ) return ( error_code ( 0xFF , 0x80 ) ) ;
  121. /* parameters & drive subcode */
  122.       regs.h.ah = 0x15 ;  regs.h.al = 0x10 ;
  123.       regs.x.cx = start ;
  124. /* buffer length, unit, command code */
  125.       buf [0] = 30 ;  buf [1] = d_num ;  buf [2] = 3 ;
  126. /* return parameters */
  127.       buf [3] = buf [4] = 0 ;
  128. /* reserved 8 bytes */
  129.       buf [5] = buf [6] = buf [7] = buf [8] = buf [9] = 0 ;
  130.       buf [10] = buf [11] = buf [12] = 0 ;
  131. /* reserved */
  132.       buf [13] = 0 ;
  133. /* transfer address */
  134.       *(unsigned long *)(&buf [14]) = (unsigned long)(&buf2 [0]) ;
  135. /* number of bytes to transfer */
  136.       *(unsigned long *)(&buf [18]) = 5 ;
  137. /* starting sector number */
  138.       buf [22] = buf [23] = buf [24] = buf [25] = 0 ;
  139. /* vol ID */
  140.       buf [26] = buf [27] = buf [28] = buf [29] = 0 ;
  141. /* control block code */
  142.       buf2 [0] = 6 ;
  143. /* parameter's block */
  144.       sregs.es =  FP_SEG ( buf ) ;  regs.x.bx = FP_OFF ( buf ) ;
  145.  
  146.       int86x ( 0x2F , ®s , ®s , &sregs ) ;
  147.  
  148.       tmp = *(unsigned long *)(&buf2 [1]) ;
  149.  
  150.       *status = 0 ;
  151.  
  152.           if ( tmp&1 ) *status |= 1 ;        /* Tray is open */
  153.           if ( tmp&2 ) *status |= 2 ;        /* Door unlocked */
  154.       if ( tmp&4 ) *status |= 4 ;        /* Supports 2 read modes */
  155.       if ( tmp&8 ) *status |= 8 ;        /* Read/Write features */
  156.           if ( tmp&16 ) *status |= 16 ;      /* Data & Audio */
  157.           if ( tmp&32 ) *status |= 32 ;      /* Interleaving */
  158.           if ( tmp&128 ) *status |= 64 ;     /* Prefetching requests */
  159.           if ( tmp&256 ) *status |= 128 ;    /* Audio channel tricks */
  160.           if ( tmp&512 ) *status |= 256 ;    /* HSG & Red Book */
  161.       if ( tmp&2048 ) *status |= 512 ;   /* No disk in drive */
  162.           if ( tmp&4096 ) *status |= 1024 ;  /* R-W subchannels support */
  163.  
  164.           return ( error_code ( buf [3] , buf [4] ) ) ;
  165.     }  /* END cd_stat */
  166. /*---*/
  167.     unsigned cd_audio_info ( unsigned d_num , unsigned *low ,
  168.                  unsigned *high , unsigned long *l_out )
  169.     {
  170.       union REGS regs ;
  171.       struct SREGS sregs ;
  172.       unsigned char buf [30] , buf2 [10] ;
  173.       unsigned num , start ;
  174. /* Attempt to detect CD-ROM */
  175.       regs.x.ax = 0x1500 ;  regs.x.bx = 0 ;
  176.  
  177.       int86x ( 0x2F , ®s , ®s , &sregs ) ;
  178.  
  179.       num = regs.x.bx ;  start = regs.x.cx ;
  180.  
  181.       if ( num == 0 ) return ( error_code ( 0xFF , 0x80 ) ) ;
  182. /* parameters & drive subcode */
  183.       regs.h.ah = 0x15 ;  regs.h.al = 0x10 ;
  184.       regs.x.cx = start ;
  185. /* buffer length, unit, command code */
  186.       buf [0] = 30 ;  buf [1] = d_num ;  buf [2] = 3 ;
  187. /* return parameters */
  188.       buf [3] = buf [4] = 0 ;
  189. /* reserved 8 bytes */
  190.       buf [5] = buf [6] = buf [7] = buf [8] = buf [9] = 0 ;
  191.       buf [10] = buf [11] = buf [12] = 0 ;
  192. /* number of units */
  193.       buf [13] = 0 ;
  194. /* transfer address */
  195.       *(unsigned long *)(&buf [14]) = (unsigned long)(&buf2 [0]) ;
  196. /* number of bytes to transfer */
  197.       *(unsigned long *)(&buf [18]) = 7 ;
  198. /* starting sector number */
  199.       buf [22] = buf [23] = buf [24] = buf [25] = 0 ;
  200. /* vol ID */
  201.       buf [26] = buf [27] = buf [28] = buf [29] = 0 ;
  202. /* control block code */
  203.       buf2 [0] = 10 ;
  204.       buf2 [1] = buf2 [2] = buf2 [3] = 0 ;
  205.       buf2 [4] = buf2 [5] = buf2 [6] = 0 ;
  206. /* parameter's block */
  207.       sregs.es =  FP_SEG ( buf ) ;  regs.x.bx = FP_OFF ( buf ) ;
  208.  
  209.       int86x ( 0x2F , ®s , ®s , &sregs ) ;
  210.  
  211.       *low = (unsigned )(buf2 [1]) ;
  212.       *high = (unsigned)(buf2 [2]) ;
  213.       *l_out = *(unsigned long *)(&buf2 [3]) ;
  214.  
  215.       return ( error_code ( buf [3] , buf [4] ) ) ;
  216.     }  /* END cd_audio_info */
  217. /*---*/
  218.     unsigned cd_media ( unsigned d_num , unsigned *status )
  219.     {
  220.       union REGS regs ;
  221.       struct SREGS sregs ;
  222.       unsigned char buf [30] , buf2 [10] ;
  223.       unsigned num , start ;
  224. /* Attempt to detect CD-ROM */
  225.       regs.x.ax = 0x1500 ;  regs.x.bx = 0 ;
  226.  
  227.       int86x ( 0x2F , ®s , ®s , &sregs ) ;
  228.  
  229.       num = regs.x.bx ;  start = regs.x.cx ;
  230.  
  231.           if ( num == 0 ) return ( error_code ( 0xFF , 0x80 ) ) ;
  232. /* parameters & drive subcode */
  233.       regs.h.ah = 0x15 ;  regs.h.al = 0x10 ;
  234.       regs.x.cx = start ;
  235. /* buffer length, unit, command code */
  236.       buf [0] = 30 ;  buf [1] = d_num ;  buf [2] = 3 ;
  237. /* return parameters */
  238.       buf [3] = buf [4] = 0 ;
  239. /* reserved 8 bytes */
  240.       buf [5] = buf [6] = buf [7] = buf [8] = buf [9] = 0 ;
  241.       buf [10] = buf [11] = buf [12] = 0 ;
  242. /* number of units */
  243.       buf [13] = 0 ;
  244. /* transfer address */
  245.       *(unsigned long *)(&buf [14]) = (unsigned long)(&buf2 [0]) ;
  246. /* number of bytes to transfer */
  247.       *(unsigned long *)(&buf [18]) = 2 ;
  248. /* starting sector number */
  249.       buf [22] = buf [23] = buf [24] = buf [25] = 0 ;
  250. /* vol ID */
  251.       buf [26] = buf [27] = buf [28] = buf [29] = 0 ;
  252. /* control block code */
  253.       buf2 [0] = 9 ;  buf2 [1] = 0 ;
  254. /* parameter's block */
  255.       sregs.es =  FP_SEG ( buf ) ;  regs.x.bx = FP_OFF ( buf ) ;
  256.  
  257.       int86x ( 0x2F , ®s , ®s , &sregs ) ;
  258.  
  259.       if ( buf2 [1] == 1 ) *status = 0 ;
  260.       else *status = 1 ;
  261.  
  262.       return ( error_code ( buf [3] , buf [4] ) ) ;
  263.     }  /* END cd_media */
  264. /*---*/
  265.     unsigned cd_atrack_info ( unsigned d_num , unsigned track ,
  266.                  unsigned *status , unsigned long *strt ,
  267.                  unsigned *adr )
  268.     {
  269.       union REGS regs ;
  270.       struct SREGS sregs ;
  271.       unsigned char buf [30] , buf2 [10] ;
  272.       unsigned num , start ;
  273. /* Attempt to detect CD-ROM */
  274.       regs.x.ax = 0x1500 ;  regs.x.bx = 0 ;
  275.  
  276.       int86x ( 0x2F , ®s , ®s , &sregs ) ;
  277.  
  278.       num = regs.x.bx ;  start = regs.x.cx ;
  279.  
  280.           if ( num == 0 ) return ( error_code ( 0xFF , 0x80 ) ) ;
  281. /* parameters & drive subcode */
  282.       regs.h.ah = 0x15 ;  regs.h.al = 0x10 ;
  283.       regs.x.cx = start ;
  284. /* buffer length, unit, command code */
  285.       buf [0] = 30 ;  buf [1] = d_num ;  buf [2] = 3 ;
  286. /* return parameters */
  287.       buf [3] = buf [4] = 0 ;
  288. /* reserved 8 bytes */
  289.       buf [5] = buf [6] = buf [7] = buf [8] = buf [9] = 0 ;
  290.       buf [10] = buf [11] = buf [12] = 0 ;
  291. /* number of units */
  292.       buf [13] = 0 ;
  293. /* transfer address */
  294.       *(unsigned long *)(&buf [14]) = (unsigned long)(&buf2 [0]) ;
  295. /* number of bytes to transfer */
  296.       *(unsigned long *)(&buf [18]) = 7 ;
  297. /* starting sector number */
  298.       buf [22] = buf [23] = buf [24] = buf [25] = 0 ;
  299. /* vol ID */
  300.       buf [26] = buf [27] = buf [28] = buf [29] = 0 ;
  301. /* control block code */
  302.       buf2 [0] = 11 ;  buf2 [1] = track ;
  303.       buf2 [2] = buf2 [3] = buf2 [4] = buf2 [5] = 0 ;
  304.       buf2 [6] = 0 ;
  305. /* parameter's block */
  306.       sregs.es =  FP_SEG ( buf ) ;  regs.x.bx = FP_OFF ( buf ) ;
  307.  
  308.       int86x ( 0x2F , ®s , ®s , &sregs ) ;
  309.  
  310.       *strt = *(unsigned long *)(&buf2 [2]) ;  *status = 0 ;
  311.       *adr = buf2 [6]&0x0F ;  buf2 [6] &= 0xF0 ;
  312.  
  313.       if ( buf2 [6]&16 ) *status |= 1 ;   /* 2 ch. w pre-emph. */
  314.       if ( buf2 [6]&128 ) *status |= 2 ;  /* 4 ch. w/o pre-emph. */
  315.       if ( buf2 [6]&144 ) *status |= 4 ;  /* 4 ch. w pre-emph. */
  316.       if ( buf2 [6]&64 ) *status |= 8 ;   /* data track */
  317.       if ( buf2 [6]&32 ) *status |= 16 ;  /* digital copy */
  318.  
  319.       *status = (unsigned)(buf2 [6]) ;
  320.  
  321.       return ( error_code ( buf [3] , buf [4] ) ) ;
  322.         }  /* END cd_atrack_info */
  323. /*---*/
  324.     unsigned cd_play ( unsigned d_num , unsigned long sector ,
  325.                unsigned long nm , unsigned adr )
  326.     {
  327.       union REGS regs ;
  328.       struct SREGS sregs ;
  329.       unsigned char buf [30] ;
  330.       unsigned num , start ;
  331. /* Attempt to detect CD-ROM */
  332.       regs.x.ax = 0x1500 ;  regs.x.bx = 0 ;
  333.  
  334.       int86x ( 0x2F , ®s , ®s , &sregs ) ;
  335.  
  336.       num = regs.x.bx ;  start = regs.x.cx ;
  337.  
  338.           if ( num == 0 ) return ( error_code ( 0xFF , 0x80 ) ) ;
  339. /* parameters & drive subcode */
  340.       regs.h.ah = 0x15 ;  regs.h.al = 0x10 ;
  341.       regs.x.cx = start ;
  342. /* buffer length, unit, command code */
  343.       buf [0] = 22 ;  buf [1] = d_num ;  buf [2] = 132 ;
  344. /* return parameters */
  345.       buf [3] = buf [4] = 0 ;
  346. /* reserved 8 bytes */
  347.       buf [5] = buf [6] = buf [7] = buf [8] = buf [9] = 0 ;
  348.       buf [10] = buf [11] = buf [12] = 0 ;
  349. /* addressing story, sector & number of sectors */
  350.       buf [13] = adr ;
  351. /*---*/
  352.       *(unsigned long *)(&buf [14]) = sector ;
  353.       *(unsigned long *)(&buf [18]) = nm ;
  354. /* parameter's block */
  355.       sregs.es =  FP_SEG ( buf ) ;  regs.x.bx = FP_OFF ( buf ) ;
  356.  
  357.       int86x ( 0x2F , ®s , ®s , &sregs ) ;
  358.  
  359.           return ( error_code ( buf [3] , buf [4] ) ) ;
  360.         }  /* END cd_play */
  361. /*---*/
  362.     unsigned cd_q_info ( unsigned d_num , unsigned *track ,
  363.                  unsigned *index , unsigned *pmin ,
  364.                  unsigned *psec , unsigned *pframe ,
  365.                  unsigned *amin , unsigned *asec ,
  366.                  unsigned *aframe )
  367.     {
  368.       union REGS regs ;
  369.       struct SREGS sregs ;
  370.       unsigned char buf [30] , buf2 [12] ;
  371.       unsigned num , start ;
  372. /* Attempt to detect CD-ROM */
  373.       regs.x.ax = 0x1500 ;  regs.x.bx = 0 ;
  374.  
  375.       int86x ( 0x2F , ®s , ®s , &sregs ) ;
  376.  
  377.       num = regs.x.bx ;  start = regs.x.cx ;
  378.  
  379.           if ( num == 0 ) return ( error_code ( 0xFF , 0x80 ) ) ;
  380. /* parameters & drive subcode */
  381.       regs.h.ah = 0x15 ;  regs.h.al = 0x10 ;
  382.       regs.x.cx = start ;
  383. /* buffer length, unit, command code */
  384.       buf [0] = 30 ;  buf [1] = d_num ;  buf [2] = 3 ;
  385. /* return parameters */
  386.       buf [3] = buf [4] = 0 ;
  387. /* reserved 8 bytes */
  388.       buf [5] = buf [6] = buf [7] = buf [8] = buf [9] = 0 ;
  389.       buf [10] = buf [11] = buf [12] = 0 ;
  390. /* number of units */
  391.       buf [13] = 0 ;
  392. /* transfer address */
  393.       *(unsigned long *)(&buf [14]) = (unsigned long)(&buf2 [0]) ;
  394. /* number of bytes to transfer */
  395.       *(unsigned long *)(&buf [18]) = 7 ;
  396. /* starting sector number */
  397.       buf [22] = buf [23] = buf [24] = buf [25] = 0 ;
  398. /* vol ID */
  399.       buf [26] = buf [27] = buf [28] = buf [29] = 0 ;
  400. /* control block code */
  401.       buf2 [0] = 12 ;
  402. /* control & adr byte */
  403.       buf2 [1] = 0 ;
  404. /* track number */
  405.       buf2 [2] = 0 ;
  406. /* point (index) */
  407.       buf2 [3] = 0 ;
  408. /* track running time */
  409.       buf2 [4] = buf2 [5] = buf2 [6] = 0 ;  /* min, sec, frame */
  410. /* ZERO */
  411.       buf2 [7] = 0 ;
  412. /* disc running time */
  413.       buf2 [8] = buf2 [9] = buf2 [10] = 0 ;
  414. /* parameter's block */
  415.       sregs.es =  FP_SEG ( buf ) ;  regs.x.bx = FP_OFF ( buf ) ;
  416.  
  417.       int86x ( 0x2F , ®s , ®s , &sregs ) ;
  418.  
  419.       *track = ((buf2 [2]&0xF0)>>4)* 10 + buf2 [2]&0x0F ;
  420.  
  421.       *index = buf2 [3] ;
  422.       *pmin = buf2 [4] ;  *psec = buf2 [5] ;  *pframe = buf2 [6] ;
  423.       *amin = buf2 [8] ;  *asec = buf2 [9] ;  *aframe = buf2 [10] ;
  424.  
  425.           return ( error_code ( buf [3] , buf [4] ) ) ;
  426.         }  /* END cd_q_info */
  427. /*---*/
  428.     unsigned cd_v_info ( unsigned d_num , unsigned long *size )
  429.     {
  430.       union REGS regs ;
  431.       struct SREGS sregs ;
  432.       unsigned char buf [30] , buf2 [12] ;
  433.       unsigned num , start ;
  434. /* Attempt to detect CD-ROM */
  435.       regs.x.ax = 0x1500 ;  regs.x.bx = 0 ;
  436.  
  437.       int86x ( 0x2F , ®s , ®s , &sregs ) ;
  438.  
  439.       num = regs.x.bx ;  start = regs.x.cx ;
  440.  
  441.           if ( num == 0 ) return ( error_code ( 0xFF , 0x80 ) ) ;
  442. /* parameters & drive subcode */
  443.       regs.h.ah = 0x15 ;  regs.h.al = 0x10 ;
  444.       regs.x.cx = start ;
  445. /* buffer length, unit, command code */
  446.       buf [0] = 30 ;  buf [1] = d_num ;  buf [2] = 3 ;
  447. /* return parameters */
  448.       buf [3] = buf [4] = 0 ;
  449. /* reserved 8 bytes */
  450.       buf [5] = buf [6] = buf [7] = buf [8] = buf [9] = 0 ;
  451.       buf [10] = buf [11] = buf [12] = 0 ;
  452. /* number of units */
  453.       buf [13] = 0 ;
  454. /* transfer address */
  455.       *(unsigned long *)(&buf [14]) = (unsigned long)(&buf2 [0]) ;
  456. /* number of bytes to transfer */
  457.       *(unsigned long *)(&buf [18]) = 5 ;
  458. /* starting sector number */
  459.       buf [22] = buf [23] = buf [24] = buf [25] = 0 ;
  460. /* vol ID */
  461.       buf [26] = buf [27] = buf [28] = buf [29] = 0 ;
  462. /* control block code */
  463.       buf2 [0] = 8 ;
  464. /* volume size */
  465.       buf2 [1] = buf2 [2] = buf2 [3] = buf2 [4] = 0 ;
  466. /* parameter's block */
  467.       sregs.es =  FP_SEG ( buf ) ;  regs.x.bx = FP_OFF ( buf ) ;
  468.  
  469.       int86x ( 0x2F , ®s , ®s , &sregs ) ;
  470.  
  471.       *size = *(unsigned long *)(&buf2 [1]) ;
  472.  
  473.           return ( error_code ( buf [3] , buf [4] ) ) ;
  474.     }  /* END cd_v_info */
  475. /*---*/
  476.     unsigned cd_upc_info ( unsigned d_num , char *upc )
  477.     {
  478.       union REGS regs ;
  479.       struct SREGS sregs ;
  480.       unsigned char buf [30] , buf2 [12] ;
  481.       unsigned num , start ;
  482. /* Attempt to detect CD-ROM */
  483.       regs.x.ax = 0x1500 ;  regs.x.bx = 0 ;
  484.  
  485.       int86x ( 0x2F , ®s , ®s , &sregs ) ;
  486.  
  487.       num = regs.x.bx ;  start = regs.x.cx ;
  488.  
  489.           if ( num == 0 ) return ( error_code ( 0xFF , 0x80 ) ) ;
  490. /* parameters & drive subcode */
  491.       regs.h.ah = 0x15 ;  regs.h.al = 0x10 ;
  492.       regs.x.cx = start ;
  493. /* buffer length, unit, command code */
  494.       buf [0] = 30 ;  buf [1] = d_num ;  buf [2] = 3 ;
  495. /* return parameters */
  496.       buf [3] = buf [4] = 0 ;
  497. /* reserved 8 bytes */
  498.       buf [5] = buf [6] = buf [7] = buf [8] = buf [9] = 0 ;
  499.       buf [10] = buf [11] = buf [12] = 0 ;
  500. /* number of units */
  501.       buf [13] = 0 ;
  502. /* transfer address */
  503.       *(unsigned long *)(&buf [14]) = (unsigned long)(&buf2 [0]) ;
  504. /* number of bytes to transfer */
  505.       *(unsigned long *)(&buf [18]) = 11 ;
  506. /* starting sector number */
  507.       buf [22] = buf [23] = buf [24] = buf [25] = 0 ;
  508. /* vol ID */
  509.       buf [26] = buf [27] = buf [28] = buf [29] = 0 ;
  510. /* control block code */
  511.       buf2 [0] = 14 ;
  512. /* control & adr byte */
  513.       buf2 [1] = 0 ;
  514. /* 7 bytes info */
  515.       buf2 [2] = buf2 [3] = buf2 [4] = buf2 [5] = 0 ;
  516.       buf2 [6] = buf2 [7] = buf2 [8] = 0 ;
  517. /* ZERO */
  518.       buf2 [9] = 0 ;
  519. /* Aframe */
  520.       buf2 [10] = 0 ;
  521. /* parameter's block */
  522.       sregs.es = FP_SEG ( buf ) ;  regs.x.bx = FP_OFF ( buf ) ;
  523.  
  524.       int86x ( 0x2F , ®s , ®s , &sregs ) ;
  525.  
  526.       strcpy ( upc , &buf2 [1] ) ;
  527.  
  528.           return ( error_code ( buf [3] , buf [4] ) ) ;
  529.         }  /* END cd_upc_info */
  530. /*---*/
  531.     unsigned cd_seek ( unsigned d_num , unsigned long pos ,
  532.                unsigned adr )
  533.     {
  534.       union REGS regs ;
  535.       struct SREGS sregs ;
  536.       unsigned char buf [30] ;
  537.       unsigned num , start ;
  538. /* Attempt to detect CD-ROM */
  539.       regs.x.ax = 0x1500 ;  regs.x.bx = 0 ;
  540.  
  541.       int86x ( 0x2F , ®s , ®s , &sregs ) ;
  542.  
  543.       num = regs.x.bx ;  start = regs.x.cx ;
  544.  
  545.           if ( num == 0 ) return ( error_code ( 0xFF , 0x80 ) ) ;
  546. /* parameters & drive subcode */
  547.       regs.h.ah = 0x15 ;  regs.h.al = 0x10 ;
  548.       regs.x.cx = start ;
  549. /* buffer length, unit, command code */
  550.       buf [0] = 26 ;  buf [1] = d_num ;  buf [2] = 131 ;
  551. /* return parameters */
  552.       buf [3] = buf [4] = 0 ;
  553. /* reserved 8 bytes */
  554.       buf [5] = buf [6] = buf [7] = buf [8] = buf [9] = 0 ;
  555.       buf [10] = buf [11] = buf [12] = 0 ;
  556. /* number of units */
  557.       buf [13] = adr ;
  558. /* transfer address (fake) */
  559.       buf [14] = buf [15] = buf [16] = buf [17] = 0 ;
  560. /* number of bytes to transfer (fake) */
  561.       buf [18] = buf [19] = buf [20] = buf [21] = 0 ;
  562. /* sector number to position at */
  563.       *(unsigned long *)(&buf [22]) = pos ;
  564. /* parameter's block */
  565.       sregs.es = FP_SEG ( buf ) ;  regs.x.bx = FP_OFF ( buf ) ;
  566.  
  567.       int86x ( 0x2F , ®s , ®s , &sregs ) ;
  568.  
  569.           return ( error_code ( buf [3] , buf [4] ) ) ;
  570.     }  /* END cd_seek */
  571. /*---*/
  572.     unsigned cd_read_vtoc ( unsigned drive , unsigned index ,
  573.                 unsigned char *buf )
  574.     {
  575.       union REGS regs ;
  576.       struct SREGS sregs ;
  577.  
  578.       regs.x.ax = 0x1505 ;
  579.       regs.x.dx = index ;
  580.       regs.x.cx = drive ;
  581.       sregs.es =  FP_SEG ( &buf [0] ) ;
  582.       regs.x.bx = FP_OFF ( &buf [0] ) ;
  583.  
  584.       int86x ( 0x2F , ®s , ®s , &sregs ) ;
  585.  
  586.       if ( regs.x.flags&0x0001 ) return ( 0xFF ) ;
  587.       else return ( 0 ) ;
  588.     }  /* END cd_read_vtoc */
  589. /*---*/
  590.     unsigned cd_eject ( unsigned d_num )
  591.     {
  592.       union REGS regs ;
  593.       struct SREGS sregs ;
  594.       unsigned char buf [30] , buf2 [2] ;
  595.       unsigned num , start ;
  596. /* Attempt to detect CD-ROM */
  597.       regs.x.ax = 0x1500 ;  regs.x.bx = 0 ;
  598.  
  599.       int86x ( 0x2F , ®s , ®s , &sregs ) ;
  600.  
  601.       num = regs.x.bx ;  start = regs.x.cx ;
  602.  
  603.           if ( num == 0 ) return ( error_code ( 0xFF , 0x80 ) ) ;
  604. /* parameters & drive subcode */
  605.       regs.h.ah = 0x15 ;  regs.h.al = 0x10 ;
  606.       regs.x.cx = start ;
  607. /* buffer length, unit, command code */
  608.       buf [0] = 30 ;  buf [1] = d_num ;  buf [2] = 12 ;
  609. /* return parameters */
  610.       buf [3] = buf [4] = 0 ;
  611. /* reserved 8 bytes */
  612.       buf [5] = buf [6] = buf [7] = buf [8] = buf [9] = 0 ;
  613.       buf [10] = buf [11] = buf [12] = 0 ;
  614. /* media descriptor byte */
  615.       buf [13] = 0 ;
  616. /* transfer address */
  617.       *(unsigned long *)(&buf [14]) = (unsigned long)(&buf2 [0]) ;
  618. /* number of bytes to transfer */
  619.       *(unsigned long *)(&buf [18]) = 1 ;
  620. /* starting sector number (fake) */
  621.       buf [22] = buf [23] = buf [24] = buf [25] = 0 ;
  622. /* DWord ptr ... (fake) */
  623.       buf [26] = buf [27] = buf [28] = buf [29] = 0 ;
  624. /* Command code */
  625.       buf2 [0] = 0 ;
  626. /* parameter's block */
  627.       sregs.es = FP_SEG ( buf ) ;  regs.x.bx = FP_OFF ( buf ) ;
  628.  
  629.       int86x ( 0x2F , ®s , ®s , &sregs ) ;
  630.  
  631.           return ( error_code ( buf [3] , buf [4] ) ) ;
  632.         }  /* END cd_eject */
  633. /*---*/
  634.     unsigned cd_load ( unsigned d_num )
  635.     {
  636.       union REGS regs ;
  637.       struct SREGS sregs ;
  638.       unsigned char buf [30] , buf2 [2] ;
  639.       unsigned num , start ;
  640. /* Attempt to detect CD-ROM */
  641.       regs.x.ax = 0x1500 ;  regs.x.bx = 0 ;
  642.  
  643.       int86x ( 0x2F , ®s , ®s , &sregs ) ;
  644.  
  645.       num = regs.x.bx ;  start = regs.x.cx ;
  646.  
  647.           if ( num == 0 ) return ( error_code ( 0xFF , 0x80 ) ) ;
  648. /* parameters & drive subcode */
  649.       regs.h.ah = 0x15 ;  regs.h.al = 0x10 ;
  650.       regs.x.cx = start ;
  651. /* buffer length, unit, command code */
  652.       buf [0] = 30 ;  buf [1] = d_num ;  buf [2] = 12 ;
  653. /* return parameters */
  654.       buf [3] = buf [4] = 0 ;
  655. /* reserved 8 bytes */
  656.       buf [5] = buf [6] = buf [7] = buf [8] = buf [9] = 0 ;
  657.       buf [10] = buf [11] = buf [12] = 0 ;
  658. /* media descriptor byte */
  659.       buf [13] = 0 ;
  660. /* transfer address */
  661.       *(unsigned long *)(&buf [14]) = (unsigned long)(&buf2 [0]) ;
  662. /* number of bytes to transfer */
  663.       *(unsigned long *)(&buf [18]) = 1 ;
  664. /* starting sector number (fake) */
  665.       buf [22] = buf [23] = buf [24] = buf [25] = 0 ;
  666. /* DWord ptr ... (fake) */
  667.       buf [26] = buf [27] = buf [28] = buf [29] = 0 ;
  668. /* Command code */
  669.       buf2 [0] = 5 ;
  670. /* parameter's block */
  671.       sregs.es = FP_SEG ( buf ) ;  regs.x.bx = FP_OFF ( buf ) ;
  672.  
  673.       int86x ( 0x2F , ®s , ®s , &sregs ) ;
  674.  
  675.       return ( error_code ( buf [3] , buf [4] ) ) ;
  676.         }  /* END cd_load */
  677. /*---*/
  678.     unsigned cd_init ( unsigned d_num )
  679.     {
  680.       union REGS regs ;
  681.       struct SREGS sregs ;
  682.       unsigned char buf [30] , buf2 [11] ;
  683.       unsigned num , start ;
  684. /* Attempt to detect CD-ROM */
  685.       regs.x.ax = 0x1500 ;  regs.x.bx = 0 ;
  686.  
  687.       int86x ( 0x2F , ®s , ®s , &sregs ) ;
  688.  
  689.       num = regs.x.bx ;  start = regs.x.cx ;
  690.  
  691.       if ( num == 0 ) return ( error_code ( 0xFF , 0x80 ) ) ;
  692. /* parameters & drive subcode */
  693.       regs.h.ah = 0x15 ;  regs.h.al = 0x10 ;
  694.       regs.x.cx = start ;
  695. /* buffer length, unit, command code */
  696.       buf [0] = 23 ;  buf [1] = d_num ;  buf [2] = 0 ;
  697. /* return parameters */
  698.       buf [3] = buf [4] = 0 ;
  699. /* reserved 8 bytes */
  700.       buf [5] = buf [6] = buf [7] = buf [8] = buf [9] = 0 ;
  701.       buf [10] = buf [11] = buf [12] = 0 ;
  702. /* Number of units (fake) */
  703.       buf [13] = 0 ;
  704. /* end address */
  705.       *(unsigned long *)(&buf [14]) = (unsigned long)(&buf2 [0]) ;
  706. /* ptr to BPB array */
  707.       *(unsigned long *)(&buf [18]) = (unsigned long)(&buf2 [4]) ;
  708. /* block device number (fake) */
  709.       buf [22] = 0 ;
  710. /* parameter's block */
  711.       sregs.es = FP_SEG ( buf ) ;  regs.x.bx = FP_OFF ( buf ) ;
  712.  
  713.       int86x ( 0x2F , ®s , ®s , &sregs ) ;
  714.  
  715.       return ( error_code ( buf [3] , buf [4] ) ) ;
  716.     }  /* END cd_init */
  717. /*---*/
  718.     unsigned cd_stop ( unsigned d_num )
  719.     {
  720.       union REGS regs ;
  721.       struct SREGS sregs ;
  722.       unsigned char buf [14] ;
  723.       unsigned num , start ;
  724. /* Attempt to detect CD-ROM */
  725.       regs.x.ax = 0x1500 ;  regs.x.bx = 0 ;
  726.  
  727.       int86x ( 0x2F , ®s , ®s , &sregs ) ;
  728.  
  729.       num = regs.x.bx ;  start = regs.x.cx ;
  730.  
  731.       if ( num == 0 ) return ( error_code ( 0xFF , 0x80 ) ) ;
  732. /* parameters & drive subcode */
  733.       regs.h.ah = 0x15 ;  regs.h.al = 0x10 ;
  734.       regs.x.cx = start ;
  735. /* buffer length, unit, command code */
  736.       buf [0] = 13 ;  buf [1] = d_num ;  buf [2] = 133 ;
  737. /* return parameters */
  738.       buf [3] = buf [4] = 0 ;
  739. /* reserved 8 bytes */
  740.       buf [5] = buf [6] = buf [7] = buf [8] = buf [9] = 0 ;
  741.       buf [10] = buf [11] = buf [12] = 0 ;
  742. /* parameter's block */
  743.       sregs.es = FP_SEG ( buf ) ;  regs.x.bx = FP_OFF ( buf ) ;
  744.  
  745.       int86x ( 0x2F , ®s , ®s , &sregs ) ;
  746.  
  747.       return ( error_code ( buf [3] , buf [4] ) ) ;
  748.     }  /* END cd_stop */
  749. /*---*/
  750.     unsigned cd_resume ( unsigned d_num )
  751.     {
  752.       union REGS regs ;
  753.       struct SREGS sregs ;
  754.       unsigned char buf [14] ;
  755.       unsigned num , start ;
  756. /* Attempt to detect CD-ROM */
  757.       regs.x.ax = 0x1500 ;  regs.x.bx = 0 ;
  758.  
  759.       int86x ( 0x2F , ®s , ®s , &sregs ) ;
  760.  
  761.       num = regs.x.bx ;  start = regs.x.cx ;
  762.  
  763.       if ( num == 0 ) return ( error_code ( 0xFF , 0x80 ) ) ;
  764. /* parameters & drive subcode */
  765.       regs.h.ah = 0x15 ;  regs.h.al = 0x10 ;
  766.       regs.x.cx = start ;
  767. /* buffer length, unit, command code */
  768.       buf [0] = 13 ;  buf [1] = d_num ;  buf [2] = 136 ;
  769. /* return parameters */
  770.       buf [3] = buf [4] = 0 ;
  771. /* reserved 8 bytes */
  772.       buf [5] = buf [6] = buf [7] = buf [8] = buf [9] = 0 ;
  773.       buf [10] = buf [11] = buf [12] = 0 ;
  774. /* parameter's block */
  775.       sregs.es = FP_SEG ( buf ) ;  regs.x.bx = FP_OFF ( buf ) ;
  776.  
  777.       int86x ( 0x2F , ®s , ®s , &sregs ) ;
  778.  
  779.       return ( error_code ( buf [3] , buf [4] ) ) ;
  780.     }  /* END cd_resume */
  781. /*---*/
  782.     unsigned cd_as_info ( unsigned d_num , unsigned long *str ,
  783.                   unsigned long *end  )
  784.     {
  785.       union REGS regs ;
  786.       struct SREGS sregs ;
  787.       unsigned char buf [30] , buf2 [11] ;
  788.       unsigned num , start ;
  789. /* Attempt to detect CD-ROM */
  790.       regs.x.ax = 0x1500 ;  regs.x.bx = 0 ;
  791.  
  792.       int86x ( 0x2F , ®s , ®s , &sregs ) ;
  793.  
  794.       num = regs.x.bx ;  start = regs.x.cx ;
  795.  
  796.       if ( num == 0 ) return ( error_code ( 0xFF , 0x80 ) ) ;
  797. /* parameters & drive subcode */
  798.       regs.h.ah = 0x15 ;  regs.h.al = 0x10 ;
  799.       regs.x.cx = start ;
  800. /* buffer length, unit, command code */
  801.       buf [0] = 30 ;  buf [1] = d_num ;  buf [2] = 3 ;
  802. /* return parameters */
  803.       buf [3] = buf [4] = 0 ;
  804. /* reserved 8 bytes */
  805.       buf [5] = buf [6] = buf [7] = buf [8] = buf [9] = 0 ;
  806.       buf [10] = buf [11] = buf [12] = 0 ;
  807. /* number of units */
  808.       buf [13] = 0 ;
  809. /* transfer address */
  810.       *(unsigned long *)(&buf [14]) = (unsigned long)(&buf2 [0]) ;
  811. /* number of bytes to transfer */
  812.       *(unsigned long *)(&buf [18]) = 11 ;
  813. /* starting sector number */
  814.       buf [22] = buf [23] = buf [24] = buf [25] = 0 ;
  815. /* vol ID */
  816.       buf [26] = buf [27] = buf [28] = buf [29] = 0 ;
  817. /* control block code */
  818.       buf2 [0] = 15 ;
  819. /* Status bits */
  820.       buf2 [1] = buf2 [2] = 0 ;
  821. /* Starting location */
  822.       buf2 [3] = buf2 [4] = buf2 [5] = buf2 [6] = 0 ;
  823. /* Ending location */
  824.       buf2 [7] = buf2 [8] = buf2 [9] = buf2 [10] = 0 ;
  825. /* parameter's block */
  826.       sregs.es = FP_SEG ( buf ) ;  regs.x.bx = FP_OFF ( buf ) ;
  827.  
  828.       int86x ( 0x2F , ®s , ®s , &sregs ) ;
  829.  
  830.       *str = *(unsigned long *)(&buf2 [3]) ;
  831.       *end = *(unsigned long *)(&buf2 [7]) ;
  832.  
  833.       return ( error_code ( buf [3] , buf [4] ) ) ;
  834.     }  /* END cd_as_info */
  835. /*---*/
  836.     unsigned cd_lock ( unsigned d_num )
  837.     {
  838.       union REGS regs ;
  839.       struct SREGS sregs ;
  840.       unsigned char buf [30] , buf2 [4] ;
  841.       unsigned num , start ;
  842. /* Attempt to detect CD-ROM */
  843.       regs.x.ax = 0x1500 ;  regs.x.bx = 0 ;
  844.  
  845.       int86x ( 0x2F , ®s , ®s , &sregs ) ;
  846.  
  847.       num = regs.x.bx ;  start = regs.x.cx ;
  848.  
  849.       if ( num == 0 ) return ( error_code ( 0xFF , 0x80 ) ) ;
  850. /* parameters & drive subcode */
  851.       regs.h.ah = 0x15 ;  regs.h.al = 0x10 ;
  852.       regs.x.cx = start ;
  853. /* buffer length, unit, command code */
  854.       buf [0] = 30 ;  buf [1] = d_num ;  buf [2] = 12 ;
  855. /* return parameters */
  856.       buf [3] = buf [4] = 0 ;
  857. /* reserved 8 bytes */
  858.       buf [5] = buf [6] = buf [7] = buf [8] = buf [9] = 0 ;
  859.       buf [10] = buf [11] = buf [12] = 0 ;
  860. /* media descriptor byte */
  861.       buf [13] = 0 ;
  862. /* transfer address */
  863.       *(unsigned long *)(&buf [14]) = (unsigned long)(&buf2 [0]) ;
  864. /* number of bytes to transfer */
  865.       *(unsigned long *)(&buf [18]) = 2 ;
  866. /* starting sector number (fake) */
  867.       buf [22] = buf [23] = buf [24] = buf [25] = 0 ;
  868. /* DWord ptr ... (fake) */
  869.       buf [26] = buf [27] = buf [28] = buf [29] = 0 ;
  870. /* Command code */
  871.       buf2 [0] = 1 ;
  872. /* Lock function */
  873.       buf2 [1] = 1 ;
  874. /* parameter's block */
  875.       sregs.es = FP_SEG ( buf ) ;  regs.x.bx = FP_OFF ( buf ) ;
  876.  
  877.       int86x ( 0x2F , ®s , ®s , &sregs ) ;
  878.  
  879.       return ( error_code ( buf [3] , buf [4] ) ) ;
  880.     }  /* END cd_lock */
  881. /*---*/
  882.     unsigned cd_unlock ( unsigned d_num )
  883.     {
  884.       union REGS regs ;
  885.       struct SREGS sregs ;
  886.       unsigned char buf [30] , buf2 [4] ;
  887.       unsigned num , start ;
  888. /* Attempt to detect CD-ROM */
  889.       regs.x.ax = 0x1500 ;  regs.x.bx = 0 ;
  890.  
  891.       int86x ( 0x2F , ®s , ®s , &sregs ) ;
  892.  
  893.       num = regs.x.bx ;  start = regs.x.cx ;
  894.  
  895.       if ( num == 0 ) return ( error_code ( 0xFF , 0x80 ) ) ;
  896. /* parameters & drive subcode */
  897.       regs.h.ah = 0x15 ;  regs.h.al = 0x10 ;
  898.       regs.x.cx = start ;
  899. /* buffer length, unit, command code */
  900.       buf [0] = 30 ;  buf [1] = d_num ;  buf [2] = 12 ;
  901. /* return parameters */
  902.       buf [3] = buf [4] = 0 ;
  903. /* reserved 8 bytes */
  904.       buf [5] = buf [6] = buf [7] = buf [8] = buf [9] = 0 ;
  905.       buf [10] = buf [11] = buf [12] = 0 ;
  906. /* media descriptor byte */
  907.       buf [13] = 0 ;
  908. /* transfer address */
  909.       *(unsigned long *)(&buf [14]) = (unsigned long)(&buf2 [0]) ;
  910. /* number of bytes to transfer */
  911.       *(unsigned long *)(&buf [18]) = 2 ;
  912. /* starting sector number (fake) */
  913.       buf [22] = buf [23] = buf [24] = buf [25] = 0 ;
  914. /* DWord ptr ... (fake) */
  915.       buf [26] = buf [27] = buf [28] = buf [29] = 0 ;
  916. /* Command code */
  917.       buf2 [0] = 1 ;
  918. /* Lock function */
  919.       buf2 [1] = 0 ;
  920. /* parameter's block */
  921.       sregs.es = FP_SEG ( buf ) ;  regs.x.bx = FP_OFF ( buf ) ;
  922.  
  923.       int86x ( 0x2F , ®s , ®s , &sregs ) ;
  924.  
  925.       return ( error_code ( buf [3] , buf [4] ) ) ;
  926.     }  /* END cd_unlock */
  927. /*---*/
  928.     unsigned cd_aud_info ( unsigned d_num , unsigned *ch1 ,
  929.                    unsigned *ch2 , unsigned *ch3 ,
  930.                    unsigned *ch4 )
  931.     {
  932.       union REGS regs ;
  933.       struct SREGS sregs ;
  934.       unsigned char buf [30] , buf2 [10] ;
  935.       unsigned num , start ;
  936. /* Attempt to detect CD-ROM */
  937.       regs.x.ax = 0x1500 ;  regs.x.bx = 0 ;
  938.  
  939.       int86x ( 0x2F , ®s , ®s , &sregs ) ;
  940.  
  941.       num = regs.x.bx ;  start = regs.x.cx ;
  942.  
  943.       if ( num == 0 ) return ( error_code ( 0xFF , 0x80 ) ) ;
  944. /* parameters & drive subcode */
  945.       regs.h.ah = 0x15 ;  regs.h.al = 0x10 ;
  946.       regs.x.cx = start ;
  947. /* buffer length, unit, command code */
  948.       buf [0] = 30 ;  buf [1] = d_num ;  buf [2] = 3 ;
  949. /* return parameters */
  950.       buf [3] = buf [4] = 0 ;
  951. /* reserved 8 bytes */
  952.       buf [5] = buf [6] = buf [7] = buf [8] = buf [9] = 0 ;
  953.       buf [10] = buf [11] = buf [12] = 0 ;
  954. /* reserved */
  955.       buf [13] = 0 ;
  956. /* transfer address */
  957.       *(unsigned long *)(&buf [14]) = (unsigned long)(&buf2 [0]) ;
  958. /* number of bytes to transfer */
  959.       *(unsigned long *)(&buf [18]) = 9 ;
  960. /* starting sector number */
  961.       buf [22] = buf [23] = buf [24] = buf [25] = 0 ;
  962. /* vol ID */
  963.       buf [26] = buf [27] = buf [28] = buf [29] = 0 ;
  964. /* control block code */
  965.       buf2 [0] = 4 ;
  966. /* Clear space 4 return values */
  967.       buf2 [1] = buf2 [2] = buf2 [3] = buf2 [4] = 0 ;
  968.       buf2 [5] = buf2 [6] = buf2 [7] = buf2 [8] = 0 ;
  969. /* parameter's block */
  970.       sregs.es =  FP_SEG ( buf ) ;  regs.x.bx = FP_OFF ( buf ) ;
  971.  
  972.       int86x ( 0x2F , ®s , ®s , &sregs ) ;
  973.  
  974.       *ch1 = buf2 [2] ;  *ch2 = buf2 [4] ;
  975.       *ch3 = buf2 [6] ;  *ch4 = buf2 [8] ;
  976.  
  977.       return ( error_code ( buf [3] , buf [4] ) ) ;
  978.     }  /* END cd_aud_info */
  979. /*---*/
  980.     unsigned cd_set_aud ( unsigned d_num , unsigned ch1 ,
  981.                   unsigned ch2 , unsigned ch3 ,
  982.                   unsigned ch4 )
  983.     {
  984.       union REGS regs ;
  985.       struct SREGS sregs ;
  986.       unsigned char buf [30] , buf2 [10] ;
  987.       unsigned num , start ;
  988. /* Attempt to detect CD-ROM */
  989.       regs.x.ax = 0x1500 ;  regs.x.bx = 0 ;
  990.  
  991.       int86x ( 0x2F , ®s , ®s , &sregs ) ;
  992.  
  993.       num = regs.x.bx ;  start = regs.x.cx ;
  994.  
  995.       if ( num == 0 ) return ( error_code ( 0xFF , 0x80 ) ) ;
  996. /* parameters & drive subcode */
  997.       regs.h.ah = 0x15 ;  regs.h.al = 0x10 ;
  998.       regs.x.cx = start ;
  999. /* buffer length, unit, command code */
  1000.       buf [0] = 30 ;  buf [1] = d_num ;  buf [2] = 12 ;
  1001. /* return parameters */
  1002.       buf [3] = buf [4] = 0 ;
  1003. /* reserved 8 bytes */
  1004.       buf [5] = buf [6] = buf [7] = buf [8] = buf [9] = 0 ;
  1005.       buf [10] = buf [11] = buf [12] = 0 ;
  1006. /* media descriptor byte */
  1007.       buf [13] = 0 ;
  1008. /* transfer address */
  1009.       *(unsigned long *)(&buf [14]) = (unsigned long)(&buf2 [0]) ;
  1010. /* number of bytes to transfer */
  1011.       *(unsigned long *)(&buf [18]) = 9 ;
  1012. /* starting sector number (fake) */
  1013.       buf [22] = buf [23] = buf [24] = buf [25] = 0 ;
  1014. /* DWord ptr ... (fake) */
  1015.       buf [26] = buf [27] = buf [28] = buf [29] = 0 ;
  1016. /* Command code */
  1017.       buf2 [0] = 3 ;
  1018. /* Volume control info */
  1019.       buf2 [1] = 0 ;  buf2 [2] = ch1 ;
  1020.       buf2 [3] = 1 ;  buf2 [4] = ch2 ;
  1021.       buf2 [5] = 2 ;  buf2 [6] = ch3 ;
  1022.       buf2 [7] = 3 ;  buf2 [8] = ch4 ;
  1023. /* parameter's block */
  1024.       sregs.es = FP_SEG ( buf ) ;  regs.x.bx = FP_OFF ( buf ) ;
  1025.  
  1026.       int86x ( 0x2F , ®s , ®s , &sregs ) ;
  1027.  
  1028.       return ( error_code ( buf [3] , buf [4] ) ) ;
  1029.     }  /* END cd_set_aud */
  1030. /*------------------------ Second level routines ------------------------*/
  1031.     unsigned get_t_time ( unsigned num , unsigned track ,
  1032.                   unsigned *min , unsigned *sec ,
  1033.                   unsigned *frame )
  1034.     {
  1035.       unsigned long lt , gt ;
  1036.       unsigned info , adr , first , last , r ;
  1037.  
  1038.       *min = *sec = *frame = 0 ;
  1039.  
  1040.       if ( ( r = cd_audio_info ( num , &first , &last , > ) )
  1041.            != (0|1) ) return ( r ) ;
  1042.       if ( track < first || track > last )
  1043.            return ( error_code ( 0xFE , 0x80 ) ) ;
  1044.       if ( ( r = cd_atrack_info ( num , track , &info , < ,
  1045.            &adr ) ) != (0|1) ) return ( r ) ;
  1046.  
  1047.       if ( track == last )
  1048.            dec_t_time ( bcd_sub ( lt , gt ) , min , sec , frame ) ;
  1049.       else
  1050.       {
  1051.         if ( ( r = cd_atrack_info ( num , track + 1 , &info , > ,
  1052.          &adr ) ) != (0|1) ) return ( r ) ;
  1053.  
  1054.         dec_t_time ( bcd_sub ( lt , gt ) , min , sec , frame ) ;
  1055.       }  /* ! a last track */
  1056.       return ( 0 ) ;
  1057.     }  /* END get_t_time */
  1058. /*---*/
  1059. /* 1 - Busy ;  0 - Free */
  1060.     unsigned check_if_busy ( unsigned num )
  1061.     {
  1062.        unsigned status , l ;
  1063.  
  1064.        l = cd_stat ( num , &status ) ;
  1065.        if ( l == 2 ) return ( 1 ) ;
  1066.        else return ( 0 ) ;
  1067.     }  /* END check if busy */
  1068. /*---*/
  1069. /* min, sec, frame -- real track time information */
  1070. /* rmin, rsec -- rounded information */
  1071.     void round_time ( unsigned min , unsigned sec ,
  1072.               unsigned frame , unsigned *rmin ,
  1073.               unsigned *rsec )
  1074.     {
  1075.       *rmin = min ;  *rsec = sec ;
  1076.  
  1077.       if ( frame > 37 )
  1078.       {
  1079.         if ( sec > 58 )
  1080.         {
  1081.           *rmin += 1 ;
  1082.           *rsec = 0 ;
  1083.         }  /* 59 minutes */
  1084.         else *rsec += 1 ;
  1085.       }  /* rounding required */
  1086.     }  /* END round_time */
  1087. /*---*/
  1088. /* num -- CD-ROM number, track -- track number */
  1089. /* str -- starting track time (0 -- beginning) */
  1090. /* sec -- time to play (0 -- entire track) */
  1091.     unsigned play_track ( unsigned num , unsigned track ,
  1092.                   unsigned str , unsigned sec )
  1093.     {
  1094.       unsigned long lt , gt , t , t2 , t3 ;
  1095.       unsigned info , adr , first , last , r ;
  1096.  
  1097.       if ( ( r = cd_audio_info ( num , &first , &last , > ) )
  1098.            != (0|1) ) return ( r ) ;
  1099.  
  1100.       if ( track < first || track > last )
  1101.            return ( error_code ( 0xFE , 0x80 ) ) ;
  1102.       if ( ( r = cd_atrack_info ( num , track , &info , < ,
  1103.            &adr ) ) != (0|1) ) return ( r ) ;
  1104.  
  1105.       if ( track != last )
  1106.       {
  1107.         if ( ( r = cd_atrack_info ( num , track + 1 , &info , > ,
  1108.          &adr ) ) != (0|1) ) return ( r ) ;
  1109.       }
  1110.  
  1111.       t = bcd_sub ( lt , gt ) ;
  1112. /*S*/
  1113.       if ( str != 0 )
  1114.       {
  1115.         t3 = dec2bcd ( str * V1 ) ;
  1116.         t2 = dec2bcd ( bcd_add ( lt , t3 ) ) ;
  1117.  
  1118.         if ( t2 < gt ) t = bcd_sub ( lt = t2 , gt ) ;
  1119.         else return ( error_code ( 0xFD , 0x80 ) ) ;
  1120.       }  /* Start from the specified position */
  1121. /*L*/
  1122.       if ( sec != 0 )
  1123.       {
  1124.         t3 = (unsigned long)sec ;
  1125.         t2 = ( t3 / 60L ) * V2 + ( t3 % 60L ) * V1 ;
  1126.  
  1127.         if ( t > t2 ) t = t2 ;
  1128.         else return ( error_code ( 0xFD , 0x80 ) ) ;
  1129.       }   /* Play the specified time */
  1130.  
  1131.       r = cd_play ( num , lt , t , adr ) ;
  1132.       return ( r ) ;
  1133.     }  /* END play track */
  1134. /*-----------------------------------------------------------------------*/
  1135.     main ()
  1136.     {
  1137.       unsigned info , i , k , l , m , adr , res ;
  1138.       unsigned pmin, psec , pframe , amin , asec , aframe ,
  1139.            index , track , min , sec , frame , min2 , sec2 ,
  1140.            ch1 , ch2 , ch3 , ch4 ;
  1141.       unsigned long l_out , g_out , songs [100] , tmp , tmp2 ;
  1142.       clock_t start , end ;
  1143.  
  1144.       clrscr () ;
  1145.  
  1146.       cd_stop ( 0 ) ;
  1147.       while ( check_if_busy ( 0 ) ) ;
  1148.  
  1149. //      cd_aud_info ( 0 , &ch1 , &ch2 , &ch3 , &ch4 ) ;
  1150.  
  1151.       if ( !cd_stat ( 0 , &info ) )
  1152.       {
  1153.         printf ( "\n  I/O Error \n" ) ;
  1154.         exit ( 1 ) ;
  1155.       }
  1156.  
  1157.       start = clock () ;
  1158.       l = play_track ( 0 , 17 , 90 , 0 ) ;
  1159.  
  1160.       do
  1161.       {
  1162.         for ( i = 0x0 ;  i <= 0x00FF ;  i += 15 )
  1163.         {
  1164.           cd_set_aud ( 0 , i , 0x00FF - i , 0 , 0 ) ;
  1165.           delay ( 600L ) ;
  1166.         }  /* Check ... */
  1167.       } while ( check_if_busy ( 0 ) ) ;
  1168.  
  1169.       do
  1170.       {
  1171.         l = check_if_busy ( 0 ) ;
  1172.       } while ( l ) ;
  1173.  
  1174.       end = clock () ;
  1175.       start *= 10 ;  start /= 182 ;
  1176.       end *= 10 ;  end /= 182 ;  end -= start ;
  1177.       start /= 3600 ;  end %= 3600 ;
  1178.  
  1179.       cd_q_info ( 0 , &track , &index , &pmin , &psec ,
  1180.               &pframe , &amin , &asec , &aframe ) ;
  1181.  
  1182.       round_time ( pmin , psec , pframe , &min2 , &sec2 ) ;
  1183.  
  1184.       printf ( "\n  Elapsed time: %ldm%lds\n" , end / 60 ,
  1185.            end % 60 ) ;
  1186.       printf ( "\n  Offset from a beginning of the song: %um%us" ,
  1187.            min2 , sec2 ) ;
  1188.  
  1189.       cd_stop ( 0 ) ;
  1190.  
  1191.       printf ( "\n\n  Completed. Bye from TOKsoft\n" ) ;  exit ( 0 ) ;
  1192.     }  /* END main */
  1193.