2000 /* DAGRABX grabs 16 bit 44.1 KHz CD Audio digitally to a file */ /* This version uses XMS as an intermediate buffer to avoid */ /* the "glitches" that otherwise occur */ #include #include #include #include #include #include #include #define FALSE 0 #define TRUE 1 int CDRomLoaded,CDRomDrive; struct EMMMoveStruct moverec; unsigned int xmshandle, xmsfree,xmstot; struct ReadLongStruc ReadLongBlock; struct IOCTLStruc IOCTLBlock; struct DiskInfoStruc DiskInfoBlock; struct TrackInfoStruc TrackInfoBlock[100]; unsigned long Red2HSG(unsigned long RedValue); int *buffer; main(int argc, char *argv[]) { struct dfree diskfree; long avail; int drive; unsigned long ssec,esec,ssec2,nsec,nsec2; unsigned int secstograb,secstowrite,i,j,k,offs; unsigned char filename[80]; FILE *outfp; int Track,StartMin,StartSec,EndMin,EndSec,StartFrame,EndFrame; float TempFloat; char LocalBuffer[132]; char c = ':'; if(argc > 3) { if (!CheckCD2F()){ printf("MSCDEX NOT LOADED\n"); exit(1); } if(!XMS_Setup()) { printf("No XMS handler installed!\n"); exit(1); } while(GetDiskInfo() != STAT_DONE); for(i = DiskInfoBlock.LowTrack; i <= DiskInfoBlock.HighTrack; i++) GetTrackInfo(i); Track = atoi(argv[1]); if( (Track < 1) || (Track > DiskInfoBlock.HighTrack)) { printf("Error: Track must be between %d and %d\n",DiskInfoBlock.LowTrack,DiskInfoBlock.HighTrack); errexit(); } StartMin = 0; StartSec = 0; StartFrame = 0; EndMin = 0; EndSec = 0; EndFrame = 0; strcpy(LocalBuffer,argv[2]); StartMin = atoi(strtok(LocalBuffer,":")); StartSec = atoi(strtok(NULL,":")); StartFrame = atoi(&LocalBuffer[strrchr(argv[2],c)+1-LocalBuffer]); strcpy(LocalBuffer,argv[3]); EndMin = atoi(strtok(LocalBuffer,":")); EndSec = atoi(strtok(NULL,":")); EndFrame = atoi(&LocalBuffer[strrchr(argv[3],c)+1-LocalBuffer]); ssec = Red2HSG(TrackInfoBlock[Track].Startpoint)+(StartMin*60L+((long)StartSec))*75L+((long)StartFrame) -150L; esec = Red2HSG(TrackInfoBlock[Track].Startpoint)+(EndMin*60L+((long)EndSec))*75L+((long)EndFrame) -150L; nsec = esec-ssec; nsec2 = nsec; ssec2 = ssec; printf("Start sector : %ld\n",ssec); printf("End sector : %ld\n",esec); printf("Number of sectors: %ld\n",nsec); printf("CDDA data size : %ld bytes\n",nsec*2352l); if(argc > 4) { if((buffer = malloc(59000)) == NULL){ printf("Malloc error!\n"); errexit(); } XMS_FreeMem(&xmsfree,&xmstot); XMS_AllocEMB(xmsfree,&xmshandle); if(xmsfree < (unsigned int)(nsec*2352l/1024l)) { printf("Not enough XMS memory!\n"); errexit(); } drive = getdisk(); getdfree(drive+1,&diskfree); avail = (long) diskfree.df_avail * (long) diskfree.df_bsec * (long) diskfree.df_sclus; if(avail < (nsec*2352l)) { printf("Not enough disk space!\n"); errexit(); } strcpy(filename,argv[4]); outfp = fopen(filename,"wb"); moverec.TLen = 58800l; /* 2352 bytes * 25 sectors */ moverec.SHand = 0; moverec.SOff = (unsigned long)buffer; moverec.DHand = xmshandle; moverec.DOff = 0l; do{ secstograb = 25; if(nsec2 < 25l) { secstograb = (unsigned int)nsec2; moverec.TLen = (unsigned long)(secstograb*2352); } ReadLong(ssec2,secstograb); while(ReadLongBlock.ReqHdr.Status & STAT_HAS_AN_ERROR) ReadLong(ssec2,secstograb); XMS_MoveEMB(&moverec); ssec2+=25l; nsec2-=25l; moverec.DOff += 58800l; } while ((long)nsec2 > 0l); moverec.TLen = 58800; moverec.SHand = xmshandle; moverec.SOff = 0l; moverec.DHand = 0; moverec.DOff = (unsigned long)buffer; do { secstowrite = 25; if(nsec < 25l) { secstowrite = (unsigned int)nsec; moverec.TLen = (unsigned long)(secstowrite*2352); } XMS_MoveEMB(&moverec); fwrite(buffer,2,1176*secstowrite,outfp); moverec.SOff += 58800l; nsec -= 25l; } while ((long)nsec > 0l); fclose(outfp); free(buffer); XMS_FreeEMB(xmshandle); } else { printf("\nPlaying only...\n"); Play(ssec,nsec); } } else { printf("DAGRAB CD-DA Audio grabber v0.1\n"); printf("usage: dagrab []\n"); } } CheckCD2F() { union REGS regs; regs.x.ax = INIT_MP_INT; int86(MULTIPLEX_INT,®s,®s); CDRomLoaded = regs.x.bx; CDRomDrive = regs.x.cx; } GetDiskInfo() { union REGS regs; struct SREGS sregs; DiskInfoBlock.CntrlCode = GET_AUDIO_DISKINFO; IOCTLBlock.ReqHdr.ParamLength = 13; IOCTLBlock.ReqHdr.SubUnit = 0; IOCTLBlock.ReqHdr.CommandCode = READ_IOCTL_COMMAND; IOCTLBlock.ReqHdr.Status = 0; IOCTLBlock.Meddescr = 0; IOCTLBlock.Transfaddr = (unsigned long)&DiskInfoBlock; IOCTLBlock.Numbytes = 7; IOCTLBlock.Startsec = 0; IOCTLBlock.volID = 0; regs.x.ax = CDREQ_MP_INT; regs.x.bx = FP_OFF(&IOCTLBlock); regs.x.cx = CDRomDrive; sregs.es = FP_SEG(&IOCTLBlock); int86x(MULTIPLEX_INT,®s,®s,&sregs); return(IOCTLBlock.ReqHdr.Status); } GetTrackInfo(unsigned char trk) { union REGS regs; struct SREGS sregs; TrackInfoBlock[trk].CntrlCode = GET_AUDIO_TRACKINFO; TrackInfoBlock[trk].Tracknum = trk; IOCTLBlock.ReqHdr.ParamLength = 13; IOCTLBlock.ReqHdr.SubUnit = 0; IOCTLBlock.ReqHdr.CommandCode = READ_IOCTL_COMMAND; IOCTLBlock.ReqHdr.Status = 0; IOCTLBlock.Meddescr = 0; IOCTLBlock.Transfaddr = (unsigned long)&(TrackInfoBlock[trk]); IOCTLBlock.Numbytes = 7; IOCTLBlock.Startsec = 0; IOCTLBlock.volID = 0; regs.x.ax = CDREQ_MP_INT; regs.x.bx = FP_OFF(&IOCTLBlock); regs.x.cx = CDRomDrive; sregs.es = FP_SEG(&IOCTLBlock); int86x(MULTIPLEX_INT,®s,®s,&sregs); return(IOCTLBlock.ReqHdr.Status); } Play(unsigned long SSec,unsigned long numsecs) { union REGS regs; struct SREGS sregs; struct PlayStruc PlayBlock; struct QInfoStruc QInfoBlock; PlayBlock.ReqHdr.ParamLength = 13; PlayBlock.ReqHdr.SubUnit = 0; PlayBlock.ReqHdr.CommandCode = CD_PLAY_AUDIO; PlayBlock.ReqHdr.Status = 0; PlayBlock.AddressMode = ADDR_HSG; PlayBlock.Startsec = SSec; PlayBlock.Numsec = numsecs; regs.x.ax = CDREQ_MP_INT; regs.x.bx = FP_OFF(&PlayBlock); regs.x.cx = CDRomDrive; sregs.es = FP_SEG(&PlayBlock); int86x(MULTIPLEX_INT,®s,®s,&sregs); do { QInfoBlock.CntrlCode = GET_QCHAN_INFO; IOCTLBlock.ReqHdr.ParamLength = 13; IOCTLBlock.ReqHdr.SubUnit = 0; IOCTLBlock.ReqHdr.CommandCode = READ_IOCTL_COMMAND; IOCTLBlock.ReqHdr.Status = 0; IOCTLBlock.Meddescr = 0; IOCTLBlock.Transfaddr = (unsigned long)&QInfoBlock; IOCTLBlock.Numbytes = 11; IOCTLBlock.Startsec = 0; IOCTLBlock.volID = 0; regs.x.ax = CDREQ_MP_INT; regs.x.bx = FP_OFF(&IOCTLBlock); regs.x.cx = CDRomDrive; sregs.es = FP_SEG(&IOCTLBlock); int86x(MULTIPLEX_INT,®s,®s,&sregs); if(kbhit()){ getch(); Stop(); break; } } while (IOCTLBlock.ReqHdr.Status & STAT_BUSY); } Stop() { union REGS regs; struct SREGS sregs; struct ReqHdrStruc StopBlock; StopBlock.ParamLength = 13; StopBlock.SubUnit = 0; StopBlock.CommandCode = CD_STOP_AUDIO; StopBlock.Status = 0; regs.x.ax = CDREQ_MP_INT; regs.x.bx = FP_OFF(&StopBlock); regs.x.cx = CDRomDrive; sregs.es = FP_SEG(&StopBlock); int86x(MULTIPLEX_INT,®s,®s,&sregs); return(StopBlock.Status); } ReadLong(unsigned long SSec,unsigned int numsecs) { union REGS regs; struct SREGS sregs; ReadLongBlock.ReqHdr.ParamLength = 13; ReadLongBlock.ReqHdr.SubUnit = 0; ReadLongBlock.ReqHdr.CommandCode = CD_READ_LONG; ReadLongBlock.ReqHdr.Status = 0; ReadLongBlock.AddressMode = ADDR_HSG; ReadLongBlock.Transfaddr = (int far*)buffer; ReadLongBlock.Numsec = numsecs; ReadLongBlock.Startsec = SSec; ReadLongBlock.Readmode = RAW; ReadLo 27e ngBlock.Interlsiz = 0; ReadLongBlock.Interlskip = 0; regs.x.ax = CDREQ_MP_INT; regs.x.bx = FP_OFF(&ReadLongBlock); regs.x.cx = CDRomDrive; sregs.es = FP_SEG(&ReadLongBlock); int86x(MULTIPLEX_INT,®s,®s,&sregs); return(ReadLongBlock.ReqHdr.Status); } unsigned long Red2HSG(unsigned long RedValue) { unsigned long Mins; unsigned long Secs; unsigned long PlusFrames; PlusFrames = RedValue & 0x000000ffL; Secs = ((RedValue & 0x0000ff00L) >> 8); Mins = ((RedValue & 0x00ff0000L) >> 16); return((Mins*60+Secs)*75+PlusFrames); } errexit() { XMS_FreeEMB(xmshandle); exit(1); } . 0