#include <conio.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <dos.h>
#include <time.h>

#define V1    75L
#define V2    4500L
#define V3    270000L
/*--- bcd2 - bcd1 ---*/
	unsigned long bcd_sub ( unsigned long bcd1 ,
				unsigned long bcd2 )
	{
	  unsigned long t11 = 0 , t12 = 0 , t1r = 0 , t2r = 0 ;

	  t11 = bcd1&0x000000FF ;  t12 = bcd2&0x000000FF ;
	  t1r += t11 ;  t2r += t12 ;

	  t11 = (bcd1>>8)&0x000000FF ;  t12 = (bcd2>>8)&0x000000FF ;
	  t1r += ( t11 * V1 ) ;  t2r += ( t12 * V1 ) ;

	  t11 = (bcd1>>16)&0x000000FF ;  t12 = (bcd2>>16)&0x000000FF ;
	  t1r += ( t11 * V2 ) ;  t2r += ( t12 * V2 ) ;

	  t11 = (bcd1>>24)&0x000000FF ;  t12 = (bcd2>>24)&0x000000FF ;
	  t1r += ( t11 * V3 ) ;  t2r += ( t12 * V3 ) ;

	  return ( t2r - t1r ) ;
	}  /* END bcd_sub */
/*---*/
/*--- bcd1 + bcd2 ---*/
	unsigned long bcd_add ( unsigned long bcd1 ,
				unsigned long bcd2 )
	{
	  unsigned long t11 = 0 , t12 = 0 , t1r = 0 , t2r = 0 ;

	  t11 = bcd1&0x000000FF ;  t12 = bcd2&0x000000FF ;
	  t1r += t11 ;  t2r += t12 ;

	  t11 = (bcd1>>8)&0x000000FF ;  t12 = (bcd2>>8)&0x000000FF ;
	  t1r += ( t11 * V1 ) ;  t2r += ( t12 * V1 ) ;

	  t11 = (bcd1>>16)&0x000000FF ;  t12 = (bcd2>>16)&0x000000FF ;
	  t1r += ( t11 * V2 ) ;  t2r += ( t12 * V2 ) ;

	  t11 = (bcd1>>24)&0x000000FF ;  t12 = (bcd2>>24)&0x000000FF ;
	  t1r += ( t11 * V3 ) ;  t2r += ( t12 * V3 ) ;

	  return ( t2r + t1r ) ;
	}  /* END bcd_add */
/*---*/
	unsigned long dec2bcd ( unsigned long val )
	{
	  unsigned long t1 , t2 = 0 , t3 = val ;

	  t1 = t3 / V2 ;  t2 += ( t1 * 65536L ) ;  t3 = t3 % V2 ;
	  t1 = t3 / V1 ;  t2 += ( t1 * 256L ) ;   t3 = t3 % V1 ;
	  t2 += ( t1 % V1 ) ;

	  return ( t2 ) ;
	}  /* END dec2bcd */
/*---*/
	void dec_t_time ( unsigned long bcd , unsigned *min ,
			  unsigned *sec , unsigned *frame )
	{
	  unsigned long t1 ;

	  t1 = *min = bcd / V2 ;
	  t1 = bcd % V2 ;
	  *sec = t1 / V1 ;
	  *frame = t1 % V1 ;
	}  /* END dec_t_time */
/*---*/
	unsigned error_code ( unsigned char b1 , unsigned char b2 )
	{
	  if ( b2&0x80 )
	  {
	   if ( b1 == 0 ) return ( 3 ) ;        /* Write protect violation */
	   else if ( b1 == 1 ) return ( 4 ) ;   /* Unknown unit */
	   else if ( b1 == 2 ) return ( 5 ) ;   /* Drive not ready */
	   else if ( b1 == 3 ) return ( 6 ) ;   /* Unknown command */
	   else if ( b1 == 4 ) return ( 7 ) ;   /* CRC error */
	   else if ( b1 == 5 ) return ( 8 ) ;   /* Bad header length */
	   else if ( b1 == 6 ) return ( 9 ) ;   /* Seek error */
	   else if ( b1 == 7 ) return ( 10 ) ;  /* Unknown media */
	   else if ( b1 == 8 ) return ( 11 ) ;  /* Sector not found */
	   else if ( b1 == 9 ) return ( 12 ) ;  /* Printer out of paper */
	   else if ( b1 == 10 ) return ( 13 ) ; /* Write fault */
	   else if ( b1 == 11 ) return ( 14 ) ; /* Read fault */
	   else if ( b1 == 12 ) return ( 15 ) ; /* General failure */
	   else if ( b1 == 15 ) return ( 16 ) ; /* Invalid disk change */
	   else if ( b1 == 0xFE ) return ( 17 ) ; /* Invalid track */
	   else if ( b1 == 0xFD ) return ( 18 ) ; /* EOT reached */
	   else if ( b1 == 0xFF ) return ( 19 ) ; /* CD-ROM letter !found */
	   else return ( 0xFF ) ;                 /* Unknown error */
	  }  /* Error detected */
	  else
	  {
	    if ( b2&2 ) return ( 2 ) ;             /* Busy */
	    else if ( b2&1 ) return ( 1 ) ;        /* Done */
	    else return ( 0 ) ;                    /* OK */
	  }  /* No errors */
	}  /* END error_code */
/*---*/
	unsigned cd_stat ( unsigned d_num , unsigned *status )
	{
	  union REGS regs ;
	  struct SREGS sregs ;
	  unsigned char buf [30] , buf2 [10] ;
	  unsigned num , start ;
	  unsigned long tmp ;
/* Attempt to detect CD-ROM */
	  regs.x.ax = 0x1500 ;  regs.x.bx = 0 ;

	  int86x ( 0x2F , &regs , &regs , &sregs ) ;

	  num = regs.x.bx ;  start = regs.x.cx ;

	  if ( num == 0 ) return ( error_code ( 0xFF , 0x80 ) ) ;
/* parameters & drive subcode */
	  regs.h.ah = 0x15 ;  regs.h.al = 0x10 ;
	  regs.x.cx = start ;
/* buffer length, unit, command code */
	  buf [0] = 30 ;  buf [1] = d_num ;  buf [2] = 3 ;
/* return parameters */
	  buf [3] = buf [4] = 0 ;
/* reserved 8 bytes */
	  buf [5] = buf [6] = buf [7] = buf [8] = buf [9] = 0 ;
	  buf [10] = buf [11] = buf [12] = 0 ;
/* reserved */
	  buf [13] = 0 ;
/* transfer address */
	  *(unsigned long *)(&buf [14]) = (unsigned long)(&buf2 [0]) ;
/* number of bytes to transfer */
	  *(unsigned long *)(&buf [18]) = 5 ;
/* starting sector number */
	  buf [22] = buf [23] = buf [24] = buf [25] = 0 ;
/* vol ID */
	  buf [26] = buf [27] = buf [28] = buf [29] = 0 ;
/* control block code */
	  buf2 [0] = 6 ;
/* parameter's block */
	  sregs.es =  FP_SEG ( buf ) ;  regs.x.bx = FP_OFF ( buf ) ;

	  int86x ( 0x2F , &regs , &regs , &sregs ) ;

	  tmp = *(unsigned long *)(&buf2 [1]) ;

	  *status = 0 ;

          if ( tmp&1 ) *status |= 1 ;        /* Tray is open */
          if ( tmp&2 ) *status |= 2 ;        /* Door unlocked */
	  if ( tmp&4 ) *status |= 4 ;        /* Supports 2 read modes */
	  if ( tmp&8 ) *status |= 8 ;        /* Read/Write features */
          if ( tmp&16 ) *status |= 16 ;      /* Data & Audio */
          if ( tmp&32 ) *status |= 32 ;      /* Interleaving */
          if ( tmp&128 ) *status |= 64 ;     /* Prefetching requests */
          if ( tmp&256 ) *status |= 128 ;    /* Audio channel tricks */
          if ( tmp&512 ) *status |= 256 ;    /* HSG & Red Book */
	  if ( tmp&2048 ) *status |= 512 ;   /* No disk in drive */
          if ( tmp&4096 ) *status |= 1024 ;  /* R-W subchannels support */

          return ( error_code ( buf [3] , buf [4] ) ) ;
	}  /* END cd_stat */
/*---*/
	unsigned cd_audio_info ( unsigned d_num , unsigned *low ,
				 unsigned *high , unsigned long *l_out )
	{
	  union REGS regs ;
	  struct SREGS sregs ;
	  unsigned char buf [30] , buf2 [10] ;
	  unsigned num , start ;
/* Attempt to detect CD-ROM */
	  regs.x.ax = 0x1500 ;  regs.x.bx = 0 ;

	  int86x ( 0x2F , &regs , &regs , &sregs ) ;

	  num = regs.x.bx ;  start = regs.x.cx ;

	  if ( num == 0 ) return ( error_code ( 0xFF , 0x80 ) ) ;
/* parameters & drive subcode */
	  regs.h.ah = 0x15 ;  regs.h.al = 0x10 ;
	  regs.x.cx = start ;
/* buffer length, unit, command code */
	  buf [0] = 30 ;  buf [1] = d_num ;  buf [2] = 3 ;
/* return parameters */
	  buf [3] = buf [4] = 0 ;
/* reserved 8 bytes */
	  buf [5] = buf [6] = buf [7] = buf [8] = buf [9] = 0 ;
	  buf [10] = buf [11] = buf [12] = 0 ;
/* number of units */
	  buf [13] = 0 ;
/* transfer address */
	  *(unsigned long *)(&buf [14]) = (unsigned long)(&buf2 [0]) ;
/* number of bytes to transfer */
	  *(unsigned long *)(&buf [18]) = 7 ;
/* starting sector number */
	  buf [22] = buf [23] = buf [24] = buf [25] = 0 ;
/* vol ID */
	  buf [26] = buf [27] = buf [28] = buf [29] = 0 ;
/* control block code */
	  buf2 [0] = 10 ;
	  buf2 [1] = buf2 [2] = buf2 [3] = 0 ;
	  buf2 [4] = buf2 [5] = buf2 [6] = 0 ;
/* parameter's block */
	  sregs.es =  FP_SEG ( buf ) ;  regs.x.bx = FP_OFF ( buf ) ;

	  int86x ( 0x2F , &regs , &regs , &sregs ) ;

	  *low = (unsigned )(buf2 [1]) ;
	  *high = (unsigned)(buf2 [2]) ;
	  *l_out = *(unsigned long *)(&buf2 [3]) ;

	  return ( error_code ( buf [3] , buf [4] ) ) ;
	}  /* END cd_audio_info */
/*---*/
	unsigned cd_media ( unsigned d_num , unsigned *status )
	{
	  union REGS regs ;
	  struct SREGS sregs ;
	  unsigned char buf [30] , buf2 [10] ;
	  unsigned num , start ;
/* Attempt to detect CD-ROM */
	  regs.x.ax = 0x1500 ;  regs.x.bx = 0 ;

	  int86x ( 0x2F , &regs , &regs , &sregs ) ;

	  num = regs.x.bx ;  start = regs.x.cx ;

          if ( num == 0 ) return ( error_code ( 0xFF , 0x80 ) ) ;
/* parameters & drive subcode */
	  regs.h.ah = 0x15 ;  regs.h.al = 0x10 ;
	  regs.x.cx = start ;
/* buffer length, unit, command code */
	  buf [0] = 30 ;  buf [1] = d_num ;  buf [2] = 3 ;
/* return parameters */
	  buf [3] = buf [4] = 0 ;
/* reserved 8 bytes */
	  buf [5] = buf [6] = buf [7] = buf [8] = buf [9] = 0 ;
	  buf [10] = buf [11] = buf [12] = 0 ;
/* number of units */
	  buf [13] = 0 ;
/* transfer address */
	  *(unsigned long *)(&buf [14]) = (unsigned long)(&buf2 [0]) ;
/* number of bytes to transfer */
	  *(unsigned long *)(&buf [18]) = 2 ;
/* starting sector number */
	  buf [22] = buf [23] = buf [24] = buf [25] = 0 ;
/* vol ID */
	  buf [26] = buf [27] = buf [28] = buf [29] = 0 ;
/* control block code */
	  buf2 [0] = 9 ;  buf2 [1] = 0 ;
/* parameter's block */
	  sregs.es =  FP_SEG ( buf ) ;  regs.x.bx = FP_OFF ( buf ) ;

	  int86x ( 0x2F , &regs , &regs , &sregs ) ;

	  if ( buf2 [1] == 1 ) *status = 0 ;
	  else *status = 1 ;

	  return ( error_code ( buf [3] , buf [4] ) ) ;
	}  /* END cd_media */
/*---*/
	unsigned cd_atrack_info ( unsigned d_num , unsigned track ,
				 unsigned *status , unsigned long *strt ,
				 unsigned *adr )
	{
	  union REGS regs ;
	  struct SREGS sregs ;
	  unsigned char buf [30] , buf2 [10] ;
	  unsigned num , start ;
/* Attempt to detect CD-ROM */
	  regs.x.ax = 0x1500 ;  regs.x.bx = 0 ;

	  int86x ( 0x2F , &regs , &regs , &sregs ) ;

	  num = regs.x.bx ;  start = regs.x.cx ;

          if ( num == 0 ) return ( error_code ( 0xFF , 0x80 ) ) ;
/* parameters & drive subcode */
	  regs.h.ah = 0x15 ;  regs.h.al = 0x10 ;
	  regs.x.cx = start ;
/* buffer length, unit, command code */
	  buf [0] = 30 ;  buf [1] = d_num ;  buf [2] = 3 ;
/* return parameters */
	  buf [3] = buf [4] = 0 ;
/* reserved 8 bytes */
	  buf [5] = buf [6] = buf [7] = buf [8] = buf [9] = 0 ;
	  buf [10] = buf [11] = buf [12] = 0 ;
/* number of units */
	  buf [13] = 0 ;
/* transfer address */
	  *(unsigned long *)(&buf [14]) = (unsigned long)(&buf2 [0]) ;
/* number of bytes to transfer */
	  *(unsigned long *)(&buf [18]) = 7 ;
/* starting sector number */
	  buf [22] = buf [23] = buf [24] = buf [25] = 0 ;
/* vol ID */
	  buf [26] = buf [27] = buf [28] = buf [29] = 0 ;
/* control block code */
	  buf2 [0] = 11 ;  buf2 [1] = track ;
	  buf2 [2] = buf2 [3] = buf2 [4] = buf2 [5] = 0 ;
	  buf2 [6] = 0 ;
/* parameter's block */
	  sregs.es =  FP_SEG ( buf ) ;  regs.x.bx = FP_OFF ( buf ) ;

	  int86x ( 0x2F , &regs , &regs , &sregs ) ;

	  *strt = *(unsigned long *)(&buf2 [2]) ;  *status = 0 ;
	  *adr = buf2 [6]&0x0F ;  buf2 [6] &= 0xF0 ;

	  if ( buf2 [6]&16 ) *status |= 1 ;   /* 2 ch. w pre-emph. */
	  if ( buf2 [6]&128 ) *status |= 2 ;  /* 4 ch. w/o pre-emph. */
	  if ( buf2 [6]&144 ) *status |= 4 ;  /* 4 ch. w pre-emph. */
	  if ( buf2 [6]&64 ) *status |= 8 ;   /* data track */
	  if ( buf2 [6]&32 ) *status |= 16 ;  /* digital copy */

	  *status = (unsigned)(buf2 [6]) ;

	  return ( error_code ( buf [3] , buf [4] ) ) ;
        }  /* END cd_atrack_info */
/*---*/
	unsigned cd_play ( unsigned d_num , unsigned long sector ,
			   unsigned long nm , unsigned adr )
	{
	  union REGS regs ;
	  struct SREGS sregs ;
	  unsigned char buf [30] ;
	  unsigned num , start ;
/* Attempt to detect CD-ROM */
	  regs.x.ax = 0x1500 ;  regs.x.bx = 0 ;

	  int86x ( 0x2F , &regs , &regs , &sregs ) ;

	  num = regs.x.bx ;  start = regs.x.cx ;

          if ( num == 0 ) return ( error_code ( 0xFF , 0x80 ) ) ;
/* parameters & drive subcode */
	  regs.h.ah = 0x15 ;  regs.h.al = 0x10 ;
	  regs.x.cx = start ;
/* buffer length, unit, command code */
	  buf [0] = 22 ;  buf [1] = d_num ;  buf [2] = 132 ;
/* return parameters */
	  buf [3] = buf [4] = 0 ;
/* reserved 8 bytes */
	  buf [5] = buf [6] = buf [7] = buf [8] = buf [9] = 0 ;
	  buf [10] = buf [11] = buf [12] = 0 ;
/* addressing story, sector & number of sectors */
	  buf [13] = adr ;
/*---*/
	  *(unsigned long *)(&buf [14]) = sector ;
	  *(unsigned long *)(&buf [18]) = nm ;
/* parameter's block */
	  sregs.es =  FP_SEG ( buf ) ;  regs.x.bx = FP_OFF ( buf ) ;

	  int86x ( 0x2F , &regs , &regs , &sregs ) ;

          return ( error_code ( buf [3] , buf [4] ) ) ;
        }  /* END cd_play */
/*---*/
	unsigned cd_q_info ( unsigned d_num , unsigned *track ,
				 unsigned *index , unsigned *pmin ,
				 unsigned *psec , unsigned *pframe ,
				 unsigned *amin , unsigned *asec ,
				 unsigned *aframe )
	{
	  union REGS regs ;
	  struct SREGS sregs ;
	  unsigned char buf [30] , buf2 [12] ;
	  unsigned num , start ;
/* Attempt to detect CD-ROM */
	  regs.x.ax = 0x1500 ;  regs.x.bx = 0 ;

	  int86x ( 0x2F , &regs , &regs , &sregs ) ;

	  num = regs.x.bx ;  start = regs.x.cx ;

          if ( num == 0 ) return ( error_code ( 0xFF , 0x80 ) ) ;
/* parameters & drive subcode */
	  regs.h.ah = 0x15 ;  regs.h.al = 0x10 ;
	  regs.x.cx = start ;
/* buffer length, unit, command code */
	  buf [0] = 30 ;  buf [1] = d_num ;  buf [2] = 3 ;
/* return parameters */
	  buf [3] = buf [4] = 0 ;
/* reserved 8 bytes */
	  buf [5] = buf [6] = buf [7] = buf [8] = buf [9] = 0 ;
	  buf [10] = buf [11] = buf [12] = 0 ;
/* number of units */
	  buf [13] = 0 ;
/* transfer address */
	  *(unsigned long *)(&buf [14]) = (unsigned long)(&buf2 [0]) ;
/* number of bytes to transfer */
	  *(unsigned long *)(&buf [18]) = 7 ;
/* starting sector number */
	  buf [22] = buf [23] = buf [24] = buf [25] = 0 ;
/* vol ID */
	  buf [26] = buf [27] = buf [28] = buf [29] = 0 ;
/* control block code */
	  buf2 [0] = 12 ;
/* control & adr byte */
	  buf2 [1] = 0 ;
/* track number */
	  buf2 [2] = 0 ;
/* point (index) */
	  buf2 [3] = 0 ;
/* track running time */
	  buf2 [4] = buf2 [5] = buf2 [6] = 0 ;  /* min, sec, frame */
/* ZERO */
	  buf2 [7] = 0 ;
/* disc running time */
	  buf2 [8] = buf2 [9] = buf2 [10] = 0 ;
/* parameter's block */
	  sregs.es =  FP_SEG ( buf ) ;  regs.x.bx = FP_OFF ( buf ) ;

	  int86x ( 0x2F , &regs , &regs , &sregs ) ;

	  *track = ((buf2 [2]&0xF0)>>4)* 10 + buf2 [2]&0x0F ;

	  *index = buf2 [3] ;
	  *pmin = buf2 [4] ;  *psec = buf2 [5] ;  *pframe = buf2 [6] ;
	  *amin = buf2 [8] ;  *asec = buf2 [9] ;  *aframe = buf2 [10] ;

          return ( error_code ( buf [3] , buf [4] ) ) ;
        }  /* END cd_q_info */
/*---*/
	unsigned cd_v_info ( unsigned d_num , unsigned long *size )
	{
	  union REGS regs ;
	  struct SREGS sregs ;
	  unsigned char buf [30] , buf2 [12] ;
	  unsigned num , start ;
/* Attempt to detect CD-ROM */
	  regs.x.ax = 0x1500 ;  regs.x.bx = 0 ;

	  int86x ( 0x2F , &regs , &regs , &sregs ) ;

	  num = regs.x.bx ;  start = regs.x.cx ;

          if ( num == 0 ) return ( error_code ( 0xFF , 0x80 ) ) ;
/* parameters & drive subcode */
	  regs.h.ah = 0x15 ;  regs.h.al = 0x10 ;
	  regs.x.cx = start ;
/* buffer length, unit, command code */
	  buf [0] = 30 ;  buf [1] = d_num ;  buf [2] = 3 ;
/* return parameters */
	  buf [3] = buf [4] = 0 ;
/* reserved 8 bytes */
	  buf [5] = buf [6] = buf [7] = buf [8] = buf [9] = 0 ;
	  buf [10] = buf [11] = buf [12] = 0 ;
/* number of units */
	  buf [13] = 0 ;
/* transfer address */
	  *(unsigned long *)(&buf [14]) = (unsigned long)(&buf2 [0]) ;
/* number of bytes to transfer */
	  *(unsigned long *)(&buf [18]) = 5 ;
/* starting sector number */
	  buf [22] = buf [23] = buf [24] = buf [25] = 0 ;
/* vol ID */
	  buf [26] = buf [27] = buf [28] = buf [29] = 0 ;
/* control block code */
	  buf2 [0] = 8 ;
/* volume size */
	  buf2 [1] = buf2 [2] = buf2 [3] = buf2 [4] = 0 ;
/* parameter's block */
	  sregs.es =  FP_SEG ( buf ) ;  regs.x.bx = FP_OFF ( buf ) ;

	  int86x ( 0x2F , &regs , &regs , &sregs ) ;

	  *size = *(unsigned long *)(&buf2 [1]) ;

          return ( error_code ( buf [3] , buf [4] ) ) ;
	}  /* END cd_v_info */
/*---*/
	unsigned cd_upc_info ( unsigned d_num , char *upc )
	{
	  union REGS regs ;
	  struct SREGS sregs ;
	  unsigned char buf [30] , buf2 [12] ;
	  unsigned num , start ;
/* Attempt to detect CD-ROM */
	  regs.x.ax = 0x1500 ;  regs.x.bx = 0 ;

	  int86x ( 0x2F , &regs , &regs , &sregs ) ;

	  num = regs.x.bx ;  start = regs.x.cx ;

          if ( num == 0 ) return ( error_code ( 0xFF , 0x80 ) ) ;
/* parameters & drive subcode */
	  regs.h.ah = 0x15 ;  regs.h.al = 0x10 ;
	  regs.x.cx = start ;
/* buffer length, unit, command code */
	  buf [0] = 30 ;  buf [1] = d_num ;  buf [2] = 3 ;
/* return parameters */
	  buf [3] = buf [4] = 0 ;
/* reserved 8 bytes */
	  buf [5] = buf [6] = buf [7] = buf [8] = buf [9] = 0 ;
	  buf [10] = buf [11] = buf [12] = 0 ;
/* number of units */
	  buf [13] = 0 ;
/* transfer address */
	  *(unsigned long *)(&buf [14]) = (unsigned long)(&buf2 [0]) ;
/* number of bytes to transfer */
	  *(unsigned long *)(&buf [18]) = 11 ;
/* starting sector number */
	  buf [22] = buf [23] = buf [24] = buf [25] = 0 ;
/* vol ID */
	  buf [26] = buf [27] = buf [28] = buf [29] = 0 ;
/* control block code */
	  buf2 [0] = 14 ;
/* control & adr byte */
	  buf2 [1] = 0 ;
/* 7 bytes info */
	  buf2 [2] = buf2 [3] = buf2 [4] = buf2 [5] = 0 ;
	  buf2 [6] = buf2 [7] = buf2 [8] = 0 ;
/* ZERO */
	  buf2 [9] = 0 ;
/* Aframe */
	  buf2 [10] = 0 ;
/* parameter's block */
	  sregs.es = FP_SEG ( buf ) ;  regs.x.bx = FP_OFF ( buf ) ;

	  int86x ( 0x2F , &regs , &regs , &sregs ) ;

	  strcpy ( upc , &buf2 [1] ) ;

          return ( error_code ( buf [3] , buf [4] ) ) ;
        }  /* END cd_upc_info */
/*---*/
	unsigned cd_seek ( unsigned d_num , unsigned long pos ,
			   unsigned adr )
	{
	  union REGS regs ;
	  struct SREGS sregs ;
	  unsigned char buf [30] ;
	  unsigned num , start ;
/* Attempt to detect CD-ROM */
	  regs.x.ax = 0x1500 ;  regs.x.bx = 0 ;

	  int86x ( 0x2F , &regs , &regs , &sregs ) ;

	  num = regs.x.bx ;  start = regs.x.cx ;

          if ( num == 0 ) return ( error_code ( 0xFF , 0x80 ) ) ;
/* parameters & drive subcode */
	  regs.h.ah = 0x15 ;  regs.h.al = 0x10 ;
	  regs.x.cx = start ;
/* buffer length, unit, command code */
	  buf [0] = 26 ;  buf [1] = d_num ;  buf [2] = 131 ;
/* return parameters */
	  buf [3] = buf [4] = 0 ;
/* reserved 8 bytes */
	  buf [5] = buf [6] = buf [7] = buf [8] = buf [9] = 0 ;
	  buf [10] = buf [11] = buf [12] = 0 ;
/* number of units */
	  buf [13] = adr ;
/* transfer address (fake) */
	  buf [14] = buf [15] = buf [16] = buf [17] = 0 ;
/* number of bytes to transfer (fake) */
	  buf [18] = buf [19] = buf [20] = buf [21] = 0 ;
/* sector number to position at */
	  *(unsigned long *)(&buf [22]) = pos ;
/* parameter's block */
	  sregs.es = FP_SEG ( buf ) ;  regs.x.bx = FP_OFF ( buf ) ;

	  int86x ( 0x2F , &regs , &regs , &sregs ) ;

          return ( error_code ( buf [3] , buf [4] ) ) ;
	}  /* END cd_seek */
/*---*/
	unsigned cd_read_vtoc ( unsigned drive , unsigned index ,
				unsigned char *buf )
	{
	  union REGS regs ;
	  struct SREGS sregs ;

	  regs.x.ax = 0x1505 ;
	  regs.x.dx = index ;
	  regs.x.cx = drive ;
	  sregs.es =  FP_SEG ( &buf [0] ) ;
	  regs.x.bx = FP_OFF ( &buf [0] ) ;

	  int86x ( 0x2F , &regs , &regs , &sregs ) ;

	  if ( regs.x.flags&0x0001 ) return ( 0xFF ) ;
	  else return ( 0 ) ;
	}  /* END cd_read_vtoc */
/*---*/
	unsigned cd_eject ( unsigned d_num )
	{
	  union REGS regs ;
	  struct SREGS sregs ;
	  unsigned char buf [30] , buf2 [2] ;
	  unsigned num , start ;
/* Attempt to detect CD-ROM */
	  regs.x.ax = 0x1500 ;  regs.x.bx = 0 ;

	  int86x ( 0x2F , &regs , &regs , &sregs ) ;

	  num = regs.x.bx ;  start = regs.x.cx ;

          if ( num == 0 ) return ( error_code ( 0xFF , 0x80 ) ) ;
/* parameters & drive subcode */
	  regs.h.ah = 0x15 ;  regs.h.al = 0x10 ;
	  regs.x.cx = start ;
/* buffer length, unit, command code */
	  buf [0] = 30 ;  buf [1] = d_num ;  buf [2] = 12 ;
/* return parameters */
	  buf [3] = buf [4] = 0 ;
/* reserved 8 bytes */
	  buf [5] = buf [6] = buf [7] = buf [8] = buf [9] = 0 ;
	  buf [10] = buf [11] = buf [12] = 0 ;
/* media descriptor byte */
	  buf [13] = 0 ;
/* transfer address */
	  *(unsigned long *)(&buf [14]) = (unsigned long)(&buf2 [0]) ;
/* number of bytes to transfer */
	  *(unsigned long *)(&buf [18]) = 1 ;
/* starting sector number (fake) */
	  buf [22] = buf [23] = buf [24] = buf [25] = 0 ;
/* DWord ptr ... (fake) */
	  buf [26] = buf [27] = buf [28] = buf [29] = 0 ;
/* Command code */
	  buf2 [0] = 0 ;
/* parameter's block */
	  sregs.es = FP_SEG ( buf ) ;  regs.x.bx = FP_OFF ( buf ) ;

	  int86x ( 0x2F , &regs , &regs , &sregs ) ;

          return ( error_code ( buf [3] , buf [4] ) ) ;
        }  /* END cd_eject */
/*---*/
	unsigned cd_load ( unsigned d_num )
	{
	  union REGS regs ;
	  struct SREGS sregs ;
	  unsigned char buf [30] , buf2 [2] ;
	  unsigned num , start ;
/* Attempt to detect CD-ROM */
	  regs.x.ax = 0x1500 ;  regs.x.bx = 0 ;

	  int86x ( 0x2F , &regs , &regs , &sregs ) ;

	  num = regs.x.bx ;  start = regs.x.cx ;

          if ( num == 0 ) return ( error_code ( 0xFF , 0x80 ) ) ;
/* parameters & drive subcode */
	  regs.h.ah = 0x15 ;  regs.h.al = 0x10 ;
	  regs.x.cx = start ;
/* buffer length, unit, command code */
	  buf [0] = 30 ;  buf [1] = d_num ;  buf [2] = 12 ;
/* return parameters */
	  buf [3] = buf [4] = 0 ;
/* reserved 8 bytes */
	  buf [5] = buf [6] = buf [7] = buf [8] = buf [9] = 0 ;
	  buf [10] = buf [11] = buf [12] = 0 ;
/* media descriptor byte */
	  buf [13] = 0 ;
/* transfer address */
	  *(unsigned long *)(&buf [14]) = (unsigned long)(&buf2 [0]) ;
/* number of bytes to transfer */
	  *(unsigned long *)(&buf [18]) = 1 ;
/* starting sector number (fake) */
	  buf [22] = buf [23] = buf [24] = buf [25] = 0 ;
/* DWord ptr ... (fake) */
	  buf [26] = buf [27] = buf [28] = buf [29] = 0 ;
/* Command code */
	  buf2 [0] = 5 ;
/* parameter's block */
	  sregs.es = FP_SEG ( buf ) ;  regs.x.bx = FP_OFF ( buf ) ;

	  int86x ( 0x2F , &regs , &regs , &sregs ) ;

	  return ( error_code ( buf [3] , buf [4] ) ) ;
        }  /* END cd_load */
/*---*/
	unsigned cd_init ( unsigned d_num )
	{
	  union REGS regs ;
	  struct SREGS sregs ;
	  unsigned char buf [30] , buf2 [11] ;
	  unsigned num , start ;
/* Attempt to detect CD-ROM */
	  regs.x.ax = 0x1500 ;  regs.x.bx = 0 ;

	  int86x ( 0x2F , &regs , &regs , &sregs ) ;

	  num = regs.x.bx ;  start = regs.x.cx ;

	  if ( num == 0 ) return ( error_code ( 0xFF , 0x80 ) ) ;
/* parameters & drive subcode */
	  regs.h.ah = 0x15 ;  regs.h.al = 0x10 ;
	  regs.x.cx = start ;
/* buffer length, unit, command code */
	  buf [0] = 23 ;  buf [1] = d_num ;  buf [2] = 0 ;
/* return parameters */
	  buf [3] = buf [4] = 0 ;
/* reserved 8 bytes */
	  buf [5] = buf [6] = buf [7] = buf [8] = buf [9] = 0 ;
	  buf [10] = buf [11] = buf [12] = 0 ;
/* Number of units (fake) */
	  buf [13] = 0 ;
/* end address */
	  *(unsigned long *)(&buf [14]) = (unsigned long)(&buf2 [0]) ;
/* ptr to BPB array */
	  *(unsigned long *)(&buf [18]) = (unsigned long)(&buf2 [4]) ;
/* block device number (fake) */
	  buf [22] = 0 ;
/* parameter's block */
	  sregs.es = FP_SEG ( buf ) ;  regs.x.bx = FP_OFF ( buf ) ;

	  int86x ( 0x2F , &regs , &regs , &sregs ) ;

	  return ( error_code ( buf [3] , buf [4] ) ) ;
	}  /* END cd_init */
/*---*/
	unsigned cd_stop ( unsigned d_num )
	{
	  union REGS regs ;
	  struct SREGS sregs ;
	  unsigned char buf [14] ;
	  unsigned num , start ;
/* Attempt to detect CD-ROM */
	  regs.x.ax = 0x1500 ;  regs.x.bx = 0 ;

	  int86x ( 0x2F , &regs , &regs , &sregs ) ;

	  num = regs.x.bx ;  start = regs.x.cx ;

	  if ( num == 0 ) return ( error_code ( 0xFF , 0x80 ) ) ;
/* parameters & drive subcode */
	  regs.h.ah = 0x15 ;  regs.h.al = 0x10 ;
	  regs.x.cx = start ;
/* buffer length, unit, command code */
	  buf [0] = 13 ;  buf [1] = d_num ;  buf [2] = 133 ;
/* return parameters */
	  buf [3] = buf [4] = 0 ;
/* reserved 8 bytes */
	  buf [5] = buf [6] = buf [7] = buf [8] = buf [9] = 0 ;
	  buf [10] = buf [11] = buf [12] = 0 ;
/* parameter's block */
	  sregs.es = FP_SEG ( buf ) ;  regs.x.bx = FP_OFF ( buf ) ;

	  int86x ( 0x2F , &regs , &regs , &sregs ) ;

	  return ( error_code ( buf [3] , buf [4] ) ) ;
	}  /* END cd_stop */
/*---*/
	unsigned cd_resume ( unsigned d_num )
	{
	  union REGS regs ;
	  struct SREGS sregs ;
	  unsigned char buf [14] ;
	  unsigned num , start ;
/* Attempt to detect CD-ROM */
	  regs.x.ax = 0x1500 ;  regs.x.bx = 0 ;

	  int86x ( 0x2F , &regs , &regs , &sregs ) ;

	  num = regs.x.bx ;  start = regs.x.cx ;

	  if ( num == 0 ) return ( error_code ( 0xFF , 0x80 ) ) ;
/* parameters & drive subcode */
	  regs.h.ah = 0x15 ;  regs.h.al = 0x10 ;
	  regs.x.cx = start ;
/* buffer length, unit, command code */
	  buf [0] = 13 ;  buf [1] = d_num ;  buf [2] = 136 ;
/* return parameters */
	  buf [3] = buf [4] = 0 ;
/* reserved 8 bytes */
	  buf [5] = buf [6] = buf [7] = buf [8] = buf [9] = 0 ;
	  buf [10] = buf [11] = buf [12] = 0 ;
/* parameter's block */
	  sregs.es = FP_SEG ( buf ) ;  regs.x.bx = FP_OFF ( buf ) ;

	  int86x ( 0x2F , &regs , &regs , &sregs ) ;

	  return ( error_code ( buf [3] , buf [4] ) ) ;
	}  /* END cd_resume */
/*---*/
	unsigned cd_as_info ( unsigned d_num , unsigned long *str ,
			      unsigned long *end  )
	{
	  union REGS regs ;
	  struct SREGS sregs ;
	  unsigned char buf [30] , buf2 [11] ;
	  unsigned num , start ;
/* Attempt to detect CD-ROM */
	  regs.x.ax = 0x1500 ;  regs.x.bx = 0 ;

	  int86x ( 0x2F , &regs , &regs , &sregs ) ;

	  num = regs.x.bx ;  start = regs.x.cx ;

	  if ( num == 0 ) return ( error_code ( 0xFF , 0x80 ) ) ;
/* parameters & drive subcode */
	  regs.h.ah = 0x15 ;  regs.h.al = 0x10 ;
	  regs.x.cx = start ;
/* buffer length, unit, command code */
	  buf [0] = 30 ;  buf [1] = d_num ;  buf [2] = 3 ;
/* return parameters */
	  buf [3] = buf [4] = 0 ;
/* reserved 8 bytes */
	  buf [5] = buf [6] = buf [7] = buf [8] = buf [9] = 0 ;
	  buf [10] = buf [11] = buf [12] = 0 ;
/* number of units */
	  buf [13] = 0 ;
/* transfer address */
	  *(unsigned long *)(&buf [14]) = (unsigned long)(&buf2 [0]) ;
/* number of bytes to transfer */
	  *(unsigned long *)(&buf [18]) = 11 ;
/* starting sector number */
	  buf [22] = buf [23] = buf [24] = buf [25] = 0 ;
/* vol ID */
	  buf [26] = buf [27] = buf [28] = buf [29] = 0 ;
/* control block code */
	  buf2 [0] = 15 ;
/* Status bits */
	  buf2 [1] = buf2 [2] = 0 ;
/* Starting location */
	  buf2 [3] = buf2 [4] = buf2 [5] = buf2 [6] = 0 ;
/* Ending location */
	  buf2 [7] = buf2 [8] = buf2 [9] = buf2 [10] = 0 ;
/* parameter's block */
	  sregs.es = FP_SEG ( buf ) ;  regs.x.bx = FP_OFF ( buf ) ;

	  int86x ( 0x2F , &regs , &regs , &sregs ) ;

	  *str = *(unsigned long *)(&buf2 [3]) ;
	  *end = *(unsigned long *)(&buf2 [7]) ;

	  return ( error_code ( buf [3] , buf [4] ) ) ;
	}  /* END cd_as_info */
/*---*/
	unsigned cd_lock ( unsigned d_num )
	{
	  union REGS regs ;
	  struct SREGS sregs ;
	  unsigned char buf [30] , buf2 [4] ;
	  unsigned num , start ;
/* Attempt to detect CD-ROM */
	  regs.x.ax = 0x1500 ;  regs.x.bx = 0 ;

	  int86x ( 0x2F , &regs , &regs , &sregs ) ;

	  num = regs.x.bx ;  start = regs.x.cx ;

	  if ( num == 0 ) return ( error_code ( 0xFF , 0x80 ) ) ;
/* parameters & drive subcode */
	  regs.h.ah = 0x15 ;  regs.h.al = 0x10 ;
	  regs.x.cx = start ;
/* buffer length, unit, command code */
	  buf [0] = 30 ;  buf [1] = d_num ;  buf [2] = 12 ;
/* return parameters */
	  buf [3] = buf [4] = 0 ;
/* reserved 8 bytes */
	  buf [5] = buf [6] = buf [7] = buf [8] = buf [9] = 0 ;
	  buf [10] = buf [11] = buf [12] = 0 ;
/* media descriptor byte */
	  buf [13] = 0 ;
/* transfer address */
	  *(unsigned long *)(&buf [14]) = (unsigned long)(&buf2 [0]) ;
/* number of bytes to transfer */
	  *(unsigned long *)(&buf [18]) = 2 ;
/* starting sector number (fake) */
	  buf [22] = buf [23] = buf [24] = buf [25] = 0 ;
/* DWord ptr ... (fake) */
	  buf [26] = buf [27] = buf [28] = buf [29] = 0 ;
/* Command code */
	  buf2 [0] = 1 ;
/* Lock function */
	  buf2 [1] = 1 ;
/* parameter's block */
	  sregs.es = FP_SEG ( buf ) ;  regs.x.bx = FP_OFF ( buf ) ;

	  int86x ( 0x2F , &regs , &regs , &sregs ) ;

	  return ( error_code ( buf [3] , buf [4] ) ) ;
	}  /* END cd_lock */
/*---*/
	unsigned cd_unlock ( unsigned d_num )
	{
	  union REGS regs ;
	  struct SREGS sregs ;
	  unsigned char buf [30] , buf2 [4] ;
	  unsigned num , start ;
/* Attempt to detect CD-ROM */
	  regs.x.ax = 0x1500 ;  regs.x.bx = 0 ;

	  int86x ( 0x2F , &regs , &regs , &sregs ) ;

	  num = regs.x.bx ;  start = regs.x.cx ;

	  if ( num == 0 ) return ( error_code ( 0xFF , 0x80 ) ) ;
/* parameters & drive subcode */
	  regs.h.ah = 0x15 ;  regs.h.al = 0x10 ;
	  regs.x.cx = start ;
/* buffer length, unit, command code */
	  buf [0] = 30 ;  buf [1] = d_num ;  buf [2] = 12 ;
/* return parameters */
	  buf [3] = buf [4] = 0 ;
/* reserved 8 bytes */
	  buf [5] = buf [6] = buf [7] = buf [8] = buf [9] = 0 ;
	  buf [10] = buf [11] = buf [12] = 0 ;
/* media descriptor byte */
	  buf [13] = 0 ;
/* transfer address */
	  *(unsigned long *)(&buf [14]) = (unsigned long)(&buf2 [0]) ;
/* number of bytes to transfer */
	  *(unsigned long *)(&buf [18]) = 2 ;
/* starting sector number (fake) */
	  buf [22] = buf [23] = buf [24] = buf [25] = 0 ;
/* DWord ptr ... (fake) */
	  buf [26] = buf [27] = buf [28] = buf [29] = 0 ;
/* Command code */
	  buf2 [0] = 1 ;
/* Lock function */
	  buf2 [1] = 0 ;
/* parameter's block */
	  sregs.es = FP_SEG ( buf ) ;  regs.x.bx = FP_OFF ( buf ) ;

	  int86x ( 0x2F , &regs , &regs , &sregs ) ;

	  return ( error_code ( buf [3] , buf [4] ) ) ;
	}  /* END cd_unlock */
/*---*/
	unsigned cd_aud_info ( unsigned d_num , unsigned *ch1 ,
			       unsigned *ch2 , unsigned *ch3 ,
			       unsigned *ch4 )
	{
	  union REGS regs ;
	  struct SREGS sregs ;
	  unsigned char buf [30] , buf2 [10] ;
	  unsigned num , start ;
/* Attempt to detect CD-ROM */
	  regs.x.ax = 0x1500 ;  regs.x.bx = 0 ;

	  int86x ( 0x2F , &regs , &regs , &sregs ) ;

	  num = regs.x.bx ;  start = regs.x.cx ;

	  if ( num == 0 ) return ( error_code ( 0xFF , 0x80 ) ) ;
/* parameters & drive subcode */
	  regs.h.ah = 0x15 ;  regs.h.al = 0x10 ;
	  regs.x.cx = start ;
/* buffer length, unit, command code */
	  buf [0] = 30 ;  buf [1] = d_num ;  buf [2] = 3 ;
/* return parameters */
	  buf [3] = buf [4] = 0 ;
/* reserved 8 bytes */
	  buf [5] = buf [6] = buf [7] = buf [8] = buf [9] = 0 ;
	  buf [10] = buf [11] = buf [12] = 0 ;
/* reserved */
	  buf [13] = 0 ;
/* transfer address */
	  *(unsigned long *)(&buf [14]) = (unsigned long)(&buf2 [0]) ;
/* number of bytes to transfer */
	  *(unsigned long *)(&buf [18]) = 9 ;
/* starting sector number */
	  buf [22] = buf [23] = buf [24] = buf [25] = 0 ;
/* vol ID */
	  buf [26] = buf [27] = buf [28] = buf [29] = 0 ;
/* control block code */
	  buf2 [0] = 4 ;
/* Clear space 4 return values */
	  buf2 [1] = buf2 [2] = buf2 [3] = buf2 [4] = 0 ;
	  buf2 [5] = buf2 [6] = buf2 [7] = buf2 [8] = 0 ;
/* parameter's block */
	  sregs.es =  FP_SEG ( buf ) ;  regs.x.bx = FP_OFF ( buf ) ;

	  int86x ( 0x2F , &regs , &regs , &sregs ) ;

	  *ch1 = buf2 [2] ;  *ch2 = buf2 [4] ;
	  *ch3 = buf2 [6] ;  *ch4 = buf2 [8] ;

	  return ( error_code ( buf [3] , buf [4] ) ) ;
	}  /* END cd_aud_info */
/*---*/
	unsigned cd_set_aud ( unsigned d_num , unsigned ch1 ,
			      unsigned ch2 , unsigned ch3 ,
			      unsigned ch4 )
	{
	  union REGS regs ;
	  struct SREGS sregs ;
	  unsigned char buf [30] , buf2 [10] ;
	  unsigned num , start ;
/* Attempt to detect CD-ROM */
	  regs.x.ax = 0x1500 ;  regs.x.bx = 0 ;

	  int86x ( 0x2F , &regs , &regs , &sregs ) ;

	  num = regs.x.bx ;  start = regs.x.cx ;

	  if ( num == 0 ) return ( error_code ( 0xFF , 0x80 ) ) ;
/* parameters & drive subcode */
	  regs.h.ah = 0x15 ;  regs.h.al = 0x10 ;
	  regs.x.cx = start ;
/* buffer length, unit, command code */
	  buf [0] = 30 ;  buf [1] = d_num ;  buf [2] = 12 ;
/* return parameters */
	  buf [3] = buf [4] = 0 ;
/* reserved 8 bytes */
	  buf [5] = buf [6] = buf [7] = buf [8] = buf [9] = 0 ;
	  buf [10] = buf [11] = buf [12] = 0 ;
/* media descriptor byte */
	  buf [13] = 0 ;
/* transfer address */
	  *(unsigned long *)(&buf [14]) = (unsigned long)(&buf2 [0]) ;
/* number of bytes to transfer */
	  *(unsigned long *)(&buf [18]) = 9 ;
/* starting sector number (fake) */
	  buf [22] = buf [23] = buf [24] = buf [25] = 0 ;
/* DWord ptr ... (fake) */
	  buf [26] = buf [27] = buf [28] = buf [29] = 0 ;
/* Command code */
	  buf2 [0] = 3 ;
/* Volume control info */
	  buf2 [1] = 0 ;  buf2 [2] = ch1 ;
	  buf2 [3] = 1 ;  buf2 [4] = ch2 ;
	  buf2 [5] = 2 ;  buf2 [6] = ch3 ;
	  buf2 [7] = 3 ;  buf2 [8] = ch4 ;
/* parameter's block */
	  sregs.es = FP_SEG ( buf ) ;  regs.x.bx = FP_OFF ( buf ) ;

	  int86x ( 0x2F , &regs , &regs , &sregs ) ;

	  return ( error_code ( buf [3] , buf [4] ) ) ;
	}  /* END cd_set_aud */
/*------------------------ Second level routines ------------------------*/
	unsigned get_t_time ( unsigned num , unsigned track ,
			      unsigned *min , unsigned *sec ,
			      unsigned *frame )
	{
	  unsigned long lt , gt ;
	  unsigned info , adr , first , last , r ;

	  *min = *sec = *frame = 0 ;

	  if ( ( r = cd_audio_info ( num , &first , &last , &gt ) )
	       != (0|1) ) return ( r ) ;
	  if ( track < first || track > last )
	       return ( error_code ( 0xFE , 0x80 ) ) ;
	  if ( ( r = cd_atrack_info ( num , track , &info , &lt ,
	       &adr ) ) != (0|1) ) return ( r ) ;

	  if ( track == last )
	       dec_t_time ( bcd_sub ( lt , gt ) , min , sec , frame ) ;
	  else
	  {
	    if ( ( r = cd_atrack_info ( num , track + 1 , &info , &gt ,
		 &adr ) ) != (0|1) ) return ( r ) ;

	    dec_t_time ( bcd_sub ( lt , gt ) , min , sec , frame ) ;
	  }  /* ! a last track */
	  return ( 0 ) ;
	}  /* END get_t_time */
/*---*/
/* 1 - Busy ;  0 - Free */
	unsigned check_if_busy ( unsigned num )
	{
	   unsigned status , l ;

	   l = cd_stat ( num , &status ) ;
	   if ( l == 2 ) return ( 1 ) ;
	   else return ( 0 ) ;
	}  /* END check if busy */
/*---*/
/* min, sec, frame -- real track time information */
/* rmin, rsec -- rounded information */
	void round_time ( unsigned min , unsigned sec ,
			  unsigned frame , unsigned *rmin ,
			  unsigned *rsec )
	{
	  *rmin = min ;  *rsec = sec ;

	  if ( frame > 37 )
	  {
	    if ( sec > 58 )
	    {
	      *rmin += 1 ;
	      *rsec = 0 ;
	    }  /* 59 minutes */
	    else *rsec += 1 ;
	  }  /* rounding required */
	}  /* END round_time */
/*---*/
/* num -- CD-ROM number, track -- track number */
/* str -- starting track time (0 -- beginning) */
/* sec -- time to play (0 -- entire track) */
	unsigned play_track ( unsigned num , unsigned track ,
			      unsigned str , unsigned sec )
	{
	  unsigned long lt , gt , t , t2 , t3 ;
	  unsigned info , adr , first , last , r ;

	  if ( ( r = cd_audio_info ( num , &first , &last , &gt ) )
	       != (0|1) ) return ( r ) ;

	  if ( track < first || track > last )
	       return ( error_code ( 0xFE , 0x80 ) ) ;
	  if ( ( r = cd_atrack_info ( num , track , &info , &lt ,
	       &adr ) ) != (0|1) ) return ( r ) ;

	  if ( track != last )
	  {
	    if ( ( r = cd_atrack_info ( num , track + 1 , &info , &gt ,
		 &adr ) ) != (0|1) ) return ( r ) ;
	  }

	  t = bcd_sub ( lt , gt ) ;
/*S*/
	  if ( str != 0 )
	  {
	    t3 = dec2bcd ( str * V1 ) ;
	    t2 = dec2bcd ( bcd_add ( lt , t3 ) ) ;

	    if ( t2 < gt ) t = bcd_sub ( lt = t2 , gt ) ;
	    else return ( error_code ( 0xFD , 0x80 ) ) ;
	  }  /* Start from the specified position */
/*L*/
	  if ( sec != 0 )
	  {
	    t3 = (unsigned long)sec ;
	    t2 = ( t3 / 60L ) * V2 + ( t3 % 60L ) * V1 ;

	    if ( t > t2 ) t = t2 ;
	    else return ( error_code ( 0xFD , 0x80 ) ) ;
	  }   /* Play the specified time */

	  r = cd_play ( num , lt , t , adr ) ;
	  return ( r ) ;
	}  /* END play track */
/*-----------------------------------------------------------------------*/
	main ()
	{
	  unsigned info , i , k , l , m , adr , res ;
	  unsigned pmin, psec , pframe , amin , asec , aframe ,
		   index , track , min , sec , frame , min2 , sec2 ,
		   ch1 , ch2 , ch3 , ch4 ;
	  unsigned long l_out , g_out , songs [100] , tmp , tmp2 ;
	  clock_t start , end ;

	  clrscr () ;

	  cd_stop ( 0 ) ;
	  while ( check_if_busy ( 0 ) ) ;

//	  cd_aud_info ( 0 , &ch1 , &ch2 , &ch3 , &ch4 ) ;

	  if ( !cd_stat ( 0 , &info ) )
	  {
	    printf ( "\n  I/O Error \n" ) ;
	    exit ( 1 ) ;
	  }

	  start = clock () ;
	  l = play_track ( 0 , 17 , 90 , 0 ) ;

	  do
	  {
	    for ( i = 0x0 ;  i <= 0x00FF ;  i += 15 )
	    {
	      cd_set_aud ( 0 , i , 0x00FF - i , 0 , 0 ) ;
	      delay ( 600L ) ;
	    }  /* Check ... */
	  } while ( check_if_busy ( 0 ) ) ;

	  do
	  {
	    l = check_if_busy ( 0 ) ;
	  } while ( l ) ;

	  end = clock () ;
	  start *= 10 ;  start /= 182 ;
	  end *= 10 ;  end /= 182 ;  end -= start ;
	  start /= 3600 ;  end %= 3600 ;

	  cd_q_info ( 0 , &track , &index , &pmin , &psec ,
		      &pframe , &amin , &asec , &aframe ) ;

	  round_time ( pmin , psec , pframe , &min2 , &sec2 ) ;

	  printf ( "\n  Elapsed time: %ldm%lds\n" , end / 60 ,
		   end % 60 ) ;
	  printf ( "\n  Offset from a beginning of the song: %um%us" ,
		   min2 , sec2 ) ;

	  cd_stop ( 0 ) ;

	  printf ( "\n\n  Completed. Bye from TOKsoft\n" ) ;  exit ( 0 ) ;
	}  /* END main */
