home *** CD-ROM | disk | FTP | other *** search
/ modiromppu / modiromppu.iso / PROGRAMS / ORGPACKS / DIDO4.ZIP / SOURCE.ZIP / DIDOD.C < prev    next >
C/C++ Source or Header  |  1995-01-23  |  9KB  |  337 lines

  1.  
  2. // Routines to make calls to the real-mode CDROM driver from protected-mode Windows,
  3. // Using GlobalDOSAlloc and DPMI's int86x service.
  4.  
  5. // These are allocated in real-mode DOS memory:
  6.  
  7. DWORD cmdbuf=0,                // Buffer for commands, device driver request headers, etc...
  8.       databuf=0,            // Buffer for actual data
  9.       buf[MAXNBUF],            // Buffer for reading audio data
  10.       prev_end=0;            // Buffer for synchronization
  11.  
  12. WORD cmdbufseg,cmdbufsel,
  13.      databufseg,databufsel, // The same as above, but split into SEG/SEL pairs
  14.      bufseg[MAXNBUF],bufsel[MAXNBUF],
  15.      prev_endseg, prev_endsel;
  16.  
  17. BYTE *pcmdbuf=0,            // Pointers the program can use to access above memory areas
  18.      *pdatabuf=0,
  19.      *pprev_end=0,
  20.      *pbuf[MAXNBUF];
  21.  
  22. // Set things up to interact with the CDROM driver. Returns 0:Failure, 1:Success
  23. int startinterfacing(void)
  24. {
  25.     int i;
  26.  
  27.     memset(buf,0,sizeof(buf));        // zap buffer pointers
  28.  
  29.     cmdbuf=GlobalDosAlloc(32);        // 32 bytes for command buffer (BTW, is at most 26 bytes)
  30.     cmdbufseg=HIWORD(cmdbuf); 
  31.     cmdbufsel=LOWORD(cmdbuf); 
  32.     pcmdbuf=MK_FP(cmdbufsel,0);
  33.  
  34.     if (!cmdbuf) goto Allocerror;          
  35.  
  36.     databuf=GlobalDosAlloc(4096);    // general purpose data buffer
  37.     databufseg=HIWORD(databuf); 
  38.     databufsel=LOWORD(databuf); 
  39.     pdatabuf=MK_FP(databufsel,0); 
  40.  
  41.     if (!databuf) goto Allocerror;
  42.  
  43.     prev_end=GlobalDosAlloc((long)FRAME_SIZE * NBLOCK);
  44.     prev_endseg=HIWORD(prev_end); 
  45.     prev_endsel=LOWORD(prev_end); 
  46.     pprev_end=MK_FP(prev_endsel,0);
  47.     if (!prev_end) goto Allocerror;
  48.  
  49.     // Try to allocate as much data buffers if possible, up to MAXNBUF
  50.  
  51.     nbuf=0;
  52.     for (i=0;i<MAXNBUF;i++) {
  53.         buf[nbuf]=GlobalDosAlloc((long)FRAME_SIZE*NBLOCK);
  54.         bufseg[nbuf]=HIWORD(buf[nbuf]);
  55.         bufsel[nbuf]=LOWORD(buf[nbuf]);
  56.         pbuf[nbuf]=MK_FP(bufsel[nbuf],0);
  57.         if (!buf[nbuf]) {
  58.             if (nbuf<2) goto Allocerror;
  59.             break;
  60.             }
  61.         nbuf++;
  62.         }
  63.  
  64.     return 1;                                                    // success
  65.  
  66. Allocerror:
  67.  
  68.     for (i=0;i<nbuf;i++) if (buf[i]) GlobalDosFree(bufsel[i]);
  69.     if (cmdbuf) GlobalDosFree(cmdbufsel);
  70.     if (databuf) GlobalDosFree(databufsel);
  71.     if (prev_end) GlobalDosFree(prev_endsel);
  72.     return 0;                                                    // failure
  73. }
  74.  
  75.  
  76. // Free the real-mode buffers
  77. int stopinterfacing(void)
  78. {
  79.     int i;
  80.     for (i=0;i<nbuf;i++) GlobalDosFree(bufsel[i]);
  81.     GlobalDosFree(cmdbufsel);
  82.     GlobalDosFree(databufsel);
  83.     GlobalDosFree(prev_endsel);
  84.     return 1;
  85. }
  86.  
  87. // Used for DPMI call
  88. struct realregs {
  89.     DWORD edi,esi,ebp,resvd,ebx,edx,ecx,eax;
  90.     WORD flags,es,ds,fs,gs,ip,cs,sp,ss; 
  91.     };
  92.  
  93. int dpmint86(int intnr,struct realregs *in,struct realregs *out)
  94. {
  95.     union REGS inregs, outregs; 
  96.     struct SREGS sregs; 
  97.     struct realregs *r; 
  98.      
  99.     memset(&inregs,0,sizeof(union REGS));        // Just to be sure there is no junk... 
  100.     memset(&outregs,0,sizeof(union REGS)); 
  101.     memset(&sregs,0,sizeof(struct SREGS)); 
  102.  
  103.     inregs.x.ax=0x0300;                         // Simulate Real Mode Interrupt 
  104.     inregs.x.bx=intnr;                             // interrupt # 
  105.     inregs.x.di=FP_OFF(in);                     // address of struct regs
  106.     sregs.es=FP_SEG(in);                        //     ,, 
  107.     int86x(0x31,&inregs,&outregs,&sregs);        // Call real mode INT via DPMI 
  108.     if (outregs.x.cflag) {
  109.         mb("DPMI interface returned error");
  110.         return 1;                                // DPMI gave error? Exit.
  111.         } 
  112.     r=MK_FP(sregs.es, outregs.x.di);            // Where to find the output 
  113.     if(r->flags & 1) {
  114.         mb("INT2F returned error");
  115.         return 1;                                // Interrupt in error? Test for carry, exit if 1
  116.         }
  117.     memcpy(out,r,sizeof(struct realregs));        // Get result registers back
  118.     return 0; 
  119. }
  120.  
  121. // Is MSCDEX installed? (No need for DPMI using this call)
  122. int CheckMscdex(void)
  123. {
  124.     union REGS reg;
  125.     reg.x.ax=0x1500;                            // MSCDEX - Get number of CDROM drives
  126.     reg.x.bx=0;
  127.     int86(0x2f,®,®);
  128.     if (!reg.x.bx) return 0;                    // Nr. of CDROM drives in bx
  129.     CDROM=reg.x.cx;                                // CX=first CDROM drive (A==0, B==1, etc)
  130.     return 1;
  131. }
  132.  
  133. // Is Smartdrv (v4.1+ or compaitble cache) installed?
  134. int CheckSmartdrv(void)
  135. {
  136.     union REGS reg;
  137.     reg.x.ax=0x4A10;
  138.     reg.x.bx=0;
  139.     reg.x.cx=0xEBAB;
  140.     int86(0x2f,®,®);
  141.     if (reg.x.ax==0xBABE) return 1; else return 0;
  142. }
  143.  
  144. // Does Smartdrv caches the CDROM ?
  145. int CheckCDROMCached(void)
  146. {
  147.     struct REGPACK r;
  148.     r.r_ax=0x4A10;
  149.     r.r_bx=3;
  150.     r.r_bp=CDROM;
  151.     r.r_dx=0;
  152.     intr(0x2f,&r);
  153.     if (r.r_ax!=0xBABE) {
  154.         mb("Smartdrv status call error");
  155.         return 0;    // error in call
  156.         }
  157.     if (r.r_dx&0x0080) return 0;    // BL bit 7 set? not cached!
  158.     return 1;
  159. }
  160.  
  161.  
  162. // Call CDROM device driver; command-buffer (at pcmdbuf) must be filled by caller
  163. void CallDriver(void)
  164. {
  165.     struct realregs r;                            // Prepare registers
  166.     memset(&r,0,sizeof(r));
  167.     r.eax=0x1510;                                // Function: CDROM device driver request
  168.     r.es=cmdbufseg; r.ebx=0;                    // Address of request structure 
  169.     r.ecx=CDROM;                                // Drive number of CDROM
  170.     dpmint86(0x2f,&r,&r);
  171. }
  172.  
  173. // Get CDROM disk information
  174. int GetDiskInfo(void)
  175. {
  176.     struct IOCTLI *pcmd=(struct IOCTLI *)pcmdbuf;
  177.     struct DiskInfo *pdi=(struct DiskInfo *)pdatabuf;
  178.  
  179.     pcmd->req.len=26;
  180.     pcmd->req.unit=0;
  181.     pcmd->req.command=3;
  182.     pcmd->descriptor=0;
  183.     pcmd->address=MK_FP(databufseg,0);
  184.     pcmd->len=7;
  185.     pcmd->secnum=0;
  186.     pcmd->ptr=0;
  187.     pdi ->control=10;
  188.  
  189.     CallDriver();
  190.  
  191.     lowest =pdi->lowest;
  192.     highest=pdi->highest;
  193.     total_time=pdi->total;
  194.     return pcmd->req.status;
  195. }
  196.  
  197.  
  198. // Read one or more raw audio sectors
  199. int ReadLong(DWORD loc, WORD secnum,WORD bufseg)
  200. {
  201.     struct ReadL *pcmd=(struct ReadL *)pcmdbuf;
  202.     pcmd->req.len=sizeof(struct ReadL);
  203.     pcmd->req.unit=0;
  204.     pcmd->req.command=128;
  205.     pcmd->mode=0;
  206.     pcmd->address=MK_FP(bufseg,0);
  207.     pcmd->secnum=secnum;
  208.     pcmd->loc=loc;
  209.     pcmd->readmode=RAW_MODE;
  210.     pcmd->skip[0]=pcmd->skip[1]=0;
  211.     CallDriver();
  212.     return pcmd->req.status;
  213. }
  214.  
  215.  
  216. // Convert sector number to printable MM:SS:FF string, for durations.
  217. char *Sector2MSF(DWORD sector)
  218. {
  219.     static char s[20];
  220.     long min,sec,frames;
  221.     frames=sector%75;
  222.     sec=sector/75;
  223.     min=sec/60; sec=sec%60;
  224.     sprintf(s,"%02ldm %02lds %02ldf",min,sec,frames);
  225.     return s;
  226. }
  227.  
  228. // Convert Sierra sector number to redbook
  229. DWORD Sierra2Red(DWORD sierra)
  230. {
  231.     DWORD min,sec,frame,loc;
  232.     sierra+=150;                         /// ????????????
  233.     frame=sierra%75;
  234.     sec=sierra/75;
  235.     min=sec/60; sec=sec%60;
  236.  
  237.     loc=(BYTE)min;
  238.     loc<<=8;    loc|=(BYTE)sec;
  239.     loc<<=8;    loc|=(BYTE)frame;
  240.     return loc;
  241. }
  242.  
  243.  
  244. // Convert redbood time location to Sierra sector
  245. DWORD Red2Sierra(DWORD loc)
  246. {
  247.     BYTE min,sec,frame;
  248.     min=(loc>>16)&0xff;
  249.     sec=(loc>>8)&0xff;
  250.     frame=loc&0xff;
  251.     return (DWORD)min*75*60+(DWORD)sec*75+(DWORD)frame-150;
  252. }
  253.  
  254.  
  255. // Convert redbook time location to printable string
  256. char *Red2MSF(DWORD loc)
  257. {
  258.     static char s[20];
  259.     BYTE min,sec,frame;
  260.     min=(loc>>16)&0xff;
  261.     sec=(loc>>8)&0xff;
  262.     frame=loc&0xff;
  263.     sprintf(s,"%02um %02us %02uf",min,sec,frame);
  264.     return s;
  265. }
  266.  
  267.  
  268. // Convert redbook time location to minute, second, frame, and Sierra sector
  269. void Red2MSFC(DWORD loc,WORD *min,WORD *sec,WORD *frame,DWORD *sector)
  270. {
  271.     *frame=loc&0xff;
  272.     loc>>=8;    *sec=loc&0xff;
  273.     loc>>=8;    *min=loc&0xff;
  274.     *sector=((DWORD)*min)*75*60+((DWORD)*sec)*75+((DWORD)*frame)-150;
  275. }
  276.  
  277.  
  278. // Convert minute, second, frame to redbook timecode and Sierra sector
  279. void MSF2Red(WORD min,WORD sec,WORD frame,DWORD *red,DWORD *sector)
  280. {
  281.     DWORD loc=0;
  282.     *sector=(DWORD)min*75*60+(DWORD)sec*75+(DWORD)frame-150;
  283.     loc|=min; loc<<=8;
  284.     loc|=sec; loc<<=8;
  285.     loc|=frame;
  286.     *red=loc;
  287. }
  288.  
  289.  
  290. // Ask the CDROM device driver information about a track.
  291. // Given the track number, find out at which sector it starts
  292. int GetTrackInfo(int track,DWORD *loc)
  293. {
  294.     struct IOCTLI *pcmd=(struct IOCTLI *)pcmdbuf;
  295.     struct TrackInfo *pbuf=(struct TrackInfo *)pdatabuf;
  296.     pcmd->req.len=26;
  297.     pcmd->req.unit=0;
  298.     pcmd->req.command=3;
  299.     pcmd->descriptor=0;
  300.     pcmd->address=MK_FP(databufseg,0);
  301.     pcmd->len=7;
  302.     pcmd->secnum=0;
  303.     pcmd->ptr=0;
  304.     pbuf->control=11;
  305.     pbuf->track=track;
  306.     CallDriver();
  307.     *loc=pbuf->loc;
  308.     return pcmd->req.status;
  309. }
  310.  
  311.  
  312. // Stop playing of current audio piece
  313. int StopAudio(void)
  314. {
  315.     struct ReqHdr *pcmd=(struct ReqHdr *)pcmdbuf;
  316.     pcmd->len=13;
  317.     pcmd->unit=0;
  318.     pcmd->command=133;
  319.     CallDriver();
  320.     return pcmd->status;
  321. }
  322.  
  323.  
  324. // Play an piece of audio
  325. int PlayAudio(DWORD loc, DWORD num)
  326. {
  327.     struct PlayReq *pcmd=(struct PlayReq *)pcmdbuf;
  328.     pcmd->req.len=22;
  329.     pcmd->req.unit=0;
  330.     pcmd->req.command=132;
  331.     pcmd->mode=1;
  332.     pcmd->loc=loc;
  333.     pcmd->secnum=num;
  334.     CallDriver();
  335.     return pcmd->req.status;
  336. }
  337.