home *** CD-ROM | disk | FTP | other *** search
/ Amiga MA Magazine 1998 #6 / amigamamagazinepolishissue1998.iso / packery / fp_adpcm / cdripper / source / cdripper.c < prev    next >
C/C++ Source or Header  |  1977-12-31  |  23KB  |  889 lines

  1.  
  2. /*   RIP TRACKS FROM A CD AND SAVE AS 2 OR 3 BIT ADPCM SAMPLE   */
  3. /* Written in 1995 by Christian Buchner. This is Public Domain. */
  4.  
  5. /* Note: TAB SIZE = 4 */
  6.  
  7. /* History:
  8.  
  9.    added version string (still V1.0)
  10.  
  11.    V1.1: added NumTracks, maximizing and boost factor
  12.  
  13. */
  14.  
  15. /* Includes */
  16.  
  17. #include <proto/dos.h>
  18. #include <proto/exec.h>
  19. #include <proto/intuition.h>
  20. #include <clib/alib_stdio_protos.h>
  21. #include <libraries/dos.h>
  22. #include <intuition/intuition.h>
  23. #include <exec/io.h>
  24. #include <exec/memory.h>
  25. #include <devices/scsidisk.h>
  26. #include <string.h>
  27. #include <stdarg.h>
  28.  
  29.  
  30. /* Version string */
  31.  
  32. UBYTE Version[]="$VER: CDRipper 1.1 "__AMIGADATE__" by Christian Buchner";
  33.  
  34.  
  35. /* CDDA constants */
  36.  
  37. #define CDDA_BLOCKSIZE 2352        /* size of one CDDA block */
  38. #define ONE_SECOND 75            /* blocks per second (75) */
  39.  
  40. /* Buffer size */
  41.  
  42. #define BUFBLOCKS 64
  43.  
  44.  
  45.  
  46. /*******************************************************************************/
  47.  
  48. BOOL OpenSCSI(UBYTE *Device, ULONG Unit);
  49. void CloseSCSI(void);
  50. ULONG DoSCSI(struct IOStdReq *IORequest, APTR Command, ULONG CommandLength, APTR Buffer, ULONG Length, ULONG Flags, BOOL Asynchronous, UBYTE *ActivityName);
  51. void RipTrack(ULONG Track, ULONG NumTracks, UBYTE *ToFile, ULONG Bits, BOOL Maximize, LONG Boost);
  52. void __stdargs Message(UBYTE *Msg,...);
  53.  
  54. extern __asm ULONG CompressADPCM2(        register __a0 UBYTE *Source,
  55.                                         register __d0 ULONG Length,
  56.                                         register __a1 UBYTE *Destination,
  57.                                         register __d1 ULONG JoinCode    );
  58.  
  59. extern __asm ULONG CompressADPCM3(        register __a0 UBYTE *Source,
  60.                                         register __d0 ULONG Length,
  61.                                         register __a1 UBYTE *Destination,
  62.                                         register __d1 ULONG JoinCode    );
  63.  
  64. /*******************************************************************************/
  65.  
  66.  
  67. /* Library bases */
  68.  
  69. struct DosLibrary *DOSBase;
  70. struct IntuitionBase *IntuitionBase;
  71.  
  72.  
  73. /* Synchronous SCSI IO */
  74.  
  75. LONG SyncSigBit= -1;
  76. struct MsgPort SyncReplyPort;
  77. struct IOStdReq SyncSCSI_IO;
  78. struct SCSICmd SyncSCSICmd;
  79.  
  80.  
  81. /* SCSI command and mode structures */
  82.  
  83. struct Read12
  84. {
  85.     UBYTE cmd;            /* READ(12) SCSI command 0xA8 */
  86.     UBYTE pad_a;        /* Bits 7-5 Logical Unit Number | Bits 4-1 Reserved | Bit 0 EVPD */
  87.     ULONG lba;            /* logical block address MSB, , ,LSB */
  88.     ULONG lbn;            /* number of blocks to transfer MSB, , ,LSB */
  89.     UBYTE subcode;        /* special sub code selector (only for SONY!)
  90.                          * 0: normal 2352
  91.                          * 1: 2368
  92.                          * 2: 2448
  93.                          * 3: 96 bytes */
  94.     UBYTE cntrl;        /* Control */
  95. };
  96.  
  97. struct ModeSense
  98. {
  99.     UBYTE cmd;
  100.     UBYTE pad_a;
  101.     UBYTE page;
  102.     UBYTE reserved;
  103.     UBYTE alloclen;
  104.     UBYTE cntrl;
  105. };
  106.  
  107. struct ModeSelect
  108. {
  109.     UBYTE cmd;
  110.     UBYTE pageformat;
  111.     UBYTE reserved_a;
  112.     UBYTE reserved_b;
  113.     UBYTE plistlen;
  114.     UBYTE cntrl;
  115. };
  116.  
  117. struct ModeData
  118. {
  119. /* 4 Byte Mode Parameter Header (Table 7-61) */
  120.     UBYTE mode_data_length;
  121.     UBYTE medium_type;
  122.     UBYTE device_specific_parameter;
  123.     UBYTE block_descriptor_length;
  124. /* 8 Byte Mode Parameter Block Descriptor (Table 7-63) */
  125.     UBYTE density;
  126.     UBYTE num_blocks_H;
  127.     UBYTE num_blocks_M;
  128.     UBYTE num_blocks_L;
  129.     ULONG block_length;
  130. };
  131.  
  132. struct Inquiry
  133. {
  134.     UBYTE cmd;
  135.     UBYTE pad_a;
  136.     UBYTE page;
  137.     UBYTE reserved;
  138.     UBYTE alloclen;
  139.     UBYTE cntrl;
  140. };
  141.  
  142. struct InquiryData
  143. {
  144.     UBYTE pdevtype;
  145.     UBYTE rmb_devtypmod;
  146.     UBYTE versions;
  147.     UBYTE rdformat;
  148.     UBYTE addlength;
  149.     UBYTE reserved_a;
  150.     UBYTE reserved_b;
  151.     UBYTE lotsofbits;
  152.     UBYTE vendor[8];
  153.     UBYTE prod_id[16];
  154.     UBYTE revision[4];
  155.     UBYTE specific[20];
  156.     UBYTE reserved[40];
  157. };
  158.  
  159. struct ReadTOC
  160. {
  161.     UBYTE cmd;
  162.     UBYTE misc;
  163.     ULONG reserved;
  164.     UBYTE starttrack;
  165.     UBYTE alloclenHI;
  166.     UBYTE alloclenLO;
  167.     UBYTE control;
  168. };
  169.  
  170. struct TrackDesc
  171. {
  172.     UBYTE reserved;
  173.     UBYTE adrctrl;
  174.     UBYTE trackno;
  175.     UBYTE reserved2;
  176.     ULONG lba;
  177. };
  178.  
  179. struct TOCData
  180. {
  181.     UWORD length;
  182.     UBYTE lowtrack;
  183.     UBYTE hightrack;
  184.     struct TrackDesc desc[100];
  185. };
  186.  
  187. struct SenseData
  188. {
  189.     UBYTE errcode;
  190.     UBYTE segnum;
  191.     UBYTE sensekey;
  192.     UBYTE information[4];
  193.     UBYTE addlength;
  194.     UBYTE specificinfo[4];
  195.     UWORD additionalsense;
  196.     UBYTE unitcode;
  197.     UBYTE sensekeyspec[3];
  198.     UBYTE space[20];
  199. };
  200.  
  201.  
  202. /* SCSI command and data bytes (somewhat pre-initialized) */
  203.  
  204. struct SenseData SyncSenseData;
  205.  
  206. struct Read12 Read12= { 0xA8, 0x00, 0, 0, 0, 0 };
  207.  
  208. struct InquiryData InquiryData;
  209. struct Inquiry Inquiry={0x12, 0x00, 0, 0, sizeof(InquiryData), 0};
  210.  
  211. struct ModeData OldModePage;
  212. struct ModeData NewModePage={0,0,0,8, 0x82,0,0,0,CDDA_BLOCKSIZE};
  213.  
  214. struct ModeSense  ModeSense ={0x1A,    0, 1, 0, sizeof(OldModePage), 0};
  215. struct ModeSelect ModeSelect={0x15, 0x10, 0, 0, sizeof(NewModePage), 0};
  216.  
  217. struct TOCData TOCData;
  218. struct ReadTOC ReadTOC={0x43, 0, 0, 0, sizeof(TOCData)>>8, sizeof(TOCData)&0xff, 0};
  219.  
  220.  
  221. UBYTE *Template="TRACK/N/A,NUMTRACKS/K/N,TO/K/A,BITS/K/N,DEVICE/K,UNIT/K/N,MAXIMIZE/S,BOOST/K/N";
  222.  
  223. struct ArgArray
  224. {
  225.     ULONG *aa_Track;
  226.     ULONG *aa_NumTracks;
  227.     UBYTE *aa_To;
  228.     ULONG *aa_Bits;
  229.     UBYTE *aa_Device;
  230.     ULONG *aa_Unit;
  231.     ULONG  aa_Maximize;
  232.     ULONG *aa_Boost;
  233. };
  234.  
  235. struct ArgArray AA;
  236. struct RDArgs *RDArgs;
  237. UBYTE ProgName[60];
  238.  
  239. UBYTE *ReadBuffer;
  240. UBYTE *StreamBuffer;
  241. UBYTE *ADPCMBuffer;
  242.  
  243.  
  244. /*******************************************************************************/
  245.  
  246.  
  247. /* void __saveds main() */
  248.  
  249. LONG __saveds main()
  250. {
  251.     UBYTE *DeviceName="scsi.device";
  252.     ULONG DeviceUnit=3;
  253.     ULONG Bits=2;
  254.     ULONG NumTracks=1;
  255.     LONG Boost=100;
  256.     
  257.     if (DOSBase=(struct DosLibrary*)OpenLibrary("dos.library",37))
  258.     {
  259.         if (!GetProgramName(ProgName,sizeof(ProgName))) strcpy(ProgName,"CDRipper");
  260.         
  261.         if (!(RDArgs=ReadArgs(Template,(LONG *)&AA,0)))
  262.         {
  263.             PrintFault(IoErr(),ProgName);
  264.         }
  265.         else
  266.         {
  267.             if (AA.aa_NumTracks) NumTracks= *AA.aa_NumTracks;
  268.             if (AA.aa_Device) DeviceName=AA.aa_Device;
  269.             if (AA.aa_Unit) DeviceUnit= *AA.aa_Unit;
  270.             if (AA.aa_Bits) Bits= *AA.aa_Bits;
  271.             if (AA.aa_Boost) Boost= *AA.aa_Boost;
  272.             
  273.             if (Bits != 2 && Bits != 3)
  274.             {
  275.                 Printf("Illegal bit number. Use 2 for ADPCM2 and 3 for ADPCM3.\n");
  276.             }
  277.             else
  278.             {
  279.                 if (OpenSCSI(DeviceName, DeviceUnit))
  280.                 {
  281.                     RipTrack(*AA.aa_Track, NumTracks, AA.aa_To, Bits, (BOOL)AA.aa_Maximize, Boost);
  282.                     
  283.                     CloseSCSI();
  284.                 }
  285.             }
  286.             FreeArgs(RDArgs);
  287.         }
  288.         CloseLibrary(DOSBase);
  289.     }
  290. }
  291.  
  292.  
  293. /* Rip CD audio data */
  294.  
  295. void RipTrack(ULONG Track, ULONG NumTracks, UBYTE *ToFile, ULONG Bits, BOOL Maximize, LONG Boost)
  296. {
  297.     BPTR File;
  298.     ULONG LBA;
  299.     ULONG StartLBA;
  300.     ULONG EndLBA;
  301.     ULONG StreamLen;
  302.     ULONG ADPCMLen;
  303.     ULONG JoinCode=0;
  304.     BOOL Break=FALSE;
  305.     LONG MaxVal=32768;
  306.     LONG ScaleFact=Boost*1024/100;
  307.     
  308.     /* Calculate stream sizes based on buffer size */
  309.     StreamLen=BUFBLOCKS*CDDA_BLOCKSIZE/8;
  310.     if (Bits==2) ADPCMLen=(StreamLen+3)/4;
  311.     if (Bits==3) ADPCMLen=(StreamLen+7)/8*3;
  312.     
  313.     StartLBA=TOCData.desc[Track-1].lba;
  314.     EndLBA=TOCData.desc[Track-1+NumTracks].lba-1;
  315.     
  316.     if (!(File=Open(ToFile,MODE_NEWFILE)))
  317.     {
  318.         Printf("Error cannot open '%s'.\n",ToFile);
  319.     }
  320.     else
  321.     {
  322.         ULONG Frequency=22050;
  323.         
  324.         if (Bits==2) Write(File,"ADPCM2", 6);
  325.         if (Bits==3) Write(File,"ADPCM3", 6);
  326.         
  327.         Write(File,&Frequency, sizeof(Frequency));
  328.         
  329.         if (ReadBuffer=AllocVec(BUFBLOCKS*CDDA_BLOCKSIZE,MEMF_CLEAR))
  330.         {
  331.             if (StreamBuffer=AllocVec(StreamLen,MEMF_CLEAR))
  332.             {
  333.                 if (ADPCMBuffer=AllocVec(ADPCMLen,MEMF_CLEAR))
  334.                 {
  335.                     if (Maximize)
  336.                     {
  337.                         MaxVal=0;
  338.                         
  339.                         for (LBA=StartLBA; LBA<EndLBA; )
  340.                         {
  341.                             UBYTE *ptr;
  342.                             ULONG Left=EndLBA-LBA;
  343.                             ULONG NumBlocks = Left < BUFBLOCKS ? Left : BUFBLOCKS;
  344.                             UWORD i;
  345.                             
  346.                             Printf("\rMaximize run (%02ld%%)",100*(LBA-StartLBA)/(EndLBA-StartLBA));
  347.                             
  348.                             /* Calculate stream sizes based on read blocks */
  349.                             StreamLen=NumBlocks*CDDA_BLOCKSIZE/8;
  350.                             
  351.                             /* Init LBA and LBN */
  352.                             Read12.lba=LBA;
  353.                             Read12.lbn=NumBlocks;
  354.                             
  355.                             /* start synchronous reading */
  356.                             DoSCSI(    &SyncSCSI_IO,
  357.                                     &Read12, sizeof(Read12),
  358.                                     ReadBuffer, NumBlocks*CDDA_BLOCKSIZE,
  359.                                     SCSIF_READ, FALSE, "reading CD-DA block");
  360.                             
  361.                             ptr=ReadBuffer;
  362.                             
  363.                             for(i=0 ; i<StreamLen ; i++ , ptr+=8)
  364.                             {
  365.                                 LONG sample=( (WORD)(*(ptr+1)<<8) | *(ptr+0)) +
  366.                                             ( (WORD)(*(ptr+3)<<8) | *(ptr+2)) +
  367.                                             ( (WORD)(*(ptr+5)<<8) | *(ptr+4)) +
  368.                                             ( (WORD)(*(ptr+7)<<8) | *(ptr+6)) ;
  369.                                 sample=sample>>2;
  370.                                 if (sample<0) sample= -sample;
  371.                                 if (sample>MaxVal) MaxVal=sample;
  372.                             }
  373.                             
  374.                             LBA+=NumBlocks;
  375.                             
  376.                             if (CheckSignal(SIGBREAKF_CTRL_C))
  377.                             {
  378.                                 PrintFault(ERROR_BREAK,NULL);
  379.                                 Break=TRUE;
  380.                                 break;
  381.                             }
  382.                         }
  383.                     }
  384.                     
  385.                     if (!Break)
  386.                     {
  387.                         if (MaxVal!=32768)
  388.                         {
  389.                             Printf("\rMaximizing by %ld%%.\n",(ULONG)100*32768/MaxVal);
  390.                         }
  391.                         
  392.                         for (LBA=StartLBA; LBA<EndLBA; )
  393.                         {
  394.                             UBYTE *ptr;
  395.                             BYTE *dest;
  396.                             ULONG Left=EndLBA-LBA;
  397.                             ULONG NumBlocks = Left < BUFBLOCKS ? Left : BUFBLOCKS;
  398.                             UWORD i;
  399.                             
  400.                             Printf("\rLoading/compressing (%02ld%%)",100*(LBA-StartLBA)/(EndLBA-StartLBA));
  401.                             
  402.                             /* Calculate stream sizes based on read blocks */
  403.                             StreamLen=NumBlocks*CDDA_BLOCKSIZE/8;
  404.                             if (Bits==2) ADPCMLen=(StreamLen+3)/4;
  405.                             if (Bits==3) ADPCMLen=(StreamLen+7)/8*3;
  406.                             
  407.                             /* Init LBA and LBN */
  408.                             Read12.lba=LBA;
  409.                             Read12.lbn=NumBlocks;
  410.                             
  411.                             /* start synchronous reading */
  412.                             DoSCSI(    &SyncSCSI_IO,
  413.                                     &Read12, sizeof(Read12),
  414.                                     ReadBuffer, NumBlocks*CDDA_BLOCKSIZE,
  415.                                     SCSIF_READ, FALSE, "reading CD-DA block");
  416.                             
  417.                             ptr=ReadBuffer;
  418.                             dest=StreamBuffer;
  419.                             
  420.                             for(i=0 ; i<StreamLen ; i++ , ptr+=8)
  421.                             {
  422.                                 LONG sample=( (WORD)(*(ptr+1)<<8) | *(ptr+0)) +
  423.                                             ( (WORD)(*(ptr+3)<<8) | *(ptr+2)) +
  424.                                             ( (WORD)(*(ptr+5)<<8) | *(ptr+4)) +
  425.                                             ( (WORD)(*(ptr+7)<<8) | *(ptr+6)) ;
  426.                                 sample=sample>>2;
  427.                                 
  428.                                 if (MaxVal!=32768)
  429.                                 {
  430.                                     sample=(sample<<15)/MaxVal;
  431.                                 }
  432.                                 
  433.                                 if (ScaleFact!=1024)
  434.                                 {
  435.                                     sample=(sample*ScaleFact)>>10;
  436.                                 }
  437.                                 
  438.                                 sample=sample>>8;
  439.                                 if (sample>127) sample= 127;
  440.                                 if (sample<-128) sample= -128;
  441.                                 *dest++=sample;
  442.                             }
  443.                             
  444.                             if (Bits==2) JoinCode=CompressADPCM2(StreamBuffer, StreamLen, ADPCMBuffer, JoinCode);
  445.                             if (Bits==3) JoinCode=CompressADPCM3(StreamBuffer, StreamLen, ADPCMBuffer, JoinCode);
  446.                             
  447.                             Write(File,ADPCMBuffer,ADPCMLen);
  448.                             
  449.                             LBA+=NumBlocks;
  450.                             
  451.                             if (CheckSignal(SIGBREAKF_CTRL_C))
  452.                             {
  453.                                 PrintFault(ERROR_BREAK,NULL);
  454.                                 Break=TRUE;
  455.                                 break;
  456.                             }
  457.                         }
  458.                     }
  459.                     Printf("\rLoading/compressing finished\n");
  460.                 }
  461.                 FreeVec(StreamBuffer);
  462.             }
  463.             FreeVec(ReadBuffer);
  464.         }
  465.         Close(File);
  466.     }
  467. }
  468.  
  469.  
  470. /* Open and initialize CDRom */
  471.  
  472. BOOL OpenSCSI(UBYTE *Device, ULONG Unit)
  473. {
  474.     BOOL Success=FALSE;
  475.     
  476.     /* Init synchronous SCSI IO */
  477.     
  478.     SyncReplyPort.mp_Node.ln_Type=NT_MSGPORT;
  479.     SyncReplyPort.mp_Flags=PA_SIGNAL;
  480.     SyncReplyPort.mp_SigTask=FindTask(NULL);
  481.     NewList(&SyncReplyPort.mp_MsgList);
  482.     
  483.     if ((SyncSigBit=SyncReplyPort.mp_SigBit=AllocSignal(-1))!=-1)
  484.     {
  485.         SyncSCSI_IO.io_Message.mn_Node.ln_Type=NT_MESSAGE;
  486.         SyncSCSI_IO.io_Message.mn_Length=sizeof(struct IOStdReq);
  487.         
  488.         SyncSCSI_IO.io_Message.mn_ReplyPort= &SyncReplyPort;
  489.         SyncSCSI_IO.io_Data= &SyncSCSICmd;
  490.         
  491.         SyncSCSICmd.scsi_SenseData=(UBYTE*)&SyncSenseData;
  492.         SyncSCSICmd.scsi_SenseLength=sizeof(SyncSenseData);
  493.         
  494.         if (OpenDevice(Device,Unit,(struct IORequest*)&SyncSCSI_IO,0))
  495.         {
  496.             Message("Cannot open '%s' unit %ld.",Device,Unit);
  497.         }
  498.         else
  499.         {
  500.             if (DoSCSI(&SyncSCSI_IO, &Inquiry, sizeof(Inquiry), &InquiryData, sizeof(InquiryData), SCSIF_READ, FALSE, "reading inquiry data"))
  501.             {
  502.                 if (InquiryData.pdevtype != 5)
  503.                 {
  504.                     Message("'%s' unit %ld is not a CDRom!",Device,Unit);
  505.                 }
  506.                 else
  507.                 {
  508.                     /* Read Table of Contents */
  509.                     if (!(DoSCSI(&SyncSCSI_IO, &ReadTOC, sizeof(ReadTOC), &TOCData, sizeof(TOCData), SCSIF_READ, FALSE, "reading table of contents")))
  510.                     {
  511.                         Message("Cannot read Table of Contents!");
  512.                     }
  513.                     else
  514.                     {
  515.                         /* Prepare CDRom for CDDA data transfer */
  516.                         DoSCSI(&SyncSCSI_IO, &ModeSense, sizeof(ModeSense), &OldModePage, sizeof(OldModePage), SCSIF_READ, FALSE, "reading mode page");
  517.                         DoSCSI(&SyncSCSI_IO, &ModeSelect, sizeof(ModeSelect), &NewModePage, sizeof(NewModePage), SCSIF_WRITE, FALSE, "selecting CD-DA data format");
  518.                         
  519.                         Success=TRUE;
  520.                     }
  521.                 }
  522.             }
  523.         }
  524.     }
  525.     if (!Success) CloseSCSI();
  526.     
  527.     return(Success);
  528. }
  529.  
  530.  
  531. /*******************************************************************************/
  532.  
  533. /* Reset and close CDRom */
  534.  
  535. void CloseSCSI(void)
  536. {
  537.     if (SyncSCSI_IO.io_Device)
  538.     {
  539.         /* Reset CDRom transfer mode */
  540.         if (OldModePage.mode_data_length>0)
  541.         {
  542.             OldModePage.mode_data_length=0;
  543.             DoSCSI(&SyncSCSI_IO, &ModeSelect, sizeof(ModeSelect), &OldModePage, sizeof(OldModePage), SCSIF_WRITE, FALSE, "resetting data format");
  544.         }
  545.         CloseDevice((struct IORequest*)&SyncSCSI_IO);
  546.         SyncSCSI_IO.io_Device=NULL;
  547.     }
  548.     if (SyncSigBit!=-1)
  549.     {
  550.         FreeSignal(SyncSigBit);
  551.         SyncSigBit= -1;
  552.     }
  553. }
  554.  
  555.  
  556. /* Execute a SCSI command (synchronous or asynchronous) */
  557.  
  558. UBYTE* SenseKeys[]=
  559. {
  560.     "NO SENSE",
  561.     "RECOVERED ERROR",
  562.     "NOT READY",
  563.     "MEDIUM ERROR",
  564.     "HARDWARE ERRROR",
  565.     "ILLEGAL REQUEST",
  566.     "UNIT ATTENTION",
  567.     "DATA PROTECT",
  568.     "BLANK CHECK",
  569.     "VENDOR-SPECIFIC",
  570.     "COPY ABORTED",
  571.     "ABORTED COMMAND",
  572.     "EQUAL",
  573.     "VOLUME OVERFLOW",
  574.     "MISCOMPARE",
  575.     "RESERVED"
  576. };
  577.  
  578. struct ErrorDefinition
  579. {
  580.     UWORD ErrorCode;
  581.     UBYTE *ErrorName;
  582. };
  583.  
  584.  
  585. struct ErrorDefinition ErrorTable[]=
  586. {
  587.     0x1300,"ADDRESS MARK NOT FOUND FOR DATA FIELD",
  588.     0x1200,"ADDRESS MARK NOT FOUND FOR ID FIELD",
  589.     0x0011,"AUDIO PLAY OPERATION IN PROGRESS",
  590.     0x0012,"AUDIO PLAY OPERATION PAUSED",
  591.     0x0014,"AUDIO PLAY OPERATION STOPPED DUE TO ERROR",
  592.     0x0013,"AUDIO PLAY OPERATION SUCCESSFULLY COMPLETED",
  593.     0x0004,"BEGINNING-OF-PARTITION/MEDIUM DETECTED",
  594.     0x1404,"BLOCK SEQUENCE ERROR",
  595.     0x3002,"CANNOT READ MEDIUM - INCOMPATIBLE FORMAT",
  596.     0x3001,"CANNOT READ MEDIUM - UNKNOWN FORMAT",
  597.     0x5200,"CARTRIDGE FAULT",
  598.     0x3F02,"CHANGED OPERATING DEFINITION",
  599.     0x1106,"CIRC UNRECOVERED ERROR",
  600.     0x3003,"CLEANING CARTRIDGE INSTALLED",
  601.     0x4A00,"COMMAND PHASE ERROR",
  602.     0x2C00,"COMMAND SEQUENCE ERROR",
  603.     0x2F00,"COMMANDS CLEARED BY ANOTHER INITIATOR",
  604.     0x2B00,"COPY CANNOT EXECUTE SINCE HOST CANNOT DISCONNECT",
  605.     0x4100,"DATA PATH FAILURE",
  606.     0x4B00,"DATA PHASE ERROR",
  607.     0x1107,"DATA RESYCHRONIZATION ERROR",
  608.     0x1600,"DATA SYNCHRONIZATION MARK ERROR",
  609.     0x1900,"DEFECT LIST ERROR",
  610.     0x1903,"DEFECT LIST ERROR IN GROWN LIST",
  611.     0x1902,"DEFECT LIST ERROR IN PRIMARY LIST",
  612.     0x1901,"DEFECT LIST NOT AVAILABLE",
  613.     0x1C00,"DEFECT LIST NOT FOUND",
  614.     0x3201,"DEFECT LIST UPDATE FAILURE",
  615.     0x6300,"END OF USER AREA ENCOUNTERED ON THIS TRACK",
  616.     0x0005,"END-OF-DATA DETECTED",
  617.     0x1403,"END-OF-DATA NOT FOUND",
  618.     0x0002,"END-OF-PARTITION/MEDIUM DETECTED",
  619.     0x5100,"ERASE FAILURE",
  620.     0x0A00,"ERROR LOG OVERFLOW",
  621.     0x1102,"ERROR TOO LONG TO CORRECT",
  622.     0x0302,"EXCESSIVE WRITE ERRORS",
  623.     0x3B07,"FAILED TO SENSE BOTTOM-OF-FORM",
  624.     0x3B06,"FAILED TO SENSE TOP-OF-FORM",
  625.     0x0001,"FILEMARK DETECTED",
  626.     0x1402,"FILEMARK OR SETMARK NOT FOUND",
  627.     0x0902,"FOCUS SERVO FAILURE",
  628.     0x3101,"FORMAT COMMAND FAILED",
  629.     0x5800,"GENERATION DOES NOT EXIST",
  630.     0x1C02,"GROWN DEFECT LIST NOT FOUND",
  631.     0x0006,"I/O PROCESS TERMINATED",
  632.     0x1000,"ID CRC OR ECC ERROR",
  633.     0x2200,"ILLEGAL FUNCTION",
  634.     0x6400,"ILLEGAL MODE FOR THIS TRACK",
  635.     0x2801,"IMPORT OR EXPORT ELEMENT ACCESSED",
  636.     0x3000,"INCOMPATIBLE MEDIUM INSTALLED",
  637.     0x1108,"INCOMPLETE BLOCK READ",
  638.     0x4800,"INITIATOR DETECTED ERROR MESSAGE RECEIVED",
  639.     0x3F03,"INQUIRY DATA HAS CHANGED",
  640.     0x4400,"INTERNAL TARGET FAILURE",
  641.     0x3D00,"INVALID BITS IN IDENTIFY MESSAGE",
  642.     0x2C02,"INVALID COMBINATION OF WINDOWS SPECIFIED",
  643.     0x2000,"INVALID COMMAND OPERATION CODE",
  644.     0x2101,"INVALID ELEMENT ADDRESS",
  645.     0x2400,"INVALID FIELD IN CDB",
  646.     0x2600,"INVALID FIELD IN PARAMETER LIST",
  647.     0x4900,"INVALID MESSAGE ERROR",
  648.     0x1105,"L-EC UNCORRECTABLE ERROR",
  649.     0x6000,"LAMP FAILURE",
  650.     0x5B02,"LOG COUNTER AT MAXIMUM",
  651.     0x5B00,"LOG EXCEPTION",
  652.     0x5B03,"LOG LIST CODES EXHAUSTED",
  653.     0x2A02,"LOG PARAMETERS CHANGED",
  654.     0x2100,"LOGICAL BLOCK ADDRESS OUT OF RANGE",
  655.     0x0800,"LOGICAL UNIT COMMUNICATION FAILURE",
  656.     0x0802,"LOGICAL UNIT COMMUNICATION PARITY ERROR",
  657.     0x0801,"LOGICAL UNIT COMMUNICATION TIME-OUT",
  658.     0x0500,"LOGICAL UNIT DOES NOT RESPOND TO SELECTION",
  659.     0x4C00,"LOGICAL UNIT FAILED SELF-CONFIGURATION",
  660.     0x3E00,"LOGICAL UNIT HAS NOT SELF-CONFIGURED YET",
  661.     0x0401,"LOGICAL UNIT IS IN PROCESS OF BECOMING READY",
  662.     0x0400,"LOGICAL UNIT NOT READY, CAUSE NOT REPORTABLE",
  663.     0x0404,"LOGICAL UNIT NOT READY, FORMAT IN PROGRESS",
  664.     0x0402,"LOGICAL UNIT NOT READY, INITIALIZING COMMAND REQUIRED",
  665.     0x0403,"LOGICAL UNIT NOT READY, MANUAL INTERVENTION REQUIRED",
  666.     0x2500,"LOGICAL UNIT NOT SUPPORTED",
  667.     0x1501,"MECHANICAL POSITIONING ERROR",
  668.     0x5300,"MEDIA LOAD OR EJECT FAILED",
  669.     0x3B0D,"MEDIUM DESTINATION ELEMENT FULL",
  670.     0x3100,"MEDIUM FORMAT CORRUPTED",
  671.     0x3A00,"MEDIUM NOT PRESENT",
  672.     0x5302,"MEDIUM REMOVAL PREVENTED",
  673.     0x3B0E,"MEDIUM SOURCE ELEMENT EMPTY",
  674.     0x4300,"MESSAGE ERROR",
  675.     0x3F01,"MICROCODE HAS BEEN CHANGED",
  676.     0x1D00,"MISCOMPARE DURING VERIFY OPERATION",
  677.     0x110A,"MISCORRECTED ERROR",
  678.     0x2A01,"MODE PARAMETERS CHANGED",
  679.     0x0700,"MULTIPLE PERIPHERAL DEVICES SELECTED",
  680.     0x1103,"MULTIPLE READ ERRORS",
  681.     0x0000,"NO ADDITIONAL SENSE INFORMATION",
  682.     0x0015,"NO CURRENT AUDIO STATUS TO RETURN",
  683.     0x3200,"NO DEFECT SPARE LOCATION AVAILABLE",
  684.     0x1109,"NO GAP FOUND",
  685.     0x0100,"NO INDEX/SECTOR SIGNAL",
  686.     0x0600,"NO REFERENCE POSITION FOUND",
  687.     0x0200,"NO SEEK COMPLETE",
  688.     0x0301,"NO WRITE CURRENT",
  689.     0x2800,"NOT READY TO READY TRANSITION (MEDIUM MAY HAVE CHANGED)",
  690.     0x5A01,"OPERATOR MEDIUM REMOVAL REQUEST",
  691.     0x5A00,"OPERATOR REQUEST OR STATE CHANGE INPUT (UNSPECIFIED)",
  692.     0x5A03,"OPERATOR SELECTED WRITE PERMIT",
  693.     0x5A02,"OPERATOR SELECTED WRITE PROTECT",
  694.     0x6102,"OUT OF FOCUS",
  695.     0x4E00,"OVERLAPPED COMMANDS ATTEMPTED",
  696.     0x2D00,"OVERWRITE ERROR ON UPDATE IN PLACE",
  697.     0x3B05,"PAPER JAM",
  698.     0x1A00,"PARAMETER LIST LENGTH ERROR",
  699.     0x2601,"PARAMETER NOT SUPPORTED",
  700.     0x2602,"PARAMETER VALUE INVALID",
  701.     0x2A00,"PARAMETERS CHANGED",
  702.     0x0300,"PERIPHERAL DEVICE WRITE FAULT",
  703.     0x5002,"POSITION ERROR RELATED TO TIMING",
  704.     0x3B0C,"POSITION PAST BEGINNING OF MEDIUM",
  705.     0x3B0B,"POSITION PAST END OF MEDIUM",
  706.     0x1502,"POSITIONING ERROR DETECTED BY READ OF MEDIUM",
  707.     0x2900,"POWER ON, RESET, OR BUS DEVICE RESET OCCURRED",
  708.     0x4200,"POWER-ON OR SELF-TEST FAILURE",
  709.     0x1C01,"PRIMARY DEFECT LIST NOT FOUND",
  710.     0x4000,"RAM FAILURE",
  711.     0x1500,"RANDOM POSITIONING ERROR",
  712.     0x3B0A,"READ PAST BEGINNING OF MEDIUM",
  713.     0x3B09,"READ PAST END OF MEDIUM",
  714.     0x1101,"READ RETRIES EXHAUSTED",
  715.     0x1401,"RECORD NOT FOUND",
  716.     0x1400,"RECORDED ENTITY NOT FOUND",
  717.     0x1802,"RECOVERED DATA - DATA AUTO-REALLOCATED",
  718.     0x1805,"RECOVERED DATA - RECOMMEND REASSIGNMENT",
  719.     0x1705,"RECOVERED DATA USING PREVIOUS SECTOR ID",
  720.     0x1803,"RECOVERED DATA WITH CIRC",
  721.     0x1801,"RECOVERED DATA WITH ERROR CORRECTION AND RETRIES APPLIED",
  722.     0x1800,"RECOVERED DATA WITH ERROR CORRECTION APPLIED",
  723.     0x1804,"RECOVERED DATA WITH LEC",
  724.     0x1703,"RECOVERED DATA WITH NEGATIVE HEAD OFFSET",
  725.     0x1700,"RECOVERED DATA WITH NO ERROR CORRECTION APPLIED",
  726.     0x1702,"RECOVERED DATA WITH POSITIVE HEAD OFFSET",
  727.     0x1701,"RECOVERED DATA WITH RETRIES",
  728.     0x1704,"RECOVERED DATA WITH RETRIES AND/OR CIRC APPLIED",
  729.     0x1706,"RECOVERED DATA WITHOUT ECC - DATA AUTO-REALLOCATED",
  730.     0x1707,"RECOVERED DATA WITHOUT ECC - RECOMMEND REASSIGNMENT",
  731.     0x1E00,"RECOVERED ID WITH ECC CORRECTION",
  732.     0x3B08,"REPOSITION ERROR",
  733.     0x3600,"RIBBON, INK, OR TONER FAILURE",
  734.     0x3700,"ROUNDED PARAMETER",
  735.     0x5C00,"RPL STATUS CHANGE",
  736.     0x3900,"SAVING PARAMETERS NOT SUPPORTED",
  737.     0x6200,"SCAN HEAD POSITIONING ERROR",
  738.     0x4700,"SCSI PARITY ERROR",
  739.     0x5400,"SCSI TO HOST SYSTEM INTERFACE FAILURE",
  740.     0x4500,"SELECT OR RESELECT FAILURE",
  741.     0x3B00,"SEQUENTIAL POSITIONING ERROR",
  742.     0x0003,"SETMARK DETECTED",
  743.     0x3B04,"SLEW FAILURE",
  744.     0x0903,"SPINDLE SERVO FAILURE",
  745.     0x5C02,"SPINDLES NOT SYNCHRONIZED",
  746.     0x5C01,"SPINDLES SYNCHRONIZED",
  747.     0x1B00,"SYNCHRONOUS DATA TRANSFER ERROR",
  748.     0x5500,"SYSTEM RESOURCE FAILURE",
  749.     0x3300,"TAPE LENGTH ERROR",
  750.     0x3B03,"TAPE OR ELECTRONIC VERTICAL FORMS UNIT NOT READY",
  751.     0x3B01,"TAPE POSITION ERROR AT BEGINNING-OF-MEDIUM",
  752.     0x3B02,"TAPE POSITION ERROR AT END-OF-MEDIUM",
  753.     0x3F00,"TARGET OPERATING CONDITIONS HAVE CHANGED",
  754.     0x5B01,"THRESHOLD CONDITION MET",
  755.     0x2603,"THRESHOLD PARAMETERS NOT SUPPORTED",
  756.     0x2C01,"TOO MANY WINDOWS SPECIFIED",
  757.     0x0900,"TRACK FOLLOWING ERROR",
  758.     0x0901,"TRACKING SERVO FAILURE",
  759.     0x6101,"UNABLE TO ACQUIRE VIDEO",
  760.     0x5700,"UNABLE TO RECOVER TABLE-OF-CONTENTS",
  761.     0x5301,"UNLOAD TAPE FAILURE",
  762.     0x1100,"UNRECOVERED READ ERROR",
  763.     0x1104,"UNRECOVERED READ ERROR - AUTO REALLOCATE FAILED",
  764.     0x110B,"UNRECOVERED READ ERROR - RECOMMEND REASSIGNMENT",
  765.     0x110C,"UNRECOVERED READ ERROR - RECOMMEND REWRITE THE DATA",
  766.     0x4600,"UNSUCCESSFUL SOFT RESET",
  767.     0x5900,"UPDATED BLOCK READ",
  768.     0x6100,"VIDEO ACQUISITION ERROR",
  769.     0x5000,"WRITE APPEND ERROR",
  770.     0x5001,"WRITE APPEND POSITION ERROR",
  771.     0x0C00,"WRITE ERROR",
  772.     0x0C02,"WRITE ERROR - AUTO REALLOCATION FAILED",
  773.     0x0C01,"WRITE ERROR RECOVERED WITH AUTO REALLOCATION",
  774.     0x2700,"WRITE PROTECTED",
  775.     0xFFFF,"UNKNOWN ERROR CODE"
  776. };
  777.  
  778.  
  779. ULONG DoSCSI(struct IOStdReq *IORequest, APTR Command, ULONG CommandLength, APTR Buffer, ULONG Length, ULONG Flags, BOOL Asynchronous, UBYTE *ActivityName)
  780. {
  781.     struct SCSICmd *Cmd=(struct SCSICmd*)IORequest->io_Data;
  782.     
  783.     /* loop forever */
  784.     for (;;)
  785.     {
  786.         Cmd->scsi_Command=Command;
  787.         Cmd->scsi_CmdLength=CommandLength;
  788.         Cmd->scsi_Data=Buffer;
  789.         Cmd->scsi_Length=Length;
  790.         Cmd->scsi_Flags=Flags;
  791.         Cmd->scsi_Actual=
  792.         Cmd->scsi_CmdActual=
  793.         Cmd->scsi_SenseActual=0;
  794.         
  795.         if (Cmd->scsi_SenseData)
  796.         {
  797.             Cmd->scsi_Flags |= SCSIF_AUTOSENSE;
  798.         }
  799.         
  800.         IORequest->io_Flags=0;
  801.         IORequest->io_Length=sizeof(struct SCSICmd);
  802.         IORequest->io_Command=HD_SCSICMD;
  803.         
  804.         if (Asynchronous)
  805.         {
  806.             BeginIO(IORequest);
  807.             break;
  808.         }
  809.         else
  810.         {
  811.             DoIO(IORequest);
  812.             
  813.             if (Cmd->scsi_SenseActual)
  814.             {
  815.                 struct EasyStruct Req={    sizeof (struct EasyStruct),
  816.                                         0,
  817.                                         "SCSI error",
  818.                                         "SCSI unit reports error while %s\n%s: %s",
  819.                                         "Retry|Cancel"};
  820.                 
  821.                 struct SenseData *SD;
  822.                 if (SD=(struct SenseData*)Cmd->scsi_SenseData)
  823.                 {
  824.                     BOOL OpenIntui=FALSE;
  825.                     UBYTE *KeyName=SenseKeys[SD->sensekey&0xf];
  826.                     UBYTE *AddName="NO ADDITIONAL ERROR CODE";
  827.                     
  828.                     if (SD->addlength>=6)
  829.                     {
  830.                         struct ErrorDefinition *ED;
  831.                         for(ED=ErrorTable;ED->ErrorCode!=0xffff;ED++)
  832.                         {
  833.                             if (ED->ErrorCode==SD->additionalsense) break;
  834.                         }
  835.                         AddName=ED->ErrorName;
  836.                     }
  837.                     
  838.                     if (!IntuitionBase)
  839.                     {
  840.                         IntuitionBase=(struct IntuitionBase*)OpenLibrary("intuition.library",37);
  841.                         OpenIntui=TRUE;
  842.                     }
  843.                     
  844.                     if (IntuitionBase)
  845.                     {
  846.                         if (!EasyRequest(NULL, &Req, NULL, ActivityName, KeyName, AddName))
  847.                         {
  848.                             break;
  849.                         }
  850.                     }
  851.                     
  852.                     if (IntuitionBase && OpenIntui)
  853.                     {
  854.                         CloseLibrary((struct Library*)IntuitionBase);
  855.                         IntuitionBase=NULL;
  856.                     }
  857.                 }
  858.             }
  859.             else break;
  860.         }
  861.     }
  862.     return(Cmd->scsi_Actual);
  863. }
  864.  
  865.  
  866. /*******************************************************************************/
  867.  
  868. /* Show a message to the user */
  869.  
  870. void __stdargs Message(UBYTE *Msg,...)
  871. {
  872.     va_list Arg;
  873.     struct EasyStruct Req={sizeof(struct EasyStruct),0,"CDRipper message",0,"Okay"};
  874.     Req.es_TextFormat=Msg;
  875.     va_start(Arg,Msg);
  876.     
  877.     if (IntuitionBase)
  878.     {
  879.         EasyRequestArgs(NULL,&Req,0,Arg);
  880.     }
  881.     else
  882.     {
  883.         VPrintf(Msg,Arg);
  884.         Printf("\n");
  885.     }
  886.     
  887.     va_end(Arg);
  888. }
  889.