Last active
August 31, 2020 12:23
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
uses crt,playcd; | |
var cd:record | |
danz,drive:word; | |
mintrk,maxtrk,anztrk:byte; | |
traks:array[0..63] of longint; | |
len:array[0..63] of longint; | |
ttyp:array[0..63] of byte; | |
end; | |
i:integer; m,s:byte; | |
zeit:longint; | |
c:char; | |
function InitCD:byte; | |
var status:longint; | |
l:longint; i:integer; | |
begin | |
cd.danz:=DriveAnz(cd.drive); | |
if cd.danz=0 then | |
begin | |
InitCd:=1; {MSCDEX nicht installiert} | |
exit; | |
end; | |
status:=DeviceState(cd.drive) and $a11; | |
if status<>$210 then begin Initcd:=2; exit; end; {CD-Fehler ignorieren !} | |
GetCDInfo(cd.drive,cd.mintrk,cd.maxtrk,l); | |
l:=RedBook2HSG(cd.drive,l); | |
cd.anztrk:=cd.maxtrk-cd.mintrk+1; | |
for i:=cd.mintrk to cd.maxtrk do | |
begin | |
cd.traks[i]:=Track2Sector(cd.drive,i); | |
cd.ttyp[i]:=tracktype; | |
cd.traks[i]:=Redbook2HSG(cd.drive,cd.traks[i]); | |
end; | |
if cd.mintrk=1 then cd.traks[1]:=0; | |
for i:=cd.mintrk to cd.maxtrk do | |
begin | |
if i=cd.maxtrk then cd.len[i]:=GetVolSize(cd.drive)-cd.traks[i] else | |
cd.len[i]:=cd.traks[i+1]-cd.traks[i]; | |
end; | |
c:=readkey; | |
{ cd.drive:=4;} | |
end; | |
function bin(a:word):string; | |
var s:string; i:longint; | |
begin | |
s:=''; | |
for i:=0 to 15 do if (a and (1 shl i))<>0 then s:=s+'1' else | |
s:=s+'0'; | |
bin:=s; | |
end; | |
procedure DriveInfo(drive:word); | |
{ devstat_DoorOpen EQU 0001h ; TÅr offen ? | |
devstat_DoorNotBolted EQU 0002h ; TÅr nicht verriegelt ? | |
devstat_ReadAndWrite EQU 0008h ; Schreiben mîglich ? | |
devstat_DataAudioVideo EQU 0010h ; Audio-CD ? | |
devstat_AudioManipulation EQU 0100h ; Audiomanipulation ? | |
devstat_HSGAndRedBook EQU 0200h ; RedBook-Modus erlaubt ? | |
devstat_NoCDInDrive EQU 0800h ; Keine CD im Laufwerk ?} | |
const stat0:array[0..6] of string=('door open', | |
'door not bolted', | |
'cd-writer', | |
'audioplay possible','audiomanipulation', | |
'redbook possible','no cd in drive'); | |
stat1:array[0..6] of string=('door closed','door bolted','read only', | |
'data cd in drive','no audiomanipulation', | |
'HSG mode only','cd in drive'); | |
stat2:array[0..6] of longint=(1,2,8,$10,$100,$200,$800); | |
var status:longint; i:integer; | |
begin | |
writeln('drive letter : ',chr(65+drive)); | |
status:=DeviceState(drive); | |
for i:=0 to 6 do if (status and stat2[i])<>0 then writeln(stat0[i]) else | |
writeln(stat1[i]); | |
end; | |
begin | |
clrscr; | |
cd.danz:=DriveAnz(cd.drive); | |
{ cd.drive:=3;} | |
zeit:=DeviceState(cd.drive); | |
writeln('Device State :',bin(hi(zeit)),' ',bin(lo(zeit))); | |
DriveInfo(cd.drive); | |
c:=readkey; | |
i:=initcd; i:=0; | |
case i of | |
1 : begin | |
writeln('MSCDEX not installed !!!'); | |
halt; | |
end; | |
2 : begin | |
writeln('Keine CD eingelegt !'); | |
halt; | |
end; | |
end; | |
writeln; | |
writeln('Tracks:'); | |
for i:=cd.mintrk to cd.maxtrk do | |
begin | |
Sect2Time(cd.len[i],m,s); | |
writeln(i:3,' - ',cd.len[i]:9,' Sektoren',' - Offset ',cd.traks[i]:9,' ',m:2,':',s:2,' Typ:',cd.ttyp[i]); | |
end; | |
i:=cd.mintrk; | |
CDPlay(cd.drive,0,cd.traks[i],cd.len[i]); | |
zeit:=Sect2PCTimer(cd.len[i]); | |
Repeat | |
if (GetTimer>=zeit)or(keypressed) then | |
begin | |
c:=readkey; | |
i:=i+1; | |
if i<=cd.maxtrk then | |
begin | |
CDPlay(cd.drive,0,cd.traks[i],cd.len[i]); | |
zeit:=Sect2PCTimer(cd.len[i]); | |
end; | |
end; | |
until i>cd.maxtrk; | |
CDStop(cd.drive); | |
end. |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Unit PlayCD; | |
INTERFACE | |
const HSGmode=0; | |
Redbook=1; | |
type CDRH=record | |
Len : byte; {= 13+ (max.128)} | |
SubUnit : byte; | |
CmdCode : byte; | |
Status : word; | |
Reserved : array[0..7] of byte; | |
daten : array[0..63] of byte; | |
IOCtlData: array[0..63] of byte; | |
end; | |
cd_info=RECORD {fÅr GetMoreInfo...} | |
f0:byte; | |
Track:byte; | |
Index:byte; | |
tMin:byte; {Min. in bezug auf den akt. Track} | |
tSec:byte; {Sec. in bezug auf den akt. Track} | |
f1:word; | |
Min:byte; | |
Sek:byte; | |
f2:byte; | |
END; | |
var tracktype:byte; | |
procedure ClearHeader(var p:CDRH); | |
function DriveAnz(var nr:word):word; | |
{Ausgabe in nr: Buchstabe des 1. CD-Laufwerks (0=A,1=B,2=C,3=D,...) } | |
function CDVer:word; | |
function CheckDrive(nr:word):boolean; | |
function GetCDPos(nr:word;mode:byte):longint; | |
function GetVolSize(nr:word):longint; | |
function DeviceState(nr:word):longint; | |
function Track2Sector(nr:word;track:byte):longint; {redbook only} | |
function Time2Sector(min,sec:byte):longint; {HSG only} | |
function HSG2Redbook(nr:word;l:longint):longint; | |
function Redbook2HSG(nr:word;l:longint):longint; | |
function Sect2PCTimer(s:longint):longint; | |
function GetTimer:longint; | |
procedure CDCall(nr:word;var p:cdrh); | |
procedure CDPlay(nr:word;mode:byte;Start,len:longint); | |
procedure CDStop(nr:word); | |
procedure CDResume(nr:word); | |
procedure CDSeek(nr:word;mode:byte;start:longint); | |
procedure IOCTLInput(var p:cdrh;nr:word;bufsize:word); | |
procedure GetCDInfo(Nr:word;Var min,max:byte;var l:longint); | |
procedure ResetDrive(Nr:word); | |
procedure GetMoreInfo(nr:word;var i:cd_info); | |
procedure Sect2Time(s:longint;var min,sec:byte); {HSG only} | |
IMPLEMENTATION | |
function CDVer:word; { MACRO ;; Out: Version Hi.Lo} | |
var v:word; | |
begin | |
asm | |
push ax | |
mov ax,150ch | |
int 2fh | |
mov v,bx | |
pop ax | |
end; | |
CDVer:=v; | |
end; | |
function DriveAnz(var nr:word):word; {nr: 1. Laufwerk} | |
var anz,n:word; | |
begin | |
asm | |
mov ax,1500h | |
xor bx,bx | |
int 2Fh | |
mov anz,bx | |
mov n,cx | |
end; | |
nr:=n; | |
driveanz:=anz; | |
end; | |
procedure ClearHeader(var p:CDRH); | |
begin | |
fillchar(p,sizeof(p),0); | |
end; | |
procedure CDCall(nr:word;var p:cdrh); | |
var s,o:word; | |
begin | |
s:=seg(p); | |
o:=ofs(p); | |
asm | |
push es | |
mov ax,1510h | |
mov cx,nr | |
mov bx,s | |
mov es,bx | |
mov BX,o | |
int 2fh | |
pop es | |
end; | |
end; | |
function CheckDrive(nr:word):boolean;{ OUT: Carry is set if any errors...} | |
var a,b:word; | |
begin | |
asm | |
mov ax,150bh | |
mov cx,nr | |
int 2fh | |
mov a,ax; | |
mov b,bx; | |
end; | |
CheckDrive:=not((a=0)and(b=$ADAD)); | |
end; | |
procedure CDPlay(nr:word;mode:byte;Start,len:longint); | |
var p:cdrh; | |
begin | |
p.len:=22; | |
p.cmdcode:=132; | |
p.daten[0]:=mode; | |
move(Start,p.daten[1],4); | |
move(len,p.daten[5],4); | |
CDCall(nr,p); | |
end; | |
procedure CDStop(nr:word); | |
var p:cdrh; | |
begin | |
p.len:=13; | |
p.cmdcode:=133; | |
CDCall(nr,p); | |
end; | |
procedure CDResume(nr:word); | |
var p:cdrh; | |
begin | |
p.len:=13; | |
p.cmdcode:=136; | |
CDCall(nr,p); | |
end; | |
procedure CDSeek(nr:word;mode:byte;start:longint); | |
var p:cdrh; | |
begin | |
p.len:=24; | |
p.cmdcode:=131; | |
p.daten[0]:=mode; | |
fillchar(p.daten[1],6,0); | |
move(start,p.daten[7],4); | |
CDCall(nr,p); | |
end; | |
procedure IOCTLInput(var p:cdrh;nr:word;bufsize:word); | |
var s,o:word; | |
begin | |
p.len:=26; | |
p.cmdcode:=3; | |
s:=seg(p.ioctldata); | |
o:=ofs(p.ioctldata); | |
move(o,p.daten[1],2); | |
move(s,p.daten[3],2); | |
move(bufsize,p.daten[5],2); | |
CDCall(nr,p); | |
end; | |
Function GetCDPos(nr:word;mode:byte):longint; | |
var l:longint; | |
p:cdrh; | |
begin | |
fillchar(p.ioctldata,64,0); | |
p.ioctldata[0]:=1; | |
p.ioctldata[1]:=mode; | |
fillchar(p.ioctldata[2],4,0); | |
IOCTLInput(p,nr,6); | |
move(p.ioctldata[2],l,4); | |
GetCDPos:=l; | |
end; | |
procedure GetCDInfo(Nr:word;Var min,max:byte;var l:longint); | |
{l:last sector , min=1st track, max=last track} | |
var p:cdrh; | |
begin | |
p.ioctldata[0]:=10; | |
IoCtlInput(p,nr,7); | |
min:=p.ioctldata[1]; | |
max:=p.ioctldata[2]; | |
move(p.ioctldata[3],l,4); | |
end; | |
function GetVolSize(nr:word):longint; | |
var p:cdrh; l:longint; | |
begin | |
p.ioctldata[0]:=8; | |
fillchar(p.ioctldata[1],4,0); | |
IOCTLInput(p,nr,5); | |
move(p.ioctldata[1],l,4); | |
GetVolSize:=l; | |
end; | |
procedure ResetDrive(Nr:word); | |
var p:cdrh; | |
begin | |
p.ioctldata[0]:=2; | |
IoCtlInput(p,nr,1); | |
end; | |
function DeviceState(nr:word):longint; | |
var p:cdrh; l:longint; | |
begin | |
p.ioctldata[0]:=6; | |
fillchar(p.ioctldata[1],4,0); | |
IOCTLInput(p,nr,5); | |
move(p.ioctldata[1],l,4); | |
DeviceState:=l; | |
end; | |
procedure GetMoreInfo(nr:word;var i:cd_info); | |
var p:cdrh; | |
begin | |
p.ioctldata[0]:=12; | |
IoctlInput(p,nr,11); | |
move(p.ioctldata[1],i,sizeof(cd_info)); | |
end; | |
function Track2Sector(nr:word;track:byte):longint; | |
{ Out: Sektor (redbook) } | |
var p:cdrh; l:longint; | |
begin | |
p.ioctldata[0]:=11; | |
p.ioctldata[1]:=track; | |
IoctlInput(p,nr,7); | |
move(p.ioctldata[2],l,4); | |
{p.ioctldata[6] - 1 Byte - weitere TrackInfo - noch unbekannt...} | |
Track2Sector:=l; | |
Tracktype:=p.ioctldata[6]; | |
end; | |
function Time2Sector(min,sec:byte):longint; | |
{HSG mode only - ein HSG-Sektor = 1/75 Sekunde } | |
begin | |
Time2Sector:=longint((min*60+sec)*75); | |
end; | |
procedure Sect2Time(s:longint;var min,sec:byte); | |
begin | |
min:=byte(trunc(s/75) div 60); | |
sec:=byte(trunc(s/76) mod 60); | |
end; | |
function Redbook2HSG(nr:word;l:longint):longint; | |
begin | |
CDSeek(nr,redbook,l); | |
RedBook2HSG:=GetCDPos(nr,HSGmode); | |
end; | |
function HSG2Redbook(nr:word;l:longint):longint; | |
begin | |
CDSeek(nr,HSGmode,l); | |
HSG2RedBook:=GetCDPos(nr,Redbook); | |
end; | |
function Sect2PCTimer(s:longint):longint; | |
begin | |
Sect2PCTimer:=memw[Seg0040:$6c]+(memw[Seg0040:$6e] shl 16)+trunc(s/75*18.2)+1; | |
end; | |
function GetTimer:longint; | |
begin | |
GetTimer:=memw[Seg0040:$6c]+(memw[Seg0040:$6e] shl 16); | |
end; | |
end. |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment