home
***
CD-ROM
|
disk
|
FTP
|
other
***
search
/
modiromppu
/
modiromppu.iso
/
PROGRAMS
/
ORGPACKS
/
DIDO4.ZIP
/
SOURCE.ZIP
/
DIDOD.C
< prev
next >
Wrap
C/C++ Source or Header
|
1995-01-23
|
9KB
|
337 lines
// Routines to make calls to the real-mode CDROM driver from protected-mode Windows,
// Using GlobalDOSAlloc and DPMI's int86x service.
// These are allocated in real-mode DOS memory:
DWORD cmdbuf=0, // Buffer for commands, device driver request headers, etc...
databuf=0, // Buffer for actual data
buf[MAXNBUF], // Buffer for reading audio data
prev_end=0; // Buffer for synchronization
WORD cmdbufseg,cmdbufsel,
databufseg,databufsel, // The same as above, but split into SEG/SEL pairs
bufseg[MAXNBUF],bufsel[MAXNBUF],
prev_endseg, prev_endsel;
BYTE *pcmdbuf=0, // Pointers the program can use to access above memory areas
*pdatabuf=0,
*pprev_end=0,
*pbuf[MAXNBUF];
// Set things up to interact with the CDROM driver. Returns 0:Failure, 1:Success
int startinterfacing(void)
{
int i;
memset(buf,0,sizeof(buf)); // zap buffer pointers
cmdbuf=GlobalDosAlloc(32); // 32 bytes for command buffer (BTW, is at most 26 bytes)
cmdbufseg=HIWORD(cmdbuf);
cmdbufsel=LOWORD(cmdbuf);
pcmdbuf=MK_FP(cmdbufsel,0);
if (!cmdbuf) goto Allocerror;
databuf=GlobalDosAlloc(4096); // general purpose data buffer
databufseg=HIWORD(databuf);
databufsel=LOWORD(databuf);
pdatabuf=MK_FP(databufsel,0);
if (!databuf) goto Allocerror;
prev_end=GlobalDosAlloc((long)FRAME_SIZE * NBLOCK);
prev_endseg=HIWORD(prev_end);
prev_endsel=LOWORD(prev_end);
pprev_end=MK_FP(prev_endsel,0);
if (!prev_end) goto Allocerror;
// Try to allocate as much data buffers if possible, up to MAXNBUF
nbuf=0;
for (i=0;i<MAXNBUF;i++) {
buf[nbuf]=GlobalDosAlloc((long)FRAME_SIZE*NBLOCK);
bufseg[nbuf]=HIWORD(buf[nbuf]);
bufsel[nbuf]=LOWORD(buf[nbuf]);
pbuf[nbuf]=MK_FP(bufsel[nbuf],0);
if (!buf[nbuf]) {
if (nbuf<2) goto Allocerror;
break;
}
nbuf++;
}
return 1; // success
Allocerror:
for (i=0;i<nbuf;i++) if (buf[i]) GlobalDosFree(bufsel[i]);
if (cmdbuf) GlobalDosFree(cmdbufsel);
if (databuf) GlobalDosFree(databufsel);
if (prev_end) GlobalDosFree(prev_endsel);
return 0; // failure
}
// Free the real-mode buffers
int stopinterfacing(void)
{
int i;
for (i=0;i<nbuf;i++) GlobalDosFree(bufsel[i]);
GlobalDosFree(cmdbufsel);
GlobalDosFree(databufsel);
GlobalDosFree(prev_endsel);
return 1;
}
// Used for DPMI call
struct realregs {
DWORD edi,esi,ebp,resvd,ebx,edx,ecx,eax;
WORD flags,es,ds,fs,gs,ip,cs,sp,ss;
};
int dpmint86(int intnr,struct realregs *in,struct realregs *out)
{
union REGS inregs, outregs;
struct SREGS sregs;
struct realregs *r;
memset(&inregs,0,sizeof(union REGS)); // Just to be sure there is no junk...
memset(&outregs,0,sizeof(union REGS));
memset(&sregs,0,sizeof(struct SREGS));
inregs.x.ax=0x0300; // Simulate Real Mode Interrupt
inregs.x.bx=intnr; // interrupt #
inregs.x.di=FP_OFF(in); // address of struct regs
sregs.es=FP_SEG(in); // ,,
int86x(0x31,&inregs,&outregs,&sregs); // Call real mode INT via DPMI
if (outregs.x.cflag) {
mb("DPMI interface returned error");
return 1; // DPMI gave error? Exit.
}
r=MK_FP(sregs.es, outregs.x.di); // Where to find the output
if(r->flags & 1) {
mb("INT2F returned error");
return 1; // Interrupt in error? Test for carry, exit if 1
}
memcpy(out,r,sizeof(struct realregs)); // Get result registers back
return 0;
}
// Is MSCDEX installed? (No need for DPMI using this call)
int CheckMscdex(void)
{
union REGS reg;
reg.x.ax=0x1500; // MSCDEX - Get number of CDROM drives
reg.x.bx=0;
int86(0x2f,®,®);
if (!reg.x.bx) return 0; // Nr. of CDROM drives in bx
CDROM=reg.x.cx; // CX=first CDROM drive (A==0, B==1, etc)
return 1;
}
// Is Smartdrv (v4.1+ or compaitble cache) installed?
int CheckSmartdrv(void)
{
union REGS reg;
reg.x.ax=0x4A10;
reg.x.bx=0;
reg.x.cx=0xEBAB;
int86(0x2f,®,®);
if (reg.x.ax==0xBABE) return 1; else return 0;
}
// Does Smartdrv caches the CDROM ?
int CheckCDROMCached(void)
{
struct REGPACK r;
r.r_ax=0x4A10;
r.r_bx=3;
r.r_bp=CDROM;
r.r_dx=0;
intr(0x2f,&r);
if (r.r_ax!=0xBABE) {
mb("Smartdrv status call error");
return 0; // error in call
}
if (r.r_dx&0x0080) return 0; // BL bit 7 set? not cached!
return 1;
}
// Call CDROM device driver; command-buffer (at pcmdbuf) must be filled by caller
void CallDriver(void)
{
struct realregs r; // Prepare registers
memset(&r,0,sizeof(r));
r.eax=0x1510; // Function: CDROM device driver request
r.es=cmdbufseg; r.ebx=0; // Address of request structure
r.ecx=CDROM; // Drive number of CDROM
dpmint86(0x2f,&r,&r);
}
// Get CDROM disk information
int GetDiskInfo(void)
{
struct IOCTLI *pcmd=(struct IOCTLI *)pcmdbuf;
struct DiskInfo *pdi=(struct DiskInfo *)pdatabuf;
pcmd->req.len=26;
pcmd->req.unit=0;
pcmd->req.command=3;
pcmd->descriptor=0;
pcmd->address=MK_FP(databufseg,0);
pcmd->len=7;
pcmd->secnum=0;
pcmd->ptr=0;
pdi ->control=10;
CallDriver();
lowest =pdi->lowest;
highest=pdi->highest;
total_time=pdi->total;
return pcmd->req.status;
}
// Read one or more raw audio sectors
int ReadLong(DWORD loc, WORD secnum,WORD bufseg)
{
struct ReadL *pcmd=(struct ReadL *)pcmdbuf;
pcmd->req.len=sizeof(struct ReadL);
pcmd->req.unit=0;
pcmd->req.command=128;
pcmd->mode=0;
pcmd->address=MK_FP(bufseg,0);
pcmd->secnum=secnum;
pcmd->loc=loc;
pcmd->readmode=RAW_MODE;
pcmd->skip[0]=pcmd->skip[1]=0;
CallDriver();
return pcmd->req.status;
}
// Convert sector number to printable MM:SS:FF string, for durations.
char *Sector2MSF(DWORD sector)
{
static char s[20];
long min,sec,frames;
frames=sector%75;
sec=sector/75;
min=sec/60; sec=sec%60;
sprintf(s,"%02ldm %02lds %02ldf",min,sec,frames);
return s;
}
// Convert Sierra sector number to redbook
DWORD Sierra2Red(DWORD sierra)
{
DWORD min,sec,frame,loc;
sierra+=150; /// ????????????
frame=sierra%75;
sec=sierra/75;
min=sec/60; sec=sec%60;
loc=(BYTE)min;
loc<<=8; loc|=(BYTE)sec;
loc<<=8; loc|=(BYTE)frame;
return loc;
}
// Convert redbood time location to Sierra sector
DWORD Red2Sierra(DWORD loc)
{
BYTE min,sec,frame;
min=(loc>>16)&0xff;
sec=(loc>>8)&0xff;
frame=loc&0xff;
return (DWORD)min*75*60+(DWORD)sec*75+(DWORD)frame-150;
}
// Convert redbook time location to printable string
char *Red2MSF(DWORD loc)
{
static char s[20];
BYTE min,sec,frame;
min=(loc>>16)&0xff;
sec=(loc>>8)&0xff;
frame=loc&0xff;
sprintf(s,"%02um %02us %02uf",min,sec,frame);
return s;
}
// Convert redbook time location to minute, second, frame, and Sierra sector
void Red2MSFC(DWORD loc,WORD *min,WORD *sec,WORD *frame,DWORD *sector)
{
*frame=loc&0xff;
loc>>=8; *sec=loc&0xff;
loc>>=8; *min=loc&0xff;
*sector=((DWORD)*min)*75*60+((DWORD)*sec)*75+((DWORD)*frame)-150;
}
// Convert minute, second, frame to redbook timecode and Sierra sector
void MSF2Red(WORD min,WORD sec,WORD frame,DWORD *red,DWORD *sector)
{
DWORD loc=0;
*sector=(DWORD)min*75*60+(DWORD)sec*75+(DWORD)frame-150;
loc|=min; loc<<=8;
loc|=sec; loc<<=8;
loc|=frame;
*red=loc;
}
// Ask the CDROM device driver information about a track.
// Given the track number, find out at which sector it starts
int GetTrackInfo(int track,DWORD *loc)
{
struct IOCTLI *pcmd=(struct IOCTLI *)pcmdbuf;
struct TrackInfo *pbuf=(struct TrackInfo *)pdatabuf;
pcmd->req.len=26;
pcmd->req.unit=0;
pcmd->req.command=3;
pcmd->descriptor=0;
pcmd->address=MK_FP(databufseg,0);
pcmd->len=7;
pcmd->secnum=0;
pcmd->ptr=0;
pbuf->control=11;
pbuf->track=track;
CallDriver();
*loc=pbuf->loc;
return pcmd->req.status;
}
// Stop playing of current audio piece
int StopAudio(void)
{
struct ReqHdr *pcmd=(struct ReqHdr *)pcmdbuf;
pcmd->len=13;
pcmd->unit=0;
pcmd->command=133;
CallDriver();
return pcmd->status;
}
// Play an piece of audio
int PlayAudio(DWORD loc, DWORD num)
{
struct PlayReq *pcmd=(struct PlayReq *)pcmdbuf;
pcmd->req.len=22;
pcmd->req.unit=0;
pcmd->req.command=132;
pcmd->mode=1;
pcmd->loc=loc;
pcmd->secnum=num;
CallDriver();
return pcmd->req.status;
}