'===========================================================================
' Subject: CD-ROM DRIVE AND DISC CHECK        Date: 07-21-97 (00:09)       
'  Author: Mike Ginger                        Code: QB, PDS                
'  Origin: FidoNet QUIK_BAS Echo            Packet: DISK.ABC
'===========================================================================
' > Recently I found some QBX 7.1 code for interfacing with MSCDEX. It seemed
' > to be really good stuff, but unfortunately I'm unable to convert it to
' > QuickBasic. Is there somebody who can do this for me, and all those folks
' > out here who need a good CD-player?

' And here's how far I've got with converting/fixing/improving this
' code (this code should work "as is" with QuickBASIC):

    ' $DYNAMIC
    DEFINT A-Z
    ' $INCLUDE: 'QB.BI'
    DECLARE SUB GetAudioInfo (Drive$)
    DECLARE SUB GetCDInfo (Drive$)
    DECLARE SUB GetDiskInfo (Drive$)
    DECLARE SUB LowHigh (Register, Low!, High!)

    DIM SHARED InRegs AS RegTypeX
    DIM SHARED OutRegs AS RegTypeX
    CONST FALSE = 0
    CONST TRUE = NOT FALSE
    TYPE Music
	StartTrack AS INTEGER
	LastTrack  AS INTEGER
	TotMin     AS INTEGER
	TotSec     AS INTEGER
	TotFrames  AS INTEGER
    END TYPE
    DIM SHARED CdInfo AS Music
    TYPE CDROM
	Length     AS STRING * 1 ' length of the request header
	SubUnit    AS STRING * 1 ' subunit of the driver (always 0?)
	Command    AS STRING * 1 ' command for the driver
	Status     AS INTEGER    ' status returned by the driver
	Reserved   AS STRING * 8 ' reserved stuff, for dos
	MediaDesc  AS STRING * 1 ' ???
	BufOffs    AS INTEGER    ' offset for the buffer
	BufSeg     AS INTEGER    ' seg for the buffer, these two
		     ' fields make a pointer
	BytesTrans AS STRING * 1 ' bytes to transfer in the buffer
	StartSect  AS INTEGER    ' starting sector (not used)
	POINOFFS   AS INTEGER    ' offset ???
	POINSEG    AS INTEGER    ' segment ???
    END TYPE
    DIM SHARED IOBlock AS CDROM
    DIM SHARED Sector AS STRING * 2048
    DIM SHARED DriveBytes(200) AS STRING * 1 ' buffer for info on the cd
    ' --------------------------------------------------------------------
    CLS
CheckCDROMs:                    ' cd-rom drive check
    IsCDROM = FALSE             ' boolean: is drivenr a cd-rom ?
    CDROMs$ = ""
    FOR DRIVENR = 3 TO 26       ' c: t/m z: only harddisks
	Drive$ = CHR$(DRIVENR + 64) + ":"
	InRegs.ax = &H150B      ' mscdex driver check
	InRegs.bx = &H0
	InRegs.cx = DRIVENR - 1
	CALL INTERRUPTX(&H2F, InRegs, OutRegs)
	IF OutRegs.bx = &HADAD THEN
	    IsCDROM = TRUE
	    IF OutRegs.ax <> &H0 THEN  ' drive is supported
		CDROMs$ = CDROMs$ + CHR$(DRIVENR + 64)
	    END IF
	END IF
    NEXT DRIVENR
    IF IsCDROM THEN
	LOCATE 8, 25
	PRINT "Found CD drives: "; CDROMs$;
	InRegs.ax = &H150C      ' ask mscdex.exe version
	CALL INTERRUPTX(&H2F, InRegs, OutRegs)
	CALL LowHigh(OutRegs.bx, BL!, BH!)
	LOCATE 7, 25
	PRINT USING "MSCDEX version    :##.##"; BH! + (BL! / 100);
	InRegs.ax = &H1500      ' installation check cd-roms
	InRegs.bx = &H0
	CALL INTERRUPTX(&H2F, InRegs, OutRegs)
	IF OutRegs.bx > 0 THEN
	    AANTAL = OutRegs.bx
	END IF
	LOCATE 10, 7: PRINT "CD drive       :";
	LOCATE 11, 7: PRINT "CD type        :";
	LOCATE 12, 7: PRINT "CD sort        :";
	LOCATE 13, 7: PRINT "CD label       :";
	LOCATE 14, 7: PRINT "Creation date  :";
	LOCATE 15, 7: PRINT "Creation time  :";
	LOCATE 16, 7: PRINT "Used space     :";
	LOCATE 17, 7: PRINT "# music titles :";
	LOCATE 18, 7: PRINT "Music time     :";
	LOCATE 19, 7: PRINT "Total Frames   :";
	KOLOM = 25              ' column
	CALL GetCDInfo(MID$(CDROMs$, 1, 1) + ":")
	IF AANTAL > 1 THEN      ' if more than 1 cdrom
	    KOLOM = 50          ' second column
	    CALL GetCDInfo(MID$(CDROMs$, 2, 1) + ":")
	END IF
    ELSE
	LOCATE 12, 26: PRINT "No CD drives found!";
	LOCATE 14, 26: PRINT "MSCDEX not installed?";
    END IF
    END

    ' --------------------------------------------------------------------
    SUB GetAudioInfo (Drive$)
    SHARED KOLOM
    IOBlock.Length = CHR$(26)
    IOBlock.SubUnit = CHR$(0)
    IOBlock.Command = CHR$(3)
    IOBlock.Status = 0
    IOBlock.BytesTrans = CHR$(7)
    DriveBytes(1) = CHR$(10)
    IOBlock.BufOffs = VARPTR(DriveBytes(1))' permits the driver to fill
    IOBlock.BufSeg = VARSEG(DriveBytes(1))' the buffer with some info
    InRegs.ax = &H1510              ' cd-rom driver dispatch function
    InRegs.cx = ASC(LEFT$(Drive$, 1)) - 65' cd-drive
    InRegs.es = VARSEG(IOBlock)     ' segment of the ioblock
    InRegs.bx = VARPTR(IOBlock)     ' offset of the ioblock
    CALL INTERRUPTX(&H2F, InRegs, InRegs)
    CdInfo.StartTrack = ASC(DriveBytes(2))
    CdInfo.LastTrack = ASC(DriveBytes(3))
    CdInfo.TotMin = ASC(DriveBytes(6))
    CdInfo.TotSec = ASC(DriveBytes(5)) - 2' necessary because all cd's
				       ' start at the 2nd second
    CdInfo.TotFrames = ASC(DriveBytes(4))
    IF CdInfo.StartTrack = 1 AND CdInfo.LastTrack > 1 AND CdInfo.TotMin > 0 AND CdInfo.TotSec > -2 THEN
	LOCATE 11, KOLOM: PRINT "AUDIO CD";
	LOCATE 12, KOLOM: PRINT "AUDIO CD";
	LOCATE 17, KOLOM: PRINT STR$(CdInfo.LastTrack);
    LOCATE 18, KOLOM: PRINT STR$(CdInfo.TotMin) + " min." + STR$(CdInfo.TotSec) + " sec.";
	LOCATE 19, KOLOM: PRINT STR$(CdInfo.TotFrames);
    END IF
    END SUB

    ' --------------------------------------------------------------------
    SUB GetCDInfo (Drive$)      ' get first sector
    SHARED KOLOM
    LOCATE 10, KOLOM: PRINT Drive$;
    MULTI = FALSE               ' multi-session cd-rom ?
    GEBRUIKT# = 0#              ' used space
    LABEL$ = "Geen label"
    CDSOORT$ = "Not a ISO-9660 CD-ROM"
    OK = FALSE                  ' ok to print
    Sector = STRING$(2048, 32)
    InRegs.ax = &H1508          ' mscdex : absolute disc read
    InRegs.es = VARSEG(Sector)  ' segment
    InRegs.bx = VARPTR(Sector)  ' offset
    InRegs.cx = ASC(LEFT$(Drive$, 1)) - 65
    InRegs.si = 0               ' si:di = start sector
    InRegs.di = 16              ' sectornumber
    InRegs.dx = 1               ' dx = count of sectors to read
    CALL INTERRUPTX(&H2F, InRegs, OutRegs)
    IF (OutRegs.flags AND 1) = 0 THEN
	IF MID$(Sector, 2, 5) = "CD001" THEN
	    IF MID$(Sector, 1, 1) = CHR$(1) THEN
		IF MID$(Sector, 1025, 8) = "CD-XA001" THEN
		    CDSOORT$ = "ISO-9660 CD-ROM-XA"
		ELSE
		    CDSOORT$ = "ISO-9660 CD-ROM"
		END IF
		OK = TRUE
	    END IF
	    IF MID$(Sector, 1, 1) = CHR$(2) THEN
		MULTI = TRUE' multi-session cd-rom
	    END IF
	END IF
    ELSE
	LOCATE 11, KOLOM: PRINT "No CD!";
	LOCATE 12, KOLOM: PRINT "No CD!";
	' CALL GetAudioInfo(Drive$)
    END IF

    CALL GetAudioInfo(Drive$)

     IF OK THEN
	IF MULTI THEN
	    LOCATE 11, KOLOM: PRINT "Multi session"
	ELSE
	    LOCATE 11, KOLOM: PRINT "Single session"
	END IF
	LOCATE 12, KOLOM: PRINT CDSOORT$;
	LABEL$ = MID$(Sector, 41, 32)
	LOCATE 13, KOLOM: PRINT LEFT$(LABEL$, 15);
    TXT$ = MID$(Sector, 814, 4) + "-" + MID$(Sector, 818, 2) + "-" + MID$(Sector, 820, 2)
	LOCATE 14, KOLOM: PRINT TXT$;
	TXT$ = MID$(Sector, 822, 2) + ":" + MID$(Sector, 824, 2)
	LOCATE 15, KOLOM: PRINT TXT$;
	GEBRUIKT# = CVL(MID$(Sector, 81, 4)) * CVI(MID$(Sector, 129, 2))
	LOCATE 16, KOLOM: PRINT USING "###,###,###"; GEBRUIKT#;

     END IF
    END SUB

' -------------------------------------------------------------------
 SUB LowHigh (Register, Low!, High!)
    Low! = Register AND 255
    High! = Register \ 255
 END SUB
