(**************************************************** ******* OBJECT SOFTWARE DESIGN ******* ******* Paul Kuijer ****** ****************************************************) unit OSD_CD; interface type CD_Record = record Status : Word; DrvChar : Char; DrvNo : Byte; HSG_RB : Byte; Sector : LongInt; VolInfo : array[1..8] of Byte; DevPar : LongInt; RawMode : Boolean; SecSize : Word; VolSize : LongInt; MedChg : Byte; LoAuTr : Byte; HiAuTr : Byte; EndAdr : LongInt; TrkNo : Byte; TrkAdr : LongInt; TrkInf : Byte; CntAdr, CTrk, CIndx, CMin, CSec, CFrm, CZero, CAMin, CASec, CAFrm : Byte; QFrm, QTrfs, QCnt : LongInt; UCtrl : Byte; Upn : array[1..7] of Byte; UZero : Byte; UFrm : Byte; end; OneTrack = record Title : string[20]; RunMin, RunSec : Byte; Start : LongInt; end; VolTable = record DiskName : string[20]; UAN_Code : string[13]; TrackCnt : Byte; Titles : array[1..99] of OneTrack; end; TrkInfo = record Nummer : Byte; Start : LongInt; Cntrl2 : Byte; end; var CD : CD_Record; CD_Avail : Boolean; VtoC : VolTable; CD_RedPos : string; CD_HSGPos : string; function CD_Reset : Boolean; function CD_HeadAdr : Boolean; function CD_Position : Boolean; function CD_MediaChanged : Boolean; function CD_Open : Boolean; function CD_Close : Boolean; function CD_Eject : Boolean; function CD_Play( no:Byte; len : Integer ) : Boolean; function CD_Stop : Boolean; function CD_Resume : Boolean; function CD_SetVol : Boolean; function CD_GetVol : Boolean; procedure CD_Info; procedure CD_TrackInfo( Nr:Byte; VAR T : TrkInfo ); function Red2Time( VAR Inf : TrkInfo ) : Word; implementation uses Dos; const IOCtlRead = $4402; IOCtlWrite = $4403; DevDrvReq = $1510; All:LongInt = $0F00; type IOCtlBlk = array[0..200] of Byte; var R : Registers; H : Text; Handle : Word; Old_Exit : Pointer; CtlBlk : IOCtlBlk; Tracks : Array[0..100] of TrkInfo; procedure CD_Exit; begin if Old_Exit <> NIL then ExitProc := Old_Exit; {$I-} Close( H ); if IOResult = 0 then; {$I+} end; function CD_Init : Boolean; begin FillChar( CD, SizeOf( CD ), 0 ); With R do begin AX := $1500; BX := $0000; CX := $0000; Intr( $2F, R ); CD_Init := (BX > 0); if BX > 0 then begin CD.DrvChar := Char( CL + Byte( 'A' ) ); CD.DrvNo := CL; if CD_HeadAdr then if CD_GetVol then; end else CD.DrvChar := '?'; end; end; procedure CD_TrackInfo( Nr : Byte; VAR T : TrkInfo ); begin T := Tracks[nr]; end; function OpenCDHandle : Word; const Name : string[8] = 'WP_CDROM'; begin Assign( H, Name ); (*$I-*) Reset(H); (*$I+*) if IOResult = 0 then begin Handle := TextRec(H).Handle; Old_Exit := ExitProc; ExitProc := @CD_Exit; end else Handle := 0; OpenCDHandle := Handle; end; procedure CloseCDHandle; begin if TextRec(H).Mode <> fmClosed then ExitProc := Old_Exit; Old_Exit := NIL; {$I-} Close( H ); if IOResult = 0 then; {$I+} end; function Red2HSG( VAR Inf:TrkInfo ) : LongInt; var l : LongInt; begin l := LongInt(( Inf.Start shr 16 ) and $FF ) * 4500; l := l + LongInt(( Inf.Start shr 8 ) and $FF ) *75; l := l + LongInt( Inf.Start ) and $FF; Red2HSG := l-2; end; function Red2Time( VAR inf:TrkInfo ) : Word; begin Red2Time := ((Inf.Start shr 24 ) and $FF ) shl 8 +((Inf.Start shr 16 ) and $FF ); end; function HSG2Red(L:LongInt) : LongInt; begin end; function CD_IOCtl( Func : Word ) : Boolean; begin with R do begin AX := Func; BX := OpenCDHandle; CX := 129; DS := DSeg; ES := DS; DX := Ofs(CtlBlk); MsDos( R ); CD.Status := AX; CD_IOCtl := (Flags and FCARRY ) = 0; CloseCDHandle; end; end; function CD_Reset : Boolean; begin CtlBlk[0] := 2; CD_Reset := CD_IOCtl( IOCtlWrite ); end; function DieTuer( AufZu:Byte ) : Boolean; begin CtlBlk[0] := 1; CtlBlk[1] := AufZu; DieTuer := CD_IOCtl( IOCtlWrite ); end; function CD_Open : Boolean; const Auf = 0; begin CD_Open := DieTuer( 0 ); end; function CD_Close : Boolean; const Zu = 1; begin CD_Close := DieTuer( Zu ); end; function CD_Eject : Boolean; begin CtlBlk[0] := 0; CD_Eject := CD_IOCtl( IOCtlWrite ); end; function CD_Play( no:Byte; len:Integer) : Boolean; begin FillChar( CtlBlk, SizeOf(CtlBlk), 0 ); CtlBlk[0] := 22; CtlBlk[1] := 0; CtlBlk[2] := $84; CtlBlk[3] := 0; CtlBlk[4] := 0; CtlBlk[5] := 0; CtlBlk[13] := CD.HSG_RB; CD.Sector := VtoC.Titles[no].Start; Move( CD.Sector, CtlBlk[14], 4 ); if len = -1 then All := $FFFF else All := len; Move( All, CtlBlk[18], 4 ); asm mov ax, $1510 push ds pop es xor cx, cx mov cl, CD.DrvNo mov bx, offset CtlBlk int $2F end; CD.Status := CtlBlk[3] or CtlBlk[4] shl 8; CD_Play := CD.Status and $8000 = 0; end; function CD_VtoC : Boolean; var i : Byte; l : LongInt; begin FillChar( Tracks, SizeOf(Tracks), 0 ); CtlBlk[0] := 10; CD_IOCtl( IOCtlRead ); Move( CtlBlk[1], CD.LoAuTr, 6 ); i := CD.HiAuTr+1; Move( CtlBlk[3], Tracks[i], 4 ); Tracks[i].Start := Red2HSG(Tracks[i]); for i := CD.LoAuTr to CD.HiAuTr do begin FillChar( CtlBlk, SizeOf(CtlBlk), 0 ); CtlBlk[0] := 11; CtlBlk[1] := i; CD_IOCtl( IOCtlRead ); Move( CtlBlk[1], Tracks[i], 6 ); end; with VtoC do begin DiskName := ''; UAN_Code := ''; TrackCnt := CD.HiAuTr; for i := CD.LoAuTr to CD.HiAuTr do begin with Titles[i] do begin L := longInt((Tracks[i+1].Start shr 16) and $FF) * 60 + (Tracks[i+1].Start shr 8) and $FF - ( LongInt((Tracks[i].Start shr 16) and $FF) * 60 + (Tracks[i].Start shr 8) and $FF); Title := '???'; RunMin := l Div 60; RunSec := l - RunMin * 60; Start := Red2HSG(Tracks[i]); end; end; end; end; function CD_Stop : Boolean; begin FillChar( CtlBlk, SizeOf(CtlBlk), 0 ); CtlBlk[0] := 5; CtlBlk[1] := 0; CtlBlk[2] := $85; CtlBlk[3] := 0; CtlBlk[4] := 0; CtlBlk[5] := 0; asm mov ax, $1510 push ds pop es xor cx, cx mov cl, CD.DrvNo mov bx, offset CtlBlk int $2F end; CD.Status := CtlBlk[3] or CtlBlk[4] shl 8; CD_Stop := CD.Status and $8000 = 0; end; function CD_Resume : Boolean; begin CtlBlk[0] := 3; CtlBlk[1] := 0; CtlBlk[2] := $88; CtlBlk[3] := 0; CtlBlk[4] := 0; asm mov ax, Seg @Data mov es, ax mov ax, DevDrvReq lea bx, CtlBlk int $2F end; CD.Status := CtlBlk[3] or CtlBlk[4] shl 8; CD_Resume := CD.Status and $8000 = 0; end; function CD_GetVol : Boolean; begin CtlBlk[0] := 4; CD_GetVol := CD_IOCtl( IOCtlRead ); if ((R.Flags and FCARRY)=0) then Move( CtlBlk[1], CD.VolInfo, 8 ) else FillChar( CD.VolInfo, 8, 0 ); end; function CD_SetVol : Boolean; begin CtlBlk[0] := 3; CD_SetVol := Cd_IOCtl( IOCtlWrite ); end; function CD_HeadAdr : Boolean; var l : LongInt; s : string; begin FillChar( CtlBlk, SizeOf(CtlBlk), 0 ); CtlBlk[0] := 1; CtlBlk[1] := 1; CD_HeadAdr := CD_IOCtl( IOCtlRead ); if (( R.Flags and FCARRY) = 0) then begin Move( CtlBlk[2], l, 4 ); if CtlBlk[4] = 1 then begin STR( CtlBlk[4]:2, s ); STR( CtlBlk[3]:2, s ); CD.Sector := LongInt( CtlBlk[4])*4500 + LongInt( CtlBlk[3])*75 + LongInt( CtlBlk[2]) - 150; end else begin CD.Sector := l; STR( L:0, CD_HSGPos ); end; end else FillChar( CD.Sector, 4, 0 ); end; function CD_Position : Boolean; var l : longint; begin CtlBlk[0] := 12; CD_Position:= CD_IOCtl( IOCtlRead ); Move( CtlBlk[1], CD.CntAdr, 10 ); end; procedure CD_GetUAN; begin CtlBlk[0] := 14; if CD_IOCtl(IOCtlRead ) then Move( CtlBlk[1], CD.UCtrl, 10 ); end; function CD_MediaChanged : Boolean; begin CtlBlk[0] := 9; if CD_IOCtl(IOCtlRead ) then Move( CtlBlk[1], CD.MedChg, 1 ); CD_MediaChanged := CD.MedChg <> 1; end; procedure CD_Info; begin if CD_HeadAdr then; CtlBlk[0] := 6; if CD_IOCtl( IOCtlRead ) then Move( CtlBlk[1], Cd.DevPar, 4 ); CtlBlk[0] := 7; if CD_IOCtl( IOCtlRead ) then Move( CtlBlk[1], Cd.RawMode, 3 ); CtlBlk[0] := 8; if CD_IOCtl( IOCtlRead ) then Move( CtlBlk[1], Cd.VolSize, 4 ); CtlBlk[0] := 12; if CD_IOCtl( IOCtlRead ) then Move( CtlBlk[1], Cd.CntAdr, 10 ); CtlBlk[0] := 11; if CD_IOCtl( IOCtlRead) then Move( CtlBlk[1], Cd.TrkNo, 6 ); CD_VtoC; end; begin CD_Avail := CD_Init; if CD_Avail then CD_Info; end.