(****************************************************
******* 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.
(
geocities.com/~franzglaser)