#1 Burning Software

It is currently Thu Dec 19, 2024 9:49 am

All times are UTC




Post new topic Reply to topic  [ 6 posts ] 
Author Message
 Post subject: Multitrack DVD fix for Starburn
PostPosted: Wed May 16, 2007 4:59 pm 
Offline

Joined: Thu Jun 02, 2005 8:50 pm
Posts: 115
MMC5r04 sections:

section 6.26.1: For media other than CD, information may be fabricated in order to emulate a CD structure for the specific
media.

section 6.26.3.2.4 Table 482: Shows the fabricated information. DVDs will ALWAYS return 01 for number of tracks even if they have more than one track.

My fix was to write a replacement for GrabTrack and GetTOCInformation using Execute Generic. Using my GrabTrackEx command which doesn't use the TOC track number to limit what tracks I can grab I have been able to rip a multi track DVD and then using the normal Starburn TAO command to burn those multiple tracks to a DVD and get an exact copy of the original. Note my command does not currently use the IsBadBlockIgnore or IsSingleLBTransferForced because I'm not exactly sure what is ment by those settings. Also My GrabtrackEx does not use the Starburn_Callback and it doesn't callback on read retries or bad blocks because I haven't figured out how to determine when a read retry has happened or a bad block has been encountered. I'm hoping this proof of concept will get the Starburn programmers to modify their GrabTrack and GetTrackInformation commands to NOT be limited by the number of tracks listed in the TOC.

Code:
LONG CDVDBurnerGrabber::CalculateSpeed(LARGE_INTEGER Processed,LARGE_INTEGER &LBsProcessed)
{
   LBsProcessed.QuadPart=Processed.QuadPart-m_LastLB.QuadPart;

   LARGE_INTEGER CurrentTime;
   QueryPerformanceCounter(&CurrentTime);
   LARGE_INTEGER Time;
   Time.QuadPart=CurrentTime.QuadPart-m_LastTime.QuadPart;

   m_AverageLB.QuadPart+=LBsProcessed.QuadPart;
   m_AverageTime.QuadPart+=Time.QuadPart;

   LONG speed=0;
   if(m_LastTime.QuadPart!=0){
      double TimeUsed = (double)Time.QuadPart/(double)m_Freq.QuadPart;
      if(TimeUsed>0.0)
         speed = (LONG)((double(LBsProcessed.QuadPart * m_LBSize)/1024.0)/TimeUsed);
   }
   m_LastTime=CurrentTime;
   m_LastLB=Processed;

   return speed;
}

LONG CDVDBurnerGrabber::CalculateAverageSpeed()
{
   LONG speed=0;
   double TimeUsed = (double)m_AverageTime.QuadPart/(double)m_Freq.QuadPart;
   if(TimeUsed>0.0)
      speed = (LONG)((double(m_AverageLB.QuadPart * m_LBSize)/1024.0)/TimeUsed);
   m_AverageTime.QuadPart=0;
   m_AverageLB.QuadPart=0;

   return speed;
}

BOOL CDVDBurnerGrabber::SetReadWriteErrorRecoveryParameter(UCHAR *ReadRetry,
                                             UCHAR *WriteRetry,
                                             BOOL *AWRE,
                                             BOOL *ARRE,
                                             BOOL *TransferBlock,
                                             BOOL *ReadContinuous,
                                             BOOL *PostError,
                                             BOOL *DisableTransferOnError,
                                             BOOL *DisableCorrection,
                                             UCHAR *EMCDR,
                                             ULONG *ErrorReportingWindowSize)
{
    READ_WRITE_ERROR_RECOVERY_PARAMETERS_MODE_PAGE pmp, pmp_verify;

    if (!ModeSense(0x01, (void*) &pmp, sizeof(pmp)))
        return FALSE;

    pmp.ucPageCode = 0x01;
   if(ReadRetry)
      pmp.ucReadRetryCount=*ReadRetry;
   if(WriteRetry)
      pmp.ucWriteRetryCount=*WriteRetry;
   if(AWRE)
      pmp.AWRE=*AWRE;
   if(ARRE)
      pmp.ARRE=*ARRE;
   if(TransferBlock)
      pmp.TB=*TransferBlock;
   if(ReadContinuous)
      pmp.RC=*ReadContinuous;
   if(PostError)
      pmp.PER=*PostError;
   if(DisableTransferOnError)
      pmp.DTE=*DisableTransferOnError;
   if(DisableCorrection)
      pmp.DCR=*DisableCorrection;
   if(EMCDR)
      pmp.EMCDR=*EMCDR;
   if(ErrorReportingWindowSize){
       pmp.ucErrorReportingWindowSize[ 0 ] = HIBYTE( HIWORD( ErrorReportingWindowSize ) );
      pmp.ucErrorReportingWindowSize[ 1 ] = LOBYTE( HIWORD( ErrorReportingWindowSize ) );
      pmp.ucErrorReportingWindowSize[ 2 ] = HIBYTE( LOWORD( ErrorReportingWindowSize ) );
      pmp.ucErrorReportingWindowSize[ 3 ] = LOBYTE( LOWORD( ErrorReportingWindowSize ) );
   }

    CopyMemory(&pmp_verify, &pmp, sizeof(pmp));
    if (!ModeSelect((void*) &pmp, sizeof(pmp)))
        return FALSE;
    if (!ModeSense(0x01, (void*) &pmp, sizeof(pmp)))
        return FALSE;
    if (memcmp(&pmp_verify, &pmp, sizeof(pmp)))
        return FALSE;
    return TRUE;
}

BOOL CDVDBurnerGrabber::SetWriteParameter(UCHAR *WriteType,
                                BOOL *TestWrite,
                                BOOL *LS_V,
                                BOOL *BUFE,
                                UCHAR *TrackMode,
                                BOOL *Copy,
                                BOOL *FP,
                                UCHAR *MultiSession,
                                UCHAR *DataBlockType,
                                UCHAR *LinkSize,
                                UCHAR *HostApplicationCode,
                                UCHAR *SessionFormat,
                                ULONG *PacketSize,
                                UWORD *AudioPause,
                                UCHAR *MediaCatalogNumberArray,
                                UCHAR *ISRCArray,
                                UCHAR *SubHeaderByte0,
                                UCHAR *SubHeaderByte1,
                                UCHAR *SubHeaderByte2,
                                UCHAR *SubHeaderByte3)
{
    WRITE_PARAMETERS_MODE_PAGE pmp, pmp_verify;

    if (!ModeSense(0x05, (void*) &pmp, sizeof(pmp)))
        return FALSE;

    pmp.ucPageCode = 0x05;
   if(WriteType)
      pmp.WriteType=*WriteType;
   if(TestWrite)
      pmp.TestWrite=*TestWrite;
   if(LS_V)
      pmp.LS_V=*LS_V;
   if(BUFE)
      pmp.BUFE=*BUFE;
   if(TrackMode)
      pmp.TrackMode=*TrackMode;
   if(Copy)
      pmp.Copy=*Copy;
   if(FP)
      pmp.FP=*FP;
   if(MultiSession)
      pmp.MultiSession=*MultiSession;
   if(DataBlockType)
      pmp.DataBlockType=*DataBlockType;
   if(LinkSize)
      pmp.LinkSize=*LinkSize;
   if(HostApplicationCode)
      pmp.HostApplicationCode=*HostApplicationCode;
   if(SessionFormat)
      pmp.ucSessionFormat=*SessionFormat;
   if(PacketSize){
       pmp.ucPacketSize[ 0 ] = HIBYTE( HIWORD( PacketSize ) );
      pmp.ucPacketSize[ 1 ] = LOBYTE( HIWORD( PacketSize ) );
      pmp.ucPacketSize[ 2 ] = HIBYTE( LOWORD( PacketSize ) );
      pmp.ucPacketSize[ 3 ] = LOBYTE( LOWORD( PacketSize ) );
   }
   if(AudioPause){
      pmp.ucAudioPauseLength[ 0 ] = HIBYTE( LOWORD( AudioPause ) );
      pmp.ucAudioPauseLength[ 1 ] = LOBYTE( LOWORD( AudioPause ) );
   }
   if(MediaCatalogNumberArray){
      memcpy(pmp.ucMediaCatalogNumber,MediaCatalogNumberArray,16);
   }
   if(ISRCArray){
      memcpy(pmp.ucISRC,ISRCArray,16);
   }
   if(SubHeaderByte0)
      pmp.ucSubHeaderByte0=*SubHeaderByte0;
   if(SubHeaderByte1)
      pmp.ucSubHeaderByte1=*SubHeaderByte1;
   if(SubHeaderByte2)
      pmp.ucSubHeaderByte2=*SubHeaderByte2;
   if(SubHeaderByte3)
      pmp.ucSubHeaderByte3=*SubHeaderByte3;

    CopyMemory(&pmp_verify, &pmp, sizeof(pmp));
    if (!ModeSelect((void*) &pmp, sizeof(pmp)))
        return FALSE;
    if (!ModeSense(0x05, (void*) &pmp, sizeof(pmp)))
        return FALSE;
    if (memcmp(&pmp_verify, &pmp, sizeof(pmp)))
        return FALSE;
    return TRUE;
}

BOOL CDVDBurnerGrabber::ModeSense(unsigned char ucModePage, void* pBuffer, WORD wBufferSize)
{
   CDB_MODE_SENSE cdb;
   RtlZeroMemory(&cdb,sizeof(cdb));
    cdb.Operation_Code = 0x5A;   // Code for MODE SENSE (10) command
    cdb.PageCode = ucModePage;   // Bits7:6, 00=Current Values, 01=Changeable Values, 10=Default Values, 11=Saved Values
    cdb.SubpageCode = 0x00;      // Subpage not supported by MM devices.  Always set 0x00
    cdb.AllocLength[0] = HIBYTE(wBufferSize);
    cdb.AllocLength[1] = LOBYTE(wBufferSize);

   l__EXCEPTION_NUMBER =
      StarBurn_CdvdBurnerGrabber_ExecuteGeneric(
         l__PVOID__CdvdBurnerGrabber,
         ( PCHAR )( &l__CHAR__ExceptionText ),
         sizeof( l__CHAR__ExceptionText ),
         &l__ULONG__SystemError,
         &l__CDB_FAILURE_INFORMATION,
         ( PUCHAR )( &cdb ),
         sizeof( cdb ),
         ( PUCHAR )( pBuffer  ),
         wBufferSize,
         FALSE
         );

   if (l__EXCEPTION_NUMBER != EN_SUCCESS){
      return FALSE;
   }
    return TRUE;
}

BOOL CDVDBurnerGrabber::ModeSelect(void* pBuffer, WORD wBufferSize)
{
   CDB_MODE_SELECT cdb;
   RtlZeroMemory(&cdb,sizeof(cdb));
    cdb.Operation_Code = 0x55;   //Code for MODE SELECT (10) command
    cdb.PF = 1;               //Structured as page
    cdb.ParamLength[0] = HIBYTE(wBufferSize);
    cdb.ParamLength[1] = LOBYTE(wBufferSize);

   l__EXCEPTION_NUMBER =
      StarBurn_CdvdBurnerGrabber_ExecuteGeneric(
         l__PVOID__CdvdBurnerGrabber,
         ( PCHAR )( &l__CHAR__ExceptionText ),
         sizeof( l__CHAR__ExceptionText ),
         &l__ULONG__SystemError,
         &l__CDB_FAILURE_INFORMATION,
         ( PUCHAR )( &cdb ),
         sizeof( cdb ),
         ( PUCHAR )( pBuffer  ),
         wBufferSize,
         TRUE
         );

   if (l__EXCEPTION_NUMBER != EN_SUCCESS){
      return FALSE;
   }
    return TRUE;
}

#define TransferSizeInLBs 0x20

EXCEPTION_NUMBER
CDVDBurnerGrabber::StarBurn_CdvdBurnerGrabber_GrabTrackEx(PVOID CdvdBurnerGrabber,
                                            PCHAR ExceptionText,
                                            ULONG ExceptionTextSizeInUCHARs,
                                            PULONG SystemError,
                                            PCDB_FAILURE_INFORMATION CDB_FAILURE_INFORMATION,
                                            UCHAR TrackNumber,
                                            PCHAR FileName,
                                            LONG Retries,
                                            BOOLEAN IsBadBlockIgnore,
                                            BOOLEAN IsSingleLBTransferForced,
                                            ULONG ReadReportDelayInSeconds)
{
   UCHAR ReadRetry=Retries;
   SetReadWriteErrorRecoveryParameter(&ReadRetry,
                              NULL,
                              NULL,
                              NULL,
                              NULL,
                              NULL,
                              NULL,
                              NULL,
                              NULL,
                              NULL,
                              NULL);

   LARGE_INTEGER startLBA,currentLBA,lastLBA,totalLBs,readLBs;

   STARBURN_TRACK_INFORMATION trackinfo;
   int tracksize;
   RtlZeroMemory(     
      &trackinfo,
      sizeof(trackinfo)
      );
   if(GetTrackInformationEx(TrackNumber,&trackinfo,&tracksize)){
      totalLBs.QuadPart = tracksize;
      startLBA.QuadPart = currentLBA.QuadPart = trackinfo.m__LONG__TrackStartAddress;
      lastLBA.QuadPart = currentLBA.QuadPart+totalLBs.QuadPart;
      FILE *file = fopen(FileName,"wb");

      CDB_READ_10 cdb;
      DWORD databuffer[(2048*TransferSizeInLBs)/4];
      DWORD lasttime=GetTickCount();
      DWORD currenttime=lasttime;
      DWORD testunitreadyrun=0;
      while(currentLBA.QuadPart<lastLBA.QuadPart){
         if((lastLBA.QuadPart-currentLBA.QuadPart)>=TransferSizeInLBs){
            readLBs.QuadPart=TransferSizeInLBs;
         }
         else{
            readLBs.QuadPart=lastLBA.QuadPart-currentLBA.QuadPart;
         }
   
            RtlZeroMemory(&cdb,sizeof( cdb ));
         cdb.Operation_Code = 0x28; // SCSI_OPCODE_READ;
         //cdb.FUA = 0x1;
          cdb.LBA[ 0 ] = HIBYTE( HIWORD( currentLBA.QuadPart ) );
         cdb.LBA[ 1 ] = LOBYTE( HIWORD( currentLBA.QuadPart ) );
         cdb.LBA[ 2 ] = HIBYTE( LOWORD( currentLBA.QuadPart ) );
         cdb.LBA[ 3 ] = LOBYTE( LOWORD( currentLBA.QuadPart ) );
         cdb.AllocLength[ 0 ] = HIBYTE( LOWORD( readLBs.QuadPart ) );
         cdb.AllocLength[ 1 ] = LOBYTE( LOWORD( readLBs.QuadPart ) );

         RtlZeroMemory(&databuffer,sizeof( databuffer ));
         l__EXCEPTION_NUMBER =
            StarBurn_CdvdBurnerGrabber_ExecuteGeneric(
               l__PVOID__CdvdBurnerGrabber,
               ExceptionText,
               ExceptionTextSizeInUCHARs,
               SystemError,
                    CDB_FAILURE_INFORMATION,
               ( PUCHAR )( &cdb ),
               sizeof( cdb ),
               ( PUCHAR )( &databuffer ),
               sizeof( databuffer ),
               FALSE
               );

         if (l__EXCEPTION_NUMBER != EN_SUCCESS){
            fclose(file);
            return l__EXCEPTION_NUMBER;
         }

         fwrite(databuffer,sizeof( UCHAR ),(int)(2048*readLBs.QuadPart),file);
      
         LARGE_INTEGER junk,processed;
         processed.QuadPart = (currentLBA.QuadPart - startLBA.QuadPart);
         LONG speed = CalculateSpeed(processed,junk);

         if(speed<1352){
            l__EXCEPTION_NUMBER =
               StarBurn_CdvdBurnerGrabber_TestUnitReadyEx(
                     l__PVOID__CdvdBurnerGrabber,
                     ExceptionText,
                     ExceptionTextSizeInUCHARs,
                     SystemError,
                          CDB_FAILURE_INFORMATION,
                     1
                     );

            // Check for correct reply
            if ( l__EXCEPTION_NUMBER != EN_SUCCESS )
            {
               return l__EXCEPTION_NUMBER;
            }
         }

         currenttime=GetTickCount();
         if((currenttime-lasttime)>(ReadReportDelayInSeconds*1000)){
            ULONG percent = (ULONG)(((currentLBA.QuadPart-startLBA.QuadPart)*100)/totalLBs.QuadPart);
            LONG averagespeed = CalculateAverageSpeed();
            if(m_pCallback)
               if(!m_pCallback(m_Index,
                           m_Drive,
                           MODE_READING,
                           percent,
                           averagespeed,
                           m_Context)){
                  fclose(file);
                  return EN_USER_EXCEPTION;
               }

            lasttime=currenttime;
         }

         currentLBA.QuadPart+=readLBs.QuadPart;
      }
      
      fclose(file);

      return EN_SUCCESS;
   }

   return EN_INVALID_INPUT_PARAMETER;
}

BOOL CDVDBurnerGrabber::GetTrackInformationEx(LONG tracknumber, PSTARBURN_TRACK_INFORMATION pTrackInformation,int *pTrackSize)
{
   int index = ((m_Index+1)*(m_Drive+1))-1;

   if(pTrackSize)
      *pTrackSize = 0;

   if(m_bIsCreated && IsUpStart()){
       TRACK_INFORMATION_BLOCK tib;
      RtlZeroMemory(
            &tib,
           sizeof( TRACK_INFORMATION_BLOCK )
           );

      CDB_READ_TRACK_INFORMATION cdb;
       RtlZeroMemory(
            &cdb,
           sizeof( CDB_READ_TRACK_INFORMATION )
           );

      cdb.Operation_Code = 0x52;
      cdb.AddressType = 0x01;
      cdb.Open = 0;
      cdb.LTN[0] = HIBYTE(HIWORD(tracknumber));  // MSB track number
      cdb.LTN[1] = LOBYTE(HIWORD(tracknumber));  // B02 track number
      cdb.LTN[2] = HIBYTE(LOWORD(tracknumber));  // B01 track number
      cdb.LTN[3] = LOBYTE(LOWORD(tracknumber));  // LSB track number
      cdb.AllocLength[0] = HIBYTE(sizeof( TRACK_INFORMATION_BLOCK ));        // MSB allocation length
      cdb.AllocLength[1] = LOBYTE(sizeof( TRACK_INFORMATION_BLOCK ));        // LSB allocation length

      //
      // Try to execute command
      //
      l__EXCEPTION_NUMBER =
         StarBurn_CdvdBurnerGrabber_ExecuteGeneric(
               l__PVOID__CdvdBurnerGrabber,
               ( PCHAR )( &l__CHAR__ExceptionText ),
               sizeof( l__CHAR__ExceptionText ),
               &l__ULONG__SystemError,
               &l__CDB_FAILURE_INFORMATION,
               ( PUCHAR )( &cdb ),
               sizeof( CDB_READ_TRACK_INFORMATION ),
               ( PUCHAR )( &g_TRACKINFOBLOCK[index] ),
               sizeof( TRACK_INFORMATION_BLOCK ),
               FALSE
               );

      pTrackInformation->m__BOOLEAN__IsValid = false;

      // Check for correct reply
      if ( l__EXCEPTION_NUMBER != EN_SUCCESS )
      {
         WriteExceptionLog(l__EXCEPTION_NUMBER,l__ULONG__SystemError);
         return FALSE;
      }

      pTrackInformation->m__BOOLEAN__IsValid = true;
      pTrackInformation->m__UCHAR__TrackNumber = (g_TRACKINFOBLOCK[index].ucTrackNoMSB<<8) | g_TRACKINFOBLOCK[index].ucTrackNoLSB;
      pTrackInformation->m__UCHAR__SessionNumber = (g_TRACKINFOBLOCK[index].ucSessionNoMSB<<8) | g_TRACKINFOBLOCK[index].ucSessionNoLSB;
      pTrackInformation->m__UCHAR__TrackMode = g_TRACKINFOBLOCK[index].TrackMode;
      pTrackInformation->m__BOOLEAN__IsCopy = g_TRACKINFOBLOCK[index].Copy;
      pTrackInformation->m__BOOLEAN__IsDamage = g_TRACKINFOBLOCK[index].Damage;
      pTrackInformation->m__UCHAR__DataMode = g_TRACKINFOBLOCK[index].DataMode;
      pTrackInformation->m__BOOLEAN__IsFixedPacket = g_TRACKINFOBLOCK[index].FP;
      pTrackInformation->m__BOOLEAN__IsPacket = g_TRACKINFOBLOCK[index].Packet;
      pTrackInformation->m__BOOLEAN__IsBlank = g_TRACKINFOBLOCK[index].Blank;
      pTrackInformation->m__BOOLEAN__IsReserved = g_TRACKINFOBLOCK[index].RT;
      pTrackInformation->m__BOOLEAN__IsNextWritableAddressValid = g_TRACKINFOBLOCK[index].NWA_V;
      pTrackInformation->m__LONG__TrackStartAddress = g_TRACKINFOBLOCK[index].ucTrackStartAddressMSB<<24 |
                                          g_TRACKINFOBLOCK[index].ucTrackStartAddressB02<<16 |
                                          g_TRACKINFOBLOCK[index].ucTrackStartAddressB01<<8 |
                                          g_TRACKINFOBLOCK[index].ucTrackStartAddressLSB;
      pTrackInformation->m__LONG__NextWritableAddress = g_TRACKINFOBLOCK[index].ucNextWritableAddressMSB<<24 |
                                            g_TRACKINFOBLOCK[index].ucNextWritableAddressB02<<16 |
                                            g_TRACKINFOBLOCK[index].ucNextWritableAddressB01<<8 |
                                            g_TRACKINFOBLOCK[index].ucNextWritableAddressLSB;
      pTrackInformation->m__LONG__FreeLBs = g_TRACKINFOBLOCK[index].ucFreeBlocksMSB<<24 |
                                   g_TRACKINFOBLOCK[index].ucFreeBlocksB02<<16 |
                                   g_TRACKINFOBLOCK[index].ucFreeBlocksB01<<8 |
                                   g_TRACKINFOBLOCK[index].ucFreeBlocksLSB;
      pTrackInformation->m__LONG__FixedPacketSizeInLBs = g_TRACKINFOBLOCK[index].ucFixedPacketSizeMSB<<24 |
                                             g_TRACKINFOBLOCK[index].ucFixedPacketSizeB02<<16 |
                                             g_TRACKINFOBLOCK[index].ucFixedPacketSizeB01<<8 |
                                             g_TRACKINFOBLOCK[index].ucFixedPacketSizeLSB;
   }
   else{
      return FALSE;
   }

   if(pTrackSize)
      *pTrackSize = g_TRACKINFOBLOCK[index].ucTrackSizeMSB<<24 |
                 g_TRACKINFOBLOCK[index].ucTrackSizeB02<<16 |
                 g_TRACKINFOBLOCK[index].ucTrackSizeB01<<8 |
                 g_TRACKINFOBLOCK[index].ucTrackSizeLSB;

   return TRUE;
}


Top
 Profile  
 
 Post subject: Re: Multitrack DVD fix for Starburn
PostPosted: Wed May 16, 2007 10:57 pm 
Offline
Site Admin

Joined: Fri Jun 18, 2004 12:03 am
Posts: 4089
Location: British Virgin Islands
Nathan. Thank you very much for this research, it would *DEFINITELY* help us. There are some remarks however 1) it woud not always work as different burners may have different space between user-accessable tracks. 2) You'll fail to burn say multisession DVD-R to DVD-RAM or +RW media. Are these two things OK for you? Thanks!

Acidtech wrote:
MMC5r04 sections:

section 6.26.1: For media other than CD, information may be fabricated in order to emulate a CD structure for the specific
media.

section 6.26.3.2.4 Table 482: Shows the fabricated information. DVDs will ALWAYS return 01 for number of tracks even if they have more than one track.

My fix was to write a replacement for GrabTrack and GetTOCInformation using Execute Generic. Using my GrabTrackEx command which doesn't use the TOC track number to limit what tracks I can grab I have been able to rip a multi track DVD and then using the normal Starburn TAO command to burn those multiple tracks to a DVD and get an exact copy of the original. Note my command does not currently use the IsBadBlockIgnore or IsSingleLBTransferForced because I'm not exactly sure what is ment by those settings. Also My GrabtrackEx does not use the Starburn_Callback and it doesn't callback on read retries or bad blocks because I haven't figured out how to determine when a read retry has happened or a bad block has been encountered. I'm hoping this proof of concept will get the Starburn programmers to modify their GrabTrack and GetTrackInformation commands to NOT be limited by the number of tracks listed in the TOC.

Code:
LONG CDVDBurnerGrabber::CalculateSpeed(LARGE_INTEGER Processed,LARGE_INTEGER &LBsProcessed)
{
   LBsProcessed.QuadPart=Processed.QuadPart-m_LastLB.QuadPart;

   LARGE_INTEGER CurrentTime;
   QueryPerformanceCounter(&CurrentTime);
   LARGE_INTEGER Time;
   Time.QuadPart=CurrentTime.QuadPart-m_LastTime.QuadPart;

   m_AverageLB.QuadPart+=LBsProcessed.QuadPart;
   m_AverageTime.QuadPart+=Time.QuadPart;

   LONG speed=0;
   if(m_LastTime.QuadPart!=0){
      double TimeUsed = (double)Time.QuadPart/(double)m_Freq.QuadPart;
      if(TimeUsed>0.0)
         speed = (LONG)((double(LBsProcessed.QuadPart * m_LBSize)/1024.0)/TimeUsed);
   }
   m_LastTime=CurrentTime;
   m_LastLB=Processed;

   return speed;
}

LONG CDVDBurnerGrabber::CalculateAverageSpeed()
{
   LONG speed=0;
   double TimeUsed = (double)m_AverageTime.QuadPart/(double)m_Freq.QuadPart;
   if(TimeUsed>0.0)
      speed = (LONG)((double(m_AverageLB.QuadPart * m_LBSize)/1024.0)/TimeUsed);
   m_AverageTime.QuadPart=0;
   m_AverageLB.QuadPart=0;

   return speed;
}

BOOL CDVDBurnerGrabber::SetReadWriteErrorRecoveryParameter(UCHAR *ReadRetry,
                                             UCHAR *WriteRetry,
                                             BOOL *AWRE,
                                             BOOL *ARRE,
                                             BOOL *TransferBlock,
                                             BOOL *ReadContinuous,
                                             BOOL *PostError,
                                             BOOL *DisableTransferOnError,
                                             BOOL *DisableCorrection,
                                             UCHAR *EMCDR,
                                             ULONG *ErrorReportingWindowSize)
{
    READ_WRITE_ERROR_RECOVERY_PARAMETERS_MODE_PAGE pmp, pmp_verify;

    if (!ModeSense(0x01, (void*) &pmp, sizeof(pmp)))
        return FALSE;

    pmp.ucPageCode = 0x01;
   if(ReadRetry)
      pmp.ucReadRetryCount=*ReadRetry;
   if(WriteRetry)
      pmp.ucWriteRetryCount=*WriteRetry;
   if(AWRE)
      pmp.AWRE=*AWRE;
   if(ARRE)
      pmp.ARRE=*ARRE;
   if(TransferBlock)
      pmp.TB=*TransferBlock;
   if(ReadContinuous)
      pmp.RC=*ReadContinuous;
   if(PostError)
      pmp.PER=*PostError;
   if(DisableTransferOnError)
      pmp.DTE=*DisableTransferOnError;
   if(DisableCorrection)
      pmp.DCR=*DisableCorrection;
   if(EMCDR)
      pmp.EMCDR=*EMCDR;
   if(ErrorReportingWindowSize){
       pmp.ucErrorReportingWindowSize[ 0 ] = HIBYTE( HIWORD( ErrorReportingWindowSize ) );
      pmp.ucErrorReportingWindowSize[ 1 ] = LOBYTE( HIWORD( ErrorReportingWindowSize ) );
      pmp.ucErrorReportingWindowSize[ 2 ] = HIBYTE( LOWORD( ErrorReportingWindowSize ) );
      pmp.ucErrorReportingWindowSize[ 3 ] = LOBYTE( LOWORD( ErrorReportingWindowSize ) );
   }

    CopyMemory(&pmp_verify, &pmp, sizeof(pmp));
    if (!ModeSelect((void*) &pmp, sizeof(pmp)))
        return FALSE;
    if (!ModeSense(0x01, (void*) &pmp, sizeof(pmp)))
        return FALSE;
    if (memcmp(&pmp_verify, &pmp, sizeof(pmp)))
        return FALSE;
    return TRUE;
}

BOOL CDVDBurnerGrabber::SetWriteParameter(UCHAR *WriteType,
                                BOOL *TestWrite,
                                BOOL *LS_V,
                                BOOL *BUFE,
                                UCHAR *TrackMode,
                                BOOL *Copy,
                                BOOL *FP,
                                UCHAR *MultiSession,
                                UCHAR *DataBlockType,
                                UCHAR *LinkSize,
                                UCHAR *HostApplicationCode,
                                UCHAR *SessionFormat,
                                ULONG *PacketSize,
                                UWORD *AudioPause,
                                UCHAR *MediaCatalogNumberArray,
                                UCHAR *ISRCArray,
                                UCHAR *SubHeaderByte0,
                                UCHAR *SubHeaderByte1,
                                UCHAR *SubHeaderByte2,
                                UCHAR *SubHeaderByte3)
{
    WRITE_PARAMETERS_MODE_PAGE pmp, pmp_verify;

    if (!ModeSense(0x05, (void*) &pmp, sizeof(pmp)))
        return FALSE;

    pmp.ucPageCode = 0x05;
   if(WriteType)
      pmp.WriteType=*WriteType;
   if(TestWrite)
      pmp.TestWrite=*TestWrite;
   if(LS_V)
      pmp.LS_V=*LS_V;
   if(BUFE)
      pmp.BUFE=*BUFE;
   if(TrackMode)
      pmp.TrackMode=*TrackMode;
   if(Copy)
      pmp.Copy=*Copy;
   if(FP)
      pmp.FP=*FP;
   if(MultiSession)
      pmp.MultiSession=*MultiSession;
   if(DataBlockType)
      pmp.DataBlockType=*DataBlockType;
   if(LinkSize)
      pmp.LinkSize=*LinkSize;
   if(HostApplicationCode)
      pmp.HostApplicationCode=*HostApplicationCode;
   if(SessionFormat)
      pmp.ucSessionFormat=*SessionFormat;
   if(PacketSize){
       pmp.ucPacketSize[ 0 ] = HIBYTE( HIWORD( PacketSize ) );
      pmp.ucPacketSize[ 1 ] = LOBYTE( HIWORD( PacketSize ) );
      pmp.ucPacketSize[ 2 ] = HIBYTE( LOWORD( PacketSize ) );
      pmp.ucPacketSize[ 3 ] = LOBYTE( LOWORD( PacketSize ) );
   }
   if(AudioPause){
      pmp.ucAudioPauseLength[ 0 ] = HIBYTE( LOWORD( AudioPause ) );
      pmp.ucAudioPauseLength[ 1 ] = LOBYTE( LOWORD( AudioPause ) );
   }
   if(MediaCatalogNumberArray){
      memcpy(pmp.ucMediaCatalogNumber,MediaCatalogNumberArray,16);
   }
   if(ISRCArray){
      memcpy(pmp.ucISRC,ISRCArray,16);
   }
   if(SubHeaderByte0)
      pmp.ucSubHeaderByte0=*SubHeaderByte0;
   if(SubHeaderByte1)
      pmp.ucSubHeaderByte1=*SubHeaderByte1;
   if(SubHeaderByte2)
      pmp.ucSubHeaderByte2=*SubHeaderByte2;
   if(SubHeaderByte3)
      pmp.ucSubHeaderByte3=*SubHeaderByte3;

    CopyMemory(&pmp_verify, &pmp, sizeof(pmp));
    if (!ModeSelect((void*) &pmp, sizeof(pmp)))
        return FALSE;
    if (!ModeSense(0x05, (void*) &pmp, sizeof(pmp)))
        return FALSE;
    if (memcmp(&pmp_verify, &pmp, sizeof(pmp)))
        return FALSE;
    return TRUE;
}

BOOL CDVDBurnerGrabber::ModeSense(unsigned char ucModePage, void* pBuffer, WORD wBufferSize)
{
   CDB_MODE_SENSE cdb;
   RtlZeroMemory(&cdb,sizeof(cdb));
    cdb.Operation_Code = 0x5A;   // Code for MODE SENSE (10) command
    cdb.PageCode = ucModePage;   // Bits7:6, 00=Current Values, 01=Changeable Values, 10=Default Values, 11=Saved Values
    cdb.SubpageCode = 0x00;      // Subpage not supported by MM devices.  Always set 0x00
    cdb.AllocLength[0] = HIBYTE(wBufferSize);
    cdb.AllocLength[1] = LOBYTE(wBufferSize);

   l__EXCEPTION_NUMBER =
      StarBurn_CdvdBurnerGrabber_ExecuteGeneric(
         l__PVOID__CdvdBurnerGrabber,
         ( PCHAR )( &l__CHAR__ExceptionText ),
         sizeof( l__CHAR__ExceptionText ),
         &l__ULONG__SystemError,
         &l__CDB_FAILURE_INFORMATION,
         ( PUCHAR )( &cdb ),
         sizeof( cdb ),
         ( PUCHAR )( pBuffer  ),
         wBufferSize,
         FALSE
         );

   if (l__EXCEPTION_NUMBER != EN_SUCCESS){
      return FALSE;
   }
    return TRUE;
}

BOOL CDVDBurnerGrabber::ModeSelect(void* pBuffer, WORD wBufferSize)
{
   CDB_MODE_SELECT cdb;
   RtlZeroMemory(&cdb,sizeof(cdb));
    cdb.Operation_Code = 0x55;   //Code for MODE SELECT (10) command
    cdb.PF = 1;               //Structured as page
    cdb.ParamLength[0] = HIBYTE(wBufferSize);
    cdb.ParamLength[1] = LOBYTE(wBufferSize);

   l__EXCEPTION_NUMBER =
      StarBurn_CdvdBurnerGrabber_ExecuteGeneric(
         l__PVOID__CdvdBurnerGrabber,
         ( PCHAR )( &l__CHAR__ExceptionText ),
         sizeof( l__CHAR__ExceptionText ),
         &l__ULONG__SystemError,
         &l__CDB_FAILURE_INFORMATION,
         ( PUCHAR )( &cdb ),
         sizeof( cdb ),
         ( PUCHAR )( pBuffer  ),
         wBufferSize,
         TRUE
         );

   if (l__EXCEPTION_NUMBER != EN_SUCCESS){
      return FALSE;
   }
    return TRUE;
}

#define TransferSizeInLBs 0x20

EXCEPTION_NUMBER
CDVDBurnerGrabber::StarBurn_CdvdBurnerGrabber_GrabTrackEx(PVOID CdvdBurnerGrabber,
                                            PCHAR ExceptionText,
                                            ULONG ExceptionTextSizeInUCHARs,
                                            PULONG SystemError,
                                            PCDB_FAILURE_INFORMATION CDB_FAILURE_INFORMATION,
                                            UCHAR TrackNumber,
                                            PCHAR FileName,
                                            LONG Retries,
                                            BOOLEAN IsBadBlockIgnore,
                                            BOOLEAN IsSingleLBTransferForced,
                                            ULONG ReadReportDelayInSeconds)
{
   UCHAR ReadRetry=Retries;
   SetReadWriteErrorRecoveryParameter(&ReadRetry,
                              NULL,
                              NULL,
                              NULL,
                              NULL,
                              NULL,
                              NULL,
                              NULL,
                              NULL,
                              NULL,
                              NULL);

   LARGE_INTEGER startLBA,currentLBA,lastLBA,totalLBs,readLBs;

   STARBURN_TRACK_INFORMATION trackinfo;
   int tracksize;
   RtlZeroMemory(     
      &trackinfo,
      sizeof(trackinfo)
      );
   if(GetTrackInformationEx(TrackNumber,&trackinfo,&tracksize)){
      totalLBs.QuadPart = tracksize;
      startLBA.QuadPart = currentLBA.QuadPart = trackinfo.m__LONG__TrackStartAddress;
      lastLBA.QuadPart = currentLBA.QuadPart+totalLBs.QuadPart;
      FILE *file = fopen(FileName,"wb");

      CDB_READ_10 cdb;
      DWORD databuffer[(2048*TransferSizeInLBs)/4];
      DWORD lasttime=GetTickCount();
      DWORD currenttime=lasttime;
      DWORD testunitreadyrun=0;
      while(currentLBA.QuadPart<lastLBA.QuadPart){
         if((lastLBA.QuadPart-currentLBA.QuadPart)>=TransferSizeInLBs){
            readLBs.QuadPart=TransferSizeInLBs;
         }
         else{
            readLBs.QuadPart=lastLBA.QuadPart-currentLBA.QuadPart;
         }
   
            RtlZeroMemory(&cdb,sizeof( cdb ));
         cdb.Operation_Code = 0x28; // SCSI_OPCODE_READ;
         //cdb.FUA = 0x1;
          cdb.LBA[ 0 ] = HIBYTE( HIWORD( currentLBA.QuadPart ) );
         cdb.LBA[ 1 ] = LOBYTE( HIWORD( currentLBA.QuadPart ) );
         cdb.LBA[ 2 ] = HIBYTE( LOWORD( currentLBA.QuadPart ) );
         cdb.LBA[ 3 ] = LOBYTE( LOWORD( currentLBA.QuadPart ) );
         cdb.AllocLength[ 0 ] = HIBYTE( LOWORD( readLBs.QuadPart ) );
         cdb.AllocLength[ 1 ] = LOBYTE( LOWORD( readLBs.QuadPart ) );

         RtlZeroMemory(&databuffer,sizeof( databuffer ));
         l__EXCEPTION_NUMBER =
            StarBurn_CdvdBurnerGrabber_ExecuteGeneric(
               l__PVOID__CdvdBurnerGrabber,
               ExceptionText,
               ExceptionTextSizeInUCHARs,
               SystemError,
                    CDB_FAILURE_INFORMATION,
               ( PUCHAR )( &cdb ),
               sizeof( cdb ),
               ( PUCHAR )( &databuffer ),
               sizeof( databuffer ),
               FALSE
               );

         if (l__EXCEPTION_NUMBER != EN_SUCCESS){
            fclose(file);
            return l__EXCEPTION_NUMBER;
         }

         fwrite(databuffer,sizeof( UCHAR ),(int)(2048*readLBs.QuadPart),file);
      
         LARGE_INTEGER junk,processed;
         processed.QuadPart = (currentLBA.QuadPart - startLBA.QuadPart);
         LONG speed = CalculateSpeed(processed,junk);

         if(speed<1352){
            l__EXCEPTION_NUMBER =
               StarBurn_CdvdBurnerGrabber_TestUnitReadyEx(
                     l__PVOID__CdvdBurnerGrabber,
                     ExceptionText,
                     ExceptionTextSizeInUCHARs,
                     SystemError,
                          CDB_FAILURE_INFORMATION,
                     1
                     );

            // Check for correct reply
            if ( l__EXCEPTION_NUMBER != EN_SUCCESS )
            {
               return l__EXCEPTION_NUMBER;
            }
         }

         currenttime=GetTickCount();
         if((currenttime-lasttime)>(ReadReportDelayInSeconds*1000)){
            ULONG percent = (ULONG)(((currentLBA.QuadPart-startLBA.QuadPart)*100)/totalLBs.QuadPart);
            LONG averagespeed = CalculateAverageSpeed();
            if(m_pCallback)
               if(!m_pCallback(m_Index,
                           m_Drive,
                           MODE_READING,
                           percent,
                           averagespeed,
                           m_Context)){
                  fclose(file);
                  return EN_USER_EXCEPTION;
               }

            lasttime=currenttime;
         }

         currentLBA.QuadPart+=readLBs.QuadPart;
      }
      
      fclose(file);

      return EN_SUCCESS;
   }

   return EN_INVALID_INPUT_PARAMETER;
}

BOOL CDVDBurnerGrabber::GetTrackInformationEx(LONG tracknumber, PSTARBURN_TRACK_INFORMATION pTrackInformation,int *pTrackSize)
{
   int index = ((m_Index+1)*(m_Drive+1))-1;

   if(pTrackSize)
      *pTrackSize = 0;

   if(m_bIsCreated && IsUpStart()){
       TRACK_INFORMATION_BLOCK tib;
      RtlZeroMemory(
            &tib,
           sizeof( TRACK_INFORMATION_BLOCK )
           );

      CDB_READ_TRACK_INFORMATION cdb;
       RtlZeroMemory(
            &cdb,
           sizeof( CDB_READ_TRACK_INFORMATION )
           );

      cdb.Operation_Code = 0x52;
      cdb.AddressType = 0x01;
      cdb.Open = 0;
      cdb.LTN[0] = HIBYTE(HIWORD(tracknumber));  // MSB track number
      cdb.LTN[1] = LOBYTE(HIWORD(tracknumber));  // B02 track number
      cdb.LTN[2] = HIBYTE(LOWORD(tracknumber));  // B01 track number
      cdb.LTN[3] = LOBYTE(LOWORD(tracknumber));  // LSB track number
      cdb.AllocLength[0] = HIBYTE(sizeof( TRACK_INFORMATION_BLOCK ));        // MSB allocation length
      cdb.AllocLength[1] = LOBYTE(sizeof( TRACK_INFORMATION_BLOCK ));        // LSB allocation length

      //
      // Try to execute command
      //
      l__EXCEPTION_NUMBER =
         StarBurn_CdvdBurnerGrabber_ExecuteGeneric(
               l__PVOID__CdvdBurnerGrabber,
               ( PCHAR )( &l__CHAR__ExceptionText ),
               sizeof( l__CHAR__ExceptionText ),
               &l__ULONG__SystemError,
               &l__CDB_FAILURE_INFORMATION,
               ( PUCHAR )( &cdb ),
               sizeof( CDB_READ_TRACK_INFORMATION ),
               ( PUCHAR )( &g_TRACKINFOBLOCK[index] ),
               sizeof( TRACK_INFORMATION_BLOCK ),
               FALSE
               );

      pTrackInformation->m__BOOLEAN__IsValid = false;

      // Check for correct reply
      if ( l__EXCEPTION_NUMBER != EN_SUCCESS )
      {
         WriteExceptionLog(l__EXCEPTION_NUMBER,l__ULONG__SystemError);
         return FALSE;
      }

      pTrackInformation->m__BOOLEAN__IsValid = true;
      pTrackInformation->m__UCHAR__TrackNumber = (g_TRACKINFOBLOCK[index].ucTrackNoMSB<<8) | g_TRACKINFOBLOCK[index].ucTrackNoLSB;
      pTrackInformation->m__UCHAR__SessionNumber = (g_TRACKINFOBLOCK[index].ucSessionNoMSB<<8) | g_TRACKINFOBLOCK[index].ucSessionNoLSB;
      pTrackInformation->m__UCHAR__TrackMode = g_TRACKINFOBLOCK[index].TrackMode;
      pTrackInformation->m__BOOLEAN__IsCopy = g_TRACKINFOBLOCK[index].Copy;
      pTrackInformation->m__BOOLEAN__IsDamage = g_TRACKINFOBLOCK[index].Damage;
      pTrackInformation->m__UCHAR__DataMode = g_TRACKINFOBLOCK[index].DataMode;
      pTrackInformation->m__BOOLEAN__IsFixedPacket = g_TRACKINFOBLOCK[index].FP;
      pTrackInformation->m__BOOLEAN__IsPacket = g_TRACKINFOBLOCK[index].Packet;
      pTrackInformation->m__BOOLEAN__IsBlank = g_TRACKINFOBLOCK[index].Blank;
      pTrackInformation->m__BOOLEAN__IsReserved = g_TRACKINFOBLOCK[index].RT;
      pTrackInformation->m__BOOLEAN__IsNextWritableAddressValid = g_TRACKINFOBLOCK[index].NWA_V;
      pTrackInformation->m__LONG__TrackStartAddress = g_TRACKINFOBLOCK[index].ucTrackStartAddressMSB<<24 |
                                          g_TRACKINFOBLOCK[index].ucTrackStartAddressB02<<16 |
                                          g_TRACKINFOBLOCK[index].ucTrackStartAddressB01<<8 |
                                          g_TRACKINFOBLOCK[index].ucTrackStartAddressLSB;
      pTrackInformation->m__LONG__NextWritableAddress = g_TRACKINFOBLOCK[index].ucNextWritableAddressMSB<<24 |
                                            g_TRACKINFOBLOCK[index].ucNextWritableAddressB02<<16 |
                                            g_TRACKINFOBLOCK[index].ucNextWritableAddressB01<<8 |
                                            g_TRACKINFOBLOCK[index].ucNextWritableAddressLSB;
      pTrackInformation->m__LONG__FreeLBs = g_TRACKINFOBLOCK[index].ucFreeBlocksMSB<<24 |
                                   g_TRACKINFOBLOCK[index].ucFreeBlocksB02<<16 |
                                   g_TRACKINFOBLOCK[index].ucFreeBlocksB01<<8 |
                                   g_TRACKINFOBLOCK[index].ucFreeBlocksLSB;
      pTrackInformation->m__LONG__FixedPacketSizeInLBs = g_TRACKINFOBLOCK[index].ucFixedPacketSizeMSB<<24 |
                                             g_TRACKINFOBLOCK[index].ucFixedPacketSizeB02<<16 |
                                             g_TRACKINFOBLOCK[index].ucFixedPacketSizeB01<<8 |
                                             g_TRACKINFOBLOCK[index].ucFixedPacketSizeLSB;
   }
   else{
      return FALSE;
   }

   if(pTrackSize)
      *pTrackSize = g_TRACKINFOBLOCK[index].ucTrackSizeMSB<<24 |
                 g_TRACKINFOBLOCK[index].ucTrackSizeB02<<16 |
                 g_TRACKINFOBLOCK[index].ucTrackSizeB01<<8 |
                 g_TRACKINFOBLOCK[index].ucTrackSizeLSB;

   return TRUE;
}


Top
 Profile  
 
 Post subject:
PostPosted: Wed May 16, 2007 11:35 pm 
Offline

Joined: Thu Jun 02, 2005 8:50 pm
Posts: 115
Quote:
Nathan. Thank you very much for this research, it would *DEFINITELY* help us. There are some remarks however 1) it woud not always work as different burners may have different space between user-accessable tracks. 2) You'll fail to burn say multisession DVD-R to DVD-RAM or +RW media. Are these two things OK for you? Thanks!


1. The way I'm using this, no that's not an issue. The only multi track DVDs we have to deal with(so far) are DVD-Video discs made on standalone recorders. I was able to take a 3 track DVD-Video and simply rip all three tracks as one long track using the last LBA of the last track as the length(using my GrabTrackEx command). I then burned that long track and that worked too. That indicates to me the track breaks don't matter much(at least on DVD-Video discs). I can only assume that it's because they aren't tracks in the real sense. On DVD+R they are "Fragments" and on DVD-R they are "RZones". The drive just treats them as "tracks". In the case of DVD+R media there is a decent description in section 4.3.6.2.2. It explains the hosts perspective of DVD+ media sessions/tracks/fragments.

2. Our software isn't really designed for any of the re-writable media so that is definitely not a problem.

P.S. I'll be working on a modified SAO burn command soon. The two problems I see with Starburns SAO(not RawRawPW) is that 1) it always wants to start at LBA 0 even if there is already an open session on the target disc and 2) the pause between tracks isn't adjustable because the CUE sheet can't be edited by us(as far as I've been able to figure out). I should be able to use SAO(with it's cue sheet) to make exact copies of other multi-session discs. If not maybe I'll work up a DAO raw burning command to do what I need and pass it along.


Top
 Profile  
 
 Post subject:
PostPosted: Thu May 17, 2007 9:39 pm 
Offline
Site Admin

Joined: Fri Jun 18, 2004 12:03 am
Posts: 4089
Location: British Virgin Islands
1) and 2) Fine. So we'll provide controllable restriction on burning different media type (compared to the source image).

3) SAO really sucks... If you want true 1:1 you need DAO. Of course you can do this via ExecuteGeneric however I think we can open StarBurn source code (at least partially, DAO engine) for you. If you're interested - please let me know.

Acidtech wrote:
Quote:
Nathan. Thank you very much for this research, it would *DEFINITELY* help us. There are some remarks however 1) it woud not always work as different burners may have different space between user-accessable tracks. 2) You'll fail to burn say multisession DVD-R to DVD-RAM or +RW media. Are these two things OK for you? Thanks!


1. The way I'm using this, no that's not an issue. The only multi track DVDs we have to deal with(so far) are DVD-Video discs made on standalone recorders. I was able to take a 3 track DVD-Video and simply rip all three tracks as one long track using the last LBA of the last track as the length(using my GrabTrackEx command). I then burned that long track and that worked too. That indicates to me the track breaks don't matter much(at least on DVD-Video discs). I can only assume that it's because they aren't tracks in the real sense. On DVD+R they are "Fragments" and on DVD-R they are "RZones". The drive just treats them as "tracks". In the case of DVD+R media there is a decent description in section 4.3.6.2.2. It explains the hosts perspective of DVD+ media sessions/tracks/fragments.

2. Our software isn't really designed for any of the re-writable media so that is definitely not a problem.

P.S. I'll be working on a modified SAO burn command soon. The two problems I see with Starburns SAO(not RawRawPW) is that 1) it always wants to start at LBA 0 even if there is already an open session on the target disc and 2) the pause between tracks isn't adjustable because the CUE sheet can't be edited by us(as far as I've been able to figure out). I should be able to use SAO(with it's cue sheet) to make exact copies of other multi-session discs. If not maybe I'll work up a DAO raw burning command to do what I need and pass it along.


Top
 Profile  
 
 Post subject:
PostPosted: Fri May 18, 2007 5:39 pm 
Offline

Joined: Thu Jun 02, 2005 8:50 pm
Posts: 115
anton (staff) wrote:
1) and 2) Fine. So we'll provide controllable restriction on burning different media type (compared to the source image).

3) SAO really sucks... If you want true 1:1 you need DAO. Of course you can do this via ExecuteGeneric however I think we can open StarBurn source code (at least partially, DAO engine) for you. If you're interested - please let me know.


1) and 2) thanks.

3) Yes, I would be very interested. That will save me a lot of time and I agree SAO sucks but I was going to use it because it would be faster than writing a DAO handler from scratch.


Top
 Profile  
 
 Post subject:
PostPosted: Tue May 22, 2007 7:22 am 
Offline
Site Admin

Joined: Fri Jun 18, 2004 12:03 am
Posts: 4089
Location: British Virgin Islands
Fine. So let's move to the e-mail as I think other guys are not very interested in the end of this story :) I wrote up follow up e-mail. Thanks!

Acidtech wrote:
anton (staff) wrote:
1) and 2) Fine. So we'll provide controllable restriction on burning different media type (compared to the source image).

3) SAO really sucks... If you want true 1:1 you need DAO. Of course you can do this via ExecuteGeneric however I think we can open StarBurn source code (at least partially, DAO engine) for you. If you're interested - please let me know.


1) and 2) thanks.

3) Yes, I would be very interested. That will save me a lot of time and I agree SAO sucks but I was going to use it because it would be faster than writing a DAO handler from scratch.


Top
 Profile  
 
Display posts from previous:  Sort by  
Post new topic Reply to topic  [ 6 posts ] 

All times are UTC


Who is online

Users browsing this forum: Google [Bot] and 14 guests


You cannot post new topics in this forum
You cannot reply to topics in this forum
You cannot edit your posts in this forum
You cannot delete your posts in this forum
You cannot post attachments in this forum

Search for:
Jump to:  
cron
Powered by phpBB © 2000, 2002, 2005, 2007 phpBB Group