home *** CD-ROM | disk | FTP | other *** search
- PROGRAM CTCDREAD;
-
- {CD-ROM Audio Dump V1.1, U. Rohbeck, 13-Juli-94
- V1.2, U. Rohbeck, 15-Juli-94 -SONY-}
-
- {literature
- Kai Schwitzke: Das VOC- und das WAVE-Dateiformat, c't 01/93 - S.213
- Dr. Bernd Steinbrink: Entwirrung der diversen CD-ROM-Formate, c't 02/93 - S.178
- Small Computer System Interface X3.131-199x, X3T9.2375 Revision 10k,17-Mar-93, Working Draft (SCSI-2)
- Ulf Rohbeck: ASPI-Bibliothek für Assembler, Turbo-Pascal und C, c't 12/93 - S.212}
-
- USES CRT,DOS,ASPIxDOS;
-
- CONST
- CDRsupport= 4;
- CDRtypeLST: ARRAY[1..CDRsupport] of STRING[16] = ('TOSHIBA','HITACHI',
- 'NEC','SONY');
- TYPE
- InquireDataFormat = Record
- ConfigPara: ARRAY[0..7] of BYTE;
- VendorID : ARRAY[1..8] of char;
- ProductID : ARRAY[1..16] of char;
- ProductRev: ARRAY[1..4] of char;
- END;
- AbsCDRaddrFormat = Record
- MSF_rsvd : Byte;
- MSF_MM : Byte;
- MSF_SS : Byte;
- MSF_DD : Byte;
- END;
- TOCTrackDescriptor = Record
- rsvd01 : Byte;
- AdrControl: Byte;
- TrackNum : Byte;
- rsvd02 : Byte;
- AbsCDRaddr: AbsCDRaddrFormat;
- END;
- ReadTOCDataFormat = Record
- TOCdataLEN: Word;
- firstTrack: Byte;
- lastTrack : Byte;
- TOCtd : ARRAY[1..99] of TOCTrackDescriptor;
- END;
- SubChannelDataHeader = Record
- rsvd : Byte;
- AudioStatus : Byte;
- SubCDataLEN : Array[0..1] of Byte;
- END;
- TrackISRCDataFormat = Record
- SubCHDR : SubChannelDataHeader;
- SubCDFcode: Byte; {Sub Channel Data Format Code}
- AdrControl: Byte;
- TNO : Byte; {Track Number}
- rsvd : Byte;
- TCVal : Byte;
- TrackISRC : Array[0..14] of Byte; {Track International-Standard-Recording-Code}
- END;
- CDROM_CurrentPositionDataFormat = Record
- SubCHDR : SubChannelDataHeader;
- SubCDFcode: Byte; {Sub Channel Data Format Code}
- AdrControl: Byte;
- TNO : Byte; {Track Number}
- INO : Byte; {Index Number}
- AbsCDRaddr: AbsCDRaddrFormat; {Absolute CD-ROM Address}
- TrackRaddr: AbsCDRaddrFormat; {Track Relative CD-ROM Address}
- END;
- MediaCatalogNumberDataFormat = Record
- SubCHDR : SubChannelDataHeader;
- SubCDFcode: Byte; {Sub Channel Data Format Code}
- rsvd : Array[0..2] of Byte;
- MCVal : Byte;
- MCN : Array[0..14] of Byte; {Media Catalog Number (UPC/Bar Code}
- END;
- ReadSubQDataFormat = Record
- SubCHDR : SubChannelDataHeader;
- SubCDFcode: Byte; {Sub Channel Data Format Code}
- AdrControl: Byte;
- TNO : Byte; {Track Number}
- INO : Byte; {Index Number}
- AbsCDRaddr: AbsCDRaddrFormat; {Absolute CD-ROM Address}
- TrackRaddr: AbsCDRaddrFormat; {Track Relative CD-ROM Address}
- MCVal : Byte;
- MCN : Array[0..14] of Byte; {Media Catalog Number (UPC/Bar Code}
- TCVal : Byte;
- TrackISRC : Array[0..14] of Byte; {Track International-Standard-Recording-Code}
- END;
- _WAVEhdr = RECORD
- MainDesc : LongInt;
- lenFile : LongInt;
- FileType : LongInt;
- SubDesc : LongInt;
- lenSubDesc: LongInt;
- Format : Word;
- Mode : Word;
- SampleFreq: LongInt;
- BytePerSec: LongInt;
- BytePerSam: Word;
- BitPerSam : Word;
- DataDesc : LongInt;
- lenData : LongInt;
- END;
- _ASPI_01 = _ASPI_SRB_GetDeviceType;
- _ASPI_02 = _ASPI_SRB_ExecuteSCSI_IORequest;
-
- CONST
- PVer = 1.1;
- PName= 'CDR-AD';
- ModeSelectData : ARRAY[0..11] of BYTE = (
- $00, {reserved}
- $00, {Medium Type}
- $00, {Device Specific Parameter}
- $08, {Block Descriptor Length}
- $82, {Density Code=CDDA transfer over SCSI support mode}
- $00,$00,$00, {Number of Blocks}
- $00, {reserved}
- $00,$09,$30);{Block Length = 2352}
- VAR
- ReadCDDA : FUNCTION(LBA:LongInt;TransLEN:Byte;PtrBuf:pointer;AllocLEN:WORD):BYTE;
- Option : BYTE;
- Os : String;
- ModeDataBuf : ARRAY[0..11] of Byte;
- SubCData01 : CDROM_CurrentPositionDataFormat;
- SubCData02 : MediaCatalogNumberDataFormat;
- SubCData03 : TrackISRCDataFormat;
- INQBuf : InquireDataFormat;
- ReadTOCdata : ReadTOCDataFormat;
- AudioDataBuf: ARRAY[0..2351] of Byte;
- startTrack, endTrack : BYTE;
- currMSF, startMSF, endMSF : AbsCDRaddrFormat;
- startLBN, endLBN : LongInt;
- InstHost : BYTE; {installed Hostadapter}
- NumHost : BYTE; {number of Hostadapters}
- InstCDROMdev: BOOLEAN; {installed CD-ROM device}
- PDevTyp : BYTE; {peripheral device type}
- WaveHDR : _WAVEhdr;
- WaveFile : FILE;
- FileName : PathStr;
- CDRtype : BYTE;
- WaveFileName: NameStr;
- WaveFilePath: DirStr;
- WaveFileExt : ExtStr;
- CurrentPath : DirStr;
- Ix : BYTE;
- VC1,VC2 : Integer;
- CurrLine : BYTE;
- ISRCcode : LongInt;
- Umleitung : BOOLEAN;
- CON : TEXT;
-
- PROCEDURE TestUmleitung (VAR umleitung:BOOLEAN);
- BEGIN
- Umleitung:= mem[prefixseg:$19]<> 1;
- IF Umleitung THEN BEGIN
- assignCRT(CON);
- rewrite(CON);
- assign(Output,'');
- rewrite(Output);
- END;
- END;
- {------------------------------------------------------}
- PROCEDURE ErrorDetect(ErrorText:STRING);
- BEGIN
- WRITELN('+++ error ExecuteSCSI_IORequest [',_ASPI_02(SRB_ParBlock.pbASPIsrb^)._.Status,']');
- if Length(ErrorText)>0 THEN WRITELN('SCSI Function=',ErrorText);
- HALT;
- END;
- {------------------------------------------------------}
- FUNCTION MSFtoLBN(MSF:AbsCDRaddrFormat):LongInt;
- BEGIN
- MSFtoLBN:=MSF.MSF_MM*LongInt($1194)+MSF.MSF_SS*75+MSF.MSF_DD;
- END;
- PROCEDURE LBNtoMSF(LBN:LongInt;var MSF:AbsCDRaddrFormat);
- BEGIN
- MSF.MSF_MM:=(LBN DIV $1194);
- MSF.MSF_SS:=(LBN-((LBN DIV $1194)*longint($1194))) DIV 75;
- MSF.MSF_DD:=(LBN MOD 75);
- END;
- {------------------------------------------------------}
- FUNCTION LBNtoMSFstr(LBN:LongInt):STRING;
- VAR
- MSF : AbsCDRaddrFormat;
-
- FUNCTION INTtoSTR(DezVAL:BYTE;OSize:BYTE):STRING;
- VAR
- DezStr: STRING[8];
- BEGIN
- STR(DezVAL:OSize,DezStr);
- WHILE Pos(' ',DezStr) > 0 do DezStr[Pos(' ',DezStr)] := '0';
- INTtoSTR:=DezStr;
- END;
-
- BEGIN
- LBNtoMSF(LBN,MSF);
- LBNtoMSFstr:=INTtoSTR(MSF.MSF_MM,2)+':'+INTtoStr(MSF.MSF_SS,2)+'.'+INTtoStr(MSF.MSF_DD,2);
- END;
- {------------------------------------------------------------------------------}
- FUNCTION MSFSTRtoMSF(MSFstr:STRING;var MSF:AbsCDRaddrFormat):BOOLEAN;
- VAR
- VCmm,VCss,VCdd: Integer;
- BEGIN
- VAL(COPY(MSFstr,1,POS(':',MSFstr)-1),MSF.MSF_MM,VCmm);
- VAL(COPY(MSFstr,POS(':',MSFstr)+1,POS('.',MSFstr)-POS(':',MSFstr)-1),MSF.MSF_SS,VCss);
- VAL(COPY(MSFstr,POS('.',MSFstr)+1,LENGTH(MSFstr)-POS('.',MSFstr)),MSF.MSF_DD,VCdd);
- IF (VCmm OR VCss OR VCss) <> 0 THEN MSFSTRtoMSF:=FALSE
- ELSE MSFSTRtoMSF:=TRUE;
- END;
- {------------------------------------------------------------------------------}
- FUNCTION MSFSTRtoLBN(MSFstr:STRING;var LBN:LongInt):BOOLEAN;
- VAR
- MSF: AbsCDRaddrFormat;
- BEGIN
- IF MSFSTRtoMSF(MSFstr,MSF) THEN BEGIN
- LBN:=MSFtoLBN(MSF);
- MSFSTRtoLBN:=TRUE;
- END ELSE MSFSTRtoLBN:=FALSE;
- END;
- {;*******************************************************************************
- ;* I n q u i r e *
- ;* Inquire PtrBuf,AllocLEN *
- ;*+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++*
- ;* parameter: *
- ;* PtrBuf : pointer of buffer data *
- ;* AllocLEN: specifies the number of bytes that the initiator has allocated *
- ;* for data *
- ;* result: *
- ;* AL: status of SRB *
- ;* FF: Error_no_unused_SRB *
- ;*******************************************************************************}
- FUNCTION Inquire(INQBuf:pointer;AllocLEN:BYTE):BYTE;
- CONST
- OpC:Array[0..5] of BYTE =($12,0,0,0,0,0);
- BEGIN
- IF AllocSRBExecute(@OpC,6) THEN BEGIN
- _ASPI_02 (SRB_ParBlock.pbASPIsrb^)._.SCSIReqFlags:=$00;
- _ASPI_02 (SRB_ParBlock.pbASPIsrb^).DataBufPtrOfs:=Ofs(InqBuf^);
- _ASPI_02 (SRB_ParBlock.pbASPIsrb^).DataBufPtrSeg:=Seg(InqBuf^);
- _ASPI_02 (SRB_ParBlock.pbASPIsrb^).DataAllocLen:=AllocLEN;
- _ASPI_02 (SRB_ParBlock.pbASPIsrb^).SCSI_CDB[4]:=AllocLEN;
- Inquire:=ExecuteSCSI_IORequest;
- END;
- END;
- {;*******************************************************************************
- ;* P l a y A u d i o M S F *
- ;* PlayAudioMSF MSFstart,MSFend *
- ;*+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++*
- ;* parameter: *
- ;* MSFstart: specifies the absolute MSF address at which the audio playback *
- ;* operation shall begin *
- ;* MSFend : specifies the absolute MSF address at which the audio playback *
- ;* operation shall end. *
- ;* result: *
- ;* AL: status of SRB *
- ;* FF: Error_no_unused_SRB *
- ;*******************************************************************************}
- FUNCTION PlayAudioMSF(MSFstart,MSFend:AbsCDRaddrFormat):BYTE;
- CONST
- OpC:Array[0..9] of BYTE =($47,0,0,0,0,0,0,0,0,0);
- BEGIN
- IF AllocSRBExecute(@OpC,10) THEN BEGIN
- _ASPI_02 (SRB_ParBlock.pbASPIsrb^)._.SCSIReqFlags:=$18;
- _ASPI_02 (SRB_ParBlock.pbASPIsrb^).SCSI_CDB[3]:=MSFstart.MSF_MM;
- _ASPI_02 (SRB_ParBlock.pbASPIsrb^).SCSI_CDB[4]:=MSFstart.MSF_SS;
- _ASPI_02 (SRB_ParBlock.pbASPIsrb^).SCSI_CDB[5]:=MSFstart.MSF_DD;
- _ASPI_02 (SRB_ParBlock.pbASPIsrb^).SCSI_CDB[6]:=MSFend.MSF_MM;
- _ASPI_02 (SRB_ParBlock.pbASPIsrb^).SCSI_CDB[7]:=MSFend.MSF_SS;
- _ASPI_02 (SRB_ParBlock.pbASPIsrb^).SCSI_CDB[8]:=MSFend.MSF_DD;
- PlayAudioMSF:=ExecuteSCSI_IORequest;
- END;
- END;
- {;*******************************************************************************
- ;* M o d e S e l e c t *
- ;* ModeSelect PtrBuf,AllocLEN *
- ;*+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++*
- ;* parameter: *
- ;* PtrBuf : pointer of buffer data *
- ;* AllocLEN: specifies the number of bytes that the initiator has allocated *
- ;* for data *
- ;* result: *
- ;* AL: status of SRB *
- ;* FF: Error_no_unused_SRB *
- ;*******************************************************************************}
- FUNCTION ModeSelect(ModeDataBuf:pointer;AllocLEN:BYTE):BYTE;
- CONST
- OpC:Array[0..5] of BYTE =($15,0,0,0,0,0);
- BEGIN
- IF AllocSRBExecute(@OpC,6) THEN BEGIN
- _ASPI_02 (SRB_ParBlock.pbASPIsrb^)._.SCSIReqFlags:=$10;
- _ASPI_02 (SRB_ParBlock.pbASPIsrb^).DataBufPtrOfs:=Ofs(ModeDataBuf^);
- _ASPI_02 (SRB_ParBlock.pbASPIsrb^).DataBufPtrSeg:=Seg(ModeDataBuf^);
- _ASPI_02 (SRB_ParBlock.pbASPIsrb^).DataAllocLen:=AllocLEN;
- _ASPI_02 (SRB_ParBlock.pbASPIsrb^).SCSI_CDB[4]:=AllocLEN;
- ModeSelect:=ExecuteSCSI_IORequest;
- END;
- END;
- {;*******************************************************************************
- ;* M o d e S e n s e *
- ;* ModeSense PtrBuf,AllocLEN *
- ;*+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++*
- ;* parameter: *
- ;* PtrBuf : pointer of buffer data *
- ;* AllocLEN: specifies number of bytes that initiator has allocated for data *
- ;* result: *
- ;* AL: status of SRB *
- ;* FF: Error_no_unused_SRB *
- ;*******************************************************************************}
- FUNCTION ModeSense(ModeDataBuf:pointer;AllocLEN:BYTE):BYTE;
- CONST
- OpC:Array[0..5] of BYTE =($1A,0,0,0,0,0);
- BEGIN
- IF AllocSRBExecute(@OpC,6) THEN BEGIN
- _ASPI_02 (SRB_ParBlock.pbASPIsrb^)._.SCSIReqFlags:=$08;
- _ASPI_02 (SRB_ParBlock.pbASPIsrb^).DataBufPtrOfs:=Ofs(ModeDataBuf^);
- _ASPI_02 (SRB_ParBlock.pbASPIsrb^).DataBufPtrSeg:=Seg(ModeDataBuf^);
- _ASPI_02 (SRB_ParBlock.pbASPIsrb^).DataAllocLen:=AllocLEN;
- _ASPI_02 (SRB_ParBlock.pbASPIsrb^).SCSI_CDB[4]:=AllocLEN;
- ModeSense:=ExecuteSCSI_IORequest;
- END;
- END;
- {;*******************************************************************************
- ;* R e a d ( 6 ) *
- ;* Read6 LBA,TransLEN,PtrBuf,AllocLEN *
- ;*+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++*
- ;* parameter: *
- ;* LBA : the logical block address at which the read operation shall begin *
- ;* TransLEN: specifies the number of logical blocks to be transfered *
- ;* PtrBuf : pointer of buffer data *
- ;* AllocLEN: specifies number of bytes that initiator has allocated for data *
- ;* result: *
- ;* AL: status of SRB *
- ;* FF: Error_no_unused_SRB *
- ;*******************************************************************************}
- FUNCTION Read6(LBA:LongInt;TransLEN:Byte;PtrBuf:pointer;AllocLEN:WORD):BYTE;far;
- CONST
- OpC:Array[0..5] of BYTE =($08,0,0,0,0,0);
- BEGIN
- IF AllocSRBExecute(@OpC,6) THEN BEGIN
- _ASPI_02 (SRB_ParBlock.pbASPIsrb^)._.SCSIReqFlags:=$08;
- _ASPI_02 (SRB_ParBlock.pbASPIsrb^).DataBufPtrOfs:=Ofs(PtrBuf^);
- _ASPI_02 (SRB_ParBlock.pbASPIsrb^).DataBufPtrSeg:=Seg(PtrBuf^);
- _ASPI_02 (SRB_ParBlock.pbASPIsrb^).DataAllocLen:=AllocLEN;
- _ASPI_02 (SRB_ParBlock.pbASPIsrb^).SCSI_CDB[1]:=LO(LBA SHR 16);
- _ASPI_02 (SRB_ParBlock.pbASPIsrb^).SCSI_CDB[2]:=HI(LBA AND $FFFF);
- _ASPI_02 (SRB_ParBlock.pbASPIsrb^).SCSI_CDB[3]:=LO(LBA AND $FFFF);
- _ASPI_02 (SRB_ParBlock.pbASPIsrb^).SCSI_CDB[4]:=TransLEN;
- Read6:=ExecuteSCSI_IORequest;
- END;
- END;
- {;*******************************************************************************
- ;* R e a d C D D A (12) *
- ;* ReadCDDA12 LBA,TransLEN,PtrBuf,AllocLEN *
- ;*+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++*
- ;* parameter: *
- ;* LBA : the logical block address at which the read operation shall begin *
- ;* TransLEN: specifies the number of logical blocks to be transfered *
- ;* PtrBuf : pointer of buffer data *
- ;* AllocLEN: specifies number of bytes that initiator has allocated for data *
- ;* result: *
- ;* AL: status of SRB *
- ;* FF: Error_no_unused_SRB *
- ;*******************************************************************************}
- FUNCTION ReadCDDA12(LBA:LongInt;TransLEN:Byte;PtrBuf:pointer;AllocLEN:WORD):BYTE;far;
- CONST
- OpC:Array[0..11] of BYTE =($D8,0,0,0,0,0,0,0,0,0,0,0);
- BEGIN
- IF AllocSRBExecute(@OpC,12) THEN BEGIN
- _ASPI_02 (SRB_ParBlock.pbASPIsrb^)._.SCSIReqFlags:=$08;
- _ASPI_02 (SRB_ParBlock.pbASPIsrb^).DataBufPtrOfs:=Ofs(PtrBuf^);
- _ASPI_02 (SRB_ParBlock.pbASPIsrb^).DataBufPtrSeg:=Seg(PtrBuf^);
- _ASPI_02 (SRB_ParBlock.pbASPIsrb^).DataAllocLen:=AllocLEN;
- _ASPI_02 (SRB_ParBlock.pbASPIsrb^).SCSI_CDB[3]:=LO(LBA SHR 16);
- _ASPI_02 (SRB_ParBlock.pbASPIsrb^).SCSI_CDB[4]:=HI(LBA AND $FFFF);
- _ASPI_02 (SRB_ParBlock.pbASPIsrb^).SCSI_CDB[5]:=LO(LBA AND $FFFF);
- _ASPI_02 (SRB_ParBlock.pbASPIsrb^).SCSI_CDB[9]:=TransLEN;
- ReadCDDA12:=ExecuteSCSI_IORequest;
- END;
- END;
- {;*******************************************************************************
- ;* R e a d C D D A (10) *
- ;* ReadCDDA10 LBA,TransLEN,PtrBuf,AllocLEN *
- ;*+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++*
- ;* parameter: *
- ;* LBA : the logical block address at which the read operation shall begin *
- ;* TransLEN: specifies the number of logical blocks to be transfered *
- ;* PtrBuf : pointer of buffer data *
- ;* AllocLEN: specifies number of bytes that initiator has allocated for data *
- ;* result: *
- ;* AL: status of SRB *
- ;* FF: Error_no_unused_SRB *
- ;*******************************************************************************}
- FUNCTION ReadCDDA10(LBA:LongInt;TransLEN:Byte;PtrBuf:pointer;AllocLEN:WORD):BYTE;far;
- CONST
- OpC:Array[0..9] of BYTE =($D4,0,0,0,0,0,0,0,0,0);
- BEGIN
- IF AllocSRBExecute(@OpC,10) THEN BEGIN
- _ASPI_02 (SRB_ParBlock.pbASPIsrb^)._.SCSIReqFlags:=$08;
- _ASPI_02 (SRB_ParBlock.pbASPIsrb^).DataBufPtrOfs:=Ofs(PtrBuf^);
- _ASPI_02 (SRB_ParBlock.pbASPIsrb^).DataBufPtrSeg:=Seg(PtrBuf^);
- _ASPI_02 (SRB_ParBlock.pbASPIsrb^).DataAllocLen:=AllocLEN;
- _ASPI_02 (SRB_ParBlock.pbASPIsrb^).SCSI_CDB[2]:=LO(LBA SHR 16);
- _ASPI_02 (SRB_ParBlock.pbASPIsrb^).SCSI_CDB[3]:=HI(LBA AND $FFFF);
- _ASPI_02 (SRB_ParBlock.pbASPIsrb^).SCSI_CDB[4]:=LO(LBA AND $FFFF);
- _ASPI_02 (SRB_ParBlock.pbASPIsrb^).SCSI_CDB[8]:=TransLEN;
- ReadCDDA10:=ExecuteSCSI_IORequest;
- END;
- END;
- {;*******************************************************************************
- ;* R e a d T O C *
- ;* ReadTOC Track,PtrBuf,AllocLEN *
- ;*+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++*
- ;* parameter: *
- ;* STrack : specifies the starting track that the logical block address *
- ;* format should be used for the CD-ROM address field *
- ;* PtrBuf : pointer of buffer data *
- ;* AllocLEN: specifies number of bytes that initiator has allocated for data *
- ;* result: *
- ;* AL: status of SRB *
- ;* FF: Error_no_unused_SRB *
- ;*******************************************************************************}
- FUNCTION ReadTOC(STrack:Byte;TOCdataBuf:pointer;AllocLEN:WORD):BYTE;
- CONST
- OpC:Array[0..9] of BYTE =($43,2,0,0,0,0,0,0,0,0);
- BEGIN
- IF AllocSRBExecute(@OpC,10) THEN BEGIN
- _ASPI_02 (SRB_ParBlock.pbASPIsrb^)._.SCSIReqFlags:=$08;
- _ASPI_02 (SRB_ParBlock.pbASPIsrb^).DataBufPtrOfs:=Ofs(TOCdataBuf^);
- _ASPI_02 (SRB_ParBlock.pbASPIsrb^).DataBufPtrSeg:=Seg(TOCdataBuf^);
- _ASPI_02 (SRB_ParBlock.pbASPIsrb^).DataAllocLen:=AllocLEN;
- _ASPI_02 (SRB_ParBlock.pbASPIsrb^).SCSI_CDB[6]:=STrack;
- _ASPI_02 (SRB_ParBlock.pbASPIsrb^).SCSI_CDB[7]:=hi(AllocLEN);
- _ASPI_02 (SRB_ParBlock.pbASPIsrb^).SCSI_CDB[8]:=lo(AllocLEN);
- ReadTOC:=ExecuteSCSI_IORequest;
- END;
- END;
- {;*******************************************************************************
- ;* R e a d S u b C *
- ;* ReadSubC STrack,SubCDF,PtrBuf,AllocLEN *
- ;*+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++*
- ;* parameter: *
- ;* STrack : specifies the starting track that the logical block address *
- ;* format should be used for the CD-ROM address field *
- ;* SubCDF : specifies the format of returned sub-channel data *
- ;* PtrBuf : pointer of buffer data *
- ;* AllocLEN: specifies number of bytes that initiator has allocated for data *
- ;* result: *
- ;* AL: status of SRB *
- ;* FF: Error_no_unused_SRB *
- ;*******************************************************************************}
- FUNCTION ReadSubC(STrack,SubCDF:Byte;SubCdataBuf:pointer;AllocLEN:WORD):BYTE;
- CONST
- OpC:Array[0..9] of BYTE =($42,2,$40,0,0,0,0,0,0,0);
- BEGIN
- IF AllocSRBExecute(@OpC,10) THEN BEGIN
- _ASPI_02 (SRB_ParBlock.pbASPIsrb^)._.SCSIReqFlags:=$08;
- _ASPI_02 (SRB_ParBlock.pbASPIsrb^).DataBufPtrOfs:=Ofs(SubCdataBuf^);
- _ASPI_02 (SRB_ParBlock.pbASPIsrb^).DataBufPtrSeg:=Seg(SubCdataBuf^);
- _ASPI_02 (SRB_ParBlock.pbASPIsrb^).DataAllocLen:=AllocLEN;
- _ASPI_02 (SRB_ParBlock.pbASPIsrb^).SCSI_CDB[3]:=SubCDF;
- _ASPI_02 (SRB_ParBlock.pbASPIsrb^).SCSI_CDB[6]:=STrack;
- _ASPI_02 (SRB_ParBlock.pbASPIsrb^).SCSI_CDB[7]:=hi(AllocLEN);
- _ASPI_02 (SRB_ParBlock.pbASPIsrb^).SCSI_CDB[8]:=lo(AllocLEN);
- ReadSubC:=ExecuteSCSI_IORequest;
- END;
- END;
-
- BEGIN { MAIN }
- ClrScr;
- TestUmleitung(Umleitung);
- WRITELN;
- WRITELN(PName,' version ',PVer:4:2,' U. Rohbeck, 05/07/94');
- { no parameter, display help text }
- IF ParamCount = 0 THEN BEGIN
- WRITELN('syntax: ',PNAME,' [option] WaveFile[.WAV]');
- WRITELN(' -l track listing of CD');
- WRITELN(' -d:<type> device select');
- WRITELN(' <type>: HITACHI');
- WRITELN(' NEC');
- WRITELN(' SONY');
- WRITELN(' TOSHIBA (default)');
- WRITELN(' -mp mode: play audio');
- WRITELN(' -mw mode: write to file in WAVE format');
- WRITELN(' -fT[=[start][,end]] format: send whole track to file');
- WRITELN(' -fM[=[start][,end]] format: send sector using MSF format MM:SS.DD');
- WRITELN(' -w watching audio');
- HALT;
- END;
- { search ASPI manager }
- IF NOT (InitSCSIMgr) THEN BEGIN
- WRITELN('+++ no SCSIMgr installed');
- HALT;
- END;
- { get number of hostadapters }
- GetInstHostAdapters(InstHost,NumHost);
- SRB_ParBlock.pbHostAdapNum:=0;
- { find first CD-ROM drive }
- WHILE ((NumHost>0) AND (NOT InstCDROMdev)) DO BEGIN
- IF ((InstHost SHR SRB_ParBlock.pbHostAdapNum) AND $01)=01 THEN BEGIN
- {get device information}
- InstCDROMdev:=FALSE;
- SRB_ParBlock.pbTargetID:=0;
- SRB_ParBlock.pbLUN:=0;
- { scan SCSI ID for CD-ROM (01) }
- WHILE (SRB_ParBlock.pbTargetID<8) AND (NOT InstCDROMdev) DO BEGIN
- IF GetDeviceType=01 THEN BEGIN
- IF _ASPI_01 (SRB_ParBlock.pbASPIsrb^).PDevTyp=$05 THEN BEGIN
- InstCDROMdev:=TRUE;
- IF Inquire(@InqBuf,SizeOf(InqBuf)) = $0FF THEN ErrorDetect('Inquire(@InqBuf,SizeOf(InqBuf))') ELSE BEGIN
- IF SRB_ParBlock.pbASPIstatus = $01 THEN BEGIN
- WRITELN(InqBuf.VendorID,' ',InqBuf.ProductID,' CD-DA Audio Dump');
- CDRtype:=1;
- { check if CD-ROM is supported }
- WHILE (CDRtype<=CDRsupport) AND (COPY(InqBuf.VendorID,1,length(CDRtypeLST[CDRtype]))<>CDRtypeLST[CDRtype])
- DO INC(CDRtype);
- IF CDRtype > CDRsupport THEN BEGIN
- WRITELN('+++ device type <',OS,'> not supported');
- HALT; {disable this line to force other drives}
- END;
- END ELSE ErrorDetect('');
- { read CD-ROM parameter table }
- IF ModeSense(@ModeDataBuf,sizeof(ModeDataBuf)) <> 01 THEN ErrorDetect('ModeSense(@ModeDataBuf,sizeof(ModeDataBuf))');
- BREAK;
- END;
- END;
- END;
- INC(SRB_ParBlock.pbTargetID);
- END; { WHILE }
- DEC(NumHost);
- END;
- END; { WHILE }
- WRITELN;
- IF NOT InstCDROMdev THEN BEGIN
- WRITELN('+++ error: no CD-ROM device installed');
- HALT;
- END;
- { read TOC }
- IF ReadTOC(00,@ReadTOCdata,sizeof(ReadTOCdata))<>01 THEN ErrorDetect('ReadTOC(00,@ReadTOCdata,sizeof(ReadTOCdata))');
- FileName:='';
- CDRtype:=1; {TOSHIBA, default}
- Option:=0;
- Ix:=1;
- { check command line }
- WHILE Ix<=ParamCount DO BEGIN
- Os:= ParamStr(Ix);
- IF (Os[1]= '-') OR (Os[1]='/') THEN BEGIN
- CASE Os[2] of
- 'l','L':BEGIN { -l: Track listing of CD }
- Option:=Option OR $80;
- END;
- 'd','D':BEGIN { -d: Drive Type }
- OS:=COPY(OS,POS(':',OS)+1,LENGTH(OS)-POS(':',OS)+1);
- FOR VC1:=1 TO LENGTH(OS) DO OS[VC1]:=UpCase(OS[VC1]);
- WHILE (CDRtype<=CDRsupport) AND (OS<>CDRtypeLST[CDRtype]) DO
- INC(CDRtype);
- IF CDRtype > CDRsupport THEN BEGIN
- WRITELN('+++ device type <',OS,'> not supported');
- HALT;
- END ELSE WRITELN('set device to: ',CDRtypeLST[CDRtype]);
- END;
- 'f','F':BEGIN { -fx.. format }
- CASE Os[3] of
- 't','T':BEGIN { -fT: send whole Track to file }
- Option:=(Option AND $FE) OR $1;
- startTrack:=0;
- VC1:=0;
- endTrack :=0;
- VC2:=0;
- IF POS('=',Os)>0 THEN BEGIN
- IF POS(',',Os)>0 THEN BEGIN
- VAL(COPY(Os,POS('=',Os)+1,POS(',',Os)-POS('=',Os)-1),
- startTrack,VC1);
- VAL(COPY(Os,POS(',',Os)+1,LENGTH(Os)-POS(',',Os)+1),
- endTrack,VC2);
- END ELSE VAL(COPY(Os,POS('=',Os)+1,LENGTH(Os)-POS('=',Os)+1),
- startTrack,VC1);
- IF (VC1 OR VC2)<>0 THEN BEGIN
- WRITELN('+++ illegal track number format');
- HALT;
- END;
- END;
- IF startTrack=0 THEN StartTrack:=ReadTOCdata.firstTrack;
- IF endTrack=0 THEN endTrack:=ReadTOCdata.lastTrack;
- startLBN:=MSFtoLBN(ReadTOCdata.TOCtd[startTrack].AbsCDRaddr);
- INC(endTrack);
- endLBN:=MSFtoLBN(ReadTOCdata.TOCtd[endTrack].AbsCDRaddr)-1;
- END;
- 'm','M':BEGIN { -fM: send sector using MSF format MM:SS:DD }
- Option:=(Option AND $FE) OR $1;
- startLBN:=0;
- VC1:=0;
- endLBN:=0;
- VC2:=0;
- IF POS('=',Os)>0 THEN BEGIN
- IF POS(',',Os)>0 THEN BEGIN
- IF POS(',',Os)-1 = POS('=',Os) THEN MSFSTRtoLBN('00:02.00',startLBN)
- ELSE BEGIN
- IF NOT MSFSTRtoLBN(COPY(Os,POS('=',Os)+1,POS(',',Os)-POS('=',Os)-1),startLBN)
- THEN VC1:=$FF;
- END;
- IF NOT MSFSTRtoLBN(COPY(Os,POS(',',Os)+1,LENGTH(Os)-POS(',',Os)+1),endLBN)
- THEN VC1:=$FF;
- END ELSE BEGIN
- IF NOT MSFSTRtoLBN(COPY(Os,POS('=',Os)+1,LENGTH(Os)-POS('=',Os)-1),startLBN)
- THEN VC1:=$FF;
- END;
- END;
- IF (VC1 OR VC2)<>0 THEN BEGIN
- WRITELN('+++ illegal MSF format');
- HALT;
- END;
- IF startLBN=0 THEN MSFSTRtoLBN('00:02.00',startLBN);
- IF endLBN=0 THEN endLBN:=MSFtoLBN(ReadTOCdata.TOCtd[ReadTOCdata.lastTrack].AbsCDRaddr);
- END; { -fM }
- END; { Case -fx }
- END; { -f }
- 'm','M':BEGIN { -mx mode select, play or write }
- CASE Os[3] of
- 'p','P': Option:=(Option AND $CF) OR $10; { -mP play audio }
- 'w','W': Option:=(Option AND $CF) OR $20; { -mW write WAV }
- END;
- END;
- 'w','W':Option:=(Option AND $BF) OR $40; { -w watching audio }
- END; { CASE }
- END ELSE FileName:=ParamStr(Ix);
- INC(Ix);
- END; (* WHILE *)
- IF ((Option AND $10)<>0) AND ((Option AND $01)=0) THEN BEGIN
- WRITELN('+++ format parameter required');
- HALT;
- END;
- { -l, display CD ROM Track list }
- IF (Option AND $80) <> 0 THEN BEGIN
- WITH ReadTOCdata DO BEGIN
- WRITELN('*** TRACK LISTING OF CD ***');
- WRITELN;
- WRITELN('Start track: ',firstTrack:2);
- WRITELN('Last track: ',lastTrack:2);
- WRITELN('Total time : ',TOCtd[ReadTOCdata.lastTrack+1].AbsCDRaddr.MSF_MM,' minutes ',
- TOCtd[ReadTOCdata.lastTrack+1].AbsCDRaddr.MSF_SS,' seconds ',
- TOCtd[ReadTOCdata.lastTrack+1].AbsCDRaddr.MSF_DD,' frames (75th/s)');
- IF ReadSubC(startTrack,$02,@SubCData02,sizeof(SubCData02)) <> 01
- THEN ErrorDetect('ReadSubC(startTrack,$02,@SubCData02,sizeof(SubCData02))');
- WRITE('UPC/BarCode: ');
- IF (subCData02.MCVAL AND $80) = 0 THEN WRITELN('*** not available ***')
- ELSE BEGIN
- FOR Ix:=0 TO 4 DO WRITE(SubCData02.MCN[Ix]);
- WRITE(' ');
- FOR Ix:=5 TO 7 DO WRITE(SubCData02.MCN[Ix]);
- WRITE('-');
- FOR Ix:=8 TO 10 DO WRITE(SubCData02.MCN[Ix]);
- WRITE('-');
- FOR Ix:=11 TO 11 DO WRITE(SubCData02.MCN[Ix]);
- WRITE(' ');
- FOR Ix:=12 TO 14 DO WRITE(SubCData02.MCN[Ix]);
- END;
- WRITELN;
- WRITELN;
- WRITELN('====================================================================');
- WRITELN('| | | MSF_start | | Digital Copy | Audio |');
- WRITELN('| No. | Type | time | Pre-Emphasis | Permitted | Channels |');
- WRITELN('|-----+-------+-----------+--------------+--------------+----------|');
- FOR Ix:=firstTrack TO lastTrack DO BEGIN
- WRITE('| ',Ix:2,' |');
- IF (TOCtd[Ix].AdrControl AND $04) <> 0 THEN WRITE(' data ')
- ELSE WRITE(' audio');
- WRITE(' | ',LBNtoMSFstr(MSFtoLBN(TOCtd[Ix].AbsCDRaddr)),' |');
- IF (TOCtd[Ix].AdrControl AND $02) = 0 THEN WRITE(' without |')
- ELSE WRITE(' with |');
- IF (TOCtd[Ix].AdrControl AND $01) <> 0 THEN WRITE(' yes |')
- ELSE WRITE(' no |');
- IF (TOCtd[Ix].AdrControl AND $08) = 0 THEN WRITELN(' 2 |')
- ELSE WRITELN(' 4 |');
- END;
- WRITELN('====================================================================');
- WRITELN;
- END;
- END;
- IF (Option AND $30) <> 0 THEN BEGIN
- IF ((Option AND $01)=0) OR (startLBN > endLBN) THEN BEGIN
- WRITELN('+++ error format parameter detected');
- HALT;
- END;
- Ix:=ReadTOCdata.firstTrack;
- WHILE ((Ix<(ReadTOCdata.lastTrack)+1) AND (MSFtoLBN(ReadTOCdata.TOCtd[IX].AbsCDRaddr) < startLBN))
- DO INC(Ix);
- IF (ReadTOCdata.TOCtd[IX].AdrControl AND $04) <> 0 THEN BEGIN
- WRITELN('+++ error: data track detected');
- HALT;
- END;
- WHILE ((Ix<(ReadTOCdata.lastTrack)+1) AND (MSFtoLBN(ReadTOCdata.TOCtd[IX].AbsCDRaddr) < endLBN))
- DO BEGIN
- IF (ReadTOCdata.TOCtd[IX].AdrControl AND $04) <> 0 THEN BEGIN
- WRITELN('+++ error: data track detected');
- HALT;
- END;
- INC(Ix);
- END;
- END;
- {play audio}
- IF (Option AND $10) <> 0 THEN BEGIN
- LBNtoMSF(startLBN,startMSF);
- LBNtoMSF(endLBN,endMSF);
- IF PlayAudioMSF(startMSF,endMSF) <> 01 THEN ErrorDetect('PlayAudioMSF(startMSF,endMSF)');
- { watch audio }
- IF (Option AND $40) <> 0 THEN BEGIN
- LBNtoMSF($00,SubCData01.AbsCDRaddr);
- WRITELN('... watching audio');
- WRITELN;
- WRITELN('Country Code : --');
- WRITELN('Owner Code : ---');
- WRITELN('year of recording: 19xx');
- WRITELN;
- WRITE('position: ');
- CurrLine:=WHEREY;
- WHILE (MSFtoLBN(SubCData01.AbsCDRaddr)) <= endLBN DO BEGIN
- IF (SubCData01.TNO<>SubCData03.TNO) THEN BEGIN
- IF ReadSubC(SubCData01.TNO,03,@SubCData03,sizeof(SubCData03)) <> 01
- THEN ErrorDetect('ReadSubC(SubCData01.TNO,03,@SubCData03,sizeof(SubCData03))');
- IF (SubCData03.TCVAL AND $80) <>0 THEN BEGIN
- WITH SubCData03 DO BEGIN
- ISRCcode:=0;
- FOR Ix:=0 TO 7 DO ISRCcode:=(ISRCcode SHL 4) OR (TrackISRC[Ix] AND $0F);
- GOTOXY(22,CurrLine-4);
- WRITE(CHR($30+((ISRCcode SHR 26) AND $3F))+
- CHR($30+((ISRCcode SHR 20) AND $3F)));
- GOTOXY(21,CurrLine-3);
- WRITE(CHR($30+((ISRCcode SHR 14) AND $3F))+
- CHR($30+((ISRCcode SHR 8) AND $3F))+
- CHR($30+((ISRCcode SHR 2) AND $3F)));
- GOTOXY(20,CurrLine-2);
- WRITE('19',TrackISRC[8]*10+TrackISRC[9]);
- END;
- END;
- END;
- ReadSubC(00,01,@SubCData01,sizeof(SubCData01));
- GotoXY(12,CurrLine);
- WRITE('Track: #',SubCData01.TNO);
- WRITE(' abs: ',LBNtoMSFstr(MSFtoLBN(SubCData01.AbsCDRaddr)));
- WRITE(' rel: ',LBNtoMSFstr(MSFtoLBN(SubCData01.TrackRaddr)));
- END;
- END;
- END;
- {write to file in WAVE-format}
- IF (Option AND $20) <> 0 THEN BEGIN
- IF FileName='' THEN BEGIN
- WRITELN('+++ no valid filename');
- HALT;
- END;
- GetDir($0,CurrentPath);
- IF CurrentPath[Length(CurrentPath)]<>'\' THEN CurrentPath:=CurrentPath+'\';
- FSPLIT(FileName,WaveFilePath,WaveFileName,WaveFileExt);
- IF WaveFilePath='' THEN WaveFilePath:=CurrentPath;
- IF WaveFilePath[Length(WaveFilePath)]<>'\' THEN WaveFilePath:=WaveFilePath+'\';
- IF WaveFileExt='' THEN WaveFileExt:='.WAV';
- CASE CDRtype of
- $01:BEGIN {TOSHIBA}
- IF ModeSelect(@ModeSelectData,sizeof(ModeSelectData)) <> 01
- THEN ErrorDetect('ModeSelect(@ModeSelectData,sizeof(ModeSelectData))');
- ReadCDDA:=Read6;
- END;
- $02:ReadCDDA:=ReadCDDA12; {HITACHI}
- $03:ReadCDDA:=ReadCDDA10; {NEC}
- $04:ReadCDDA:=ReadCDDA12; {SONY}
- END;
- ASSIGN(WaveFile,WaveFilePath+WaveFileName+WaveFileExt);
- REWRITE(WaveFile,1);
- {initialize WAVEheader}
- WAVEhdr.MainDesc:=$46464952; {'RIFF'}
- WAVEhdr.FileType:=$45564157; {'WAVE'}
- WAVEhdr.SubDesc:=$20746D66; {'fmt '}
- WAVEhdr.lenSubDesc:=$10;
- WAVEhdr.Format:=$01; {PCM}
- WAVEhdr.Mode:=$02; {Stereo}
- WAVEhdr.SampleFreq:=$0AC44; {44.1 KHz}
- WAVEhdr.BytePerSec:=$2B110; {16Bit-Stereo-Sound}
- WAVEhdr.BytePerSam:=$04; {16Bit-Stereo-Sound}
- WAVEhdr.BitPerSam:=$10; {16-Bit}
- WAVEhdr.DataDesc:=$61746164; {'data'}
- WAVEhdr.lenData:=longInt((endLBN+1)-startLBN)*$930;
- WAVEhdr.lenFile:=sizeof(WAVEhdr)-8+WAVEhdr.lenData;
- WRITELN('total bytes requested: ',WAVEhdr.lenFile,' Byte');
- IF DiskFree(ORD(WaveFilePath[1])-$40)< WAVEhdr.lenFile THEN BEGIN
- WRITELN('+++ not enough space available on target drive');
- HALT;
- END;
- BLOCKWRITE(WaveFile,WAVEhdr,sizeof(WAVEhdr));
- WRITELN;
- WHILE startLBN <= endLBN DO BEGIN
- IF READCDDA(150+startLBN,1,@AudioDataBuf,sizeof(AudioDataBuf))<>01
- THEN ErrorDetect('READCDDA(150+startLBN,1,@AudioDataBuf,sizeof(AudioDataBuf))');
- BLOCKWRITE(WaveFile,AudioDataBuf,sizeof(AudioDataBuf));
- GotoXY(1,WhereY);
- WRITE('MSF: ',LBNtoMSFstr(startLBN));
- INC(startLBN);
- END;
- CLOSE(WaveFile);
- WRITELN;
- END;
- ModeDataBuf[0]:=0;
- IF ModeSelect(@ModeDataBuf,sizeof(ModeDataBuf)) <> 01
- THEN ErrorDetect('ModeSelect(@ModeDataBuf,sizeof(ModeDataBuf))');
- END.
-