⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 udfrecognize.cpp

📁 DVD工具dvdsynth的源码
💻 CPP
字号:
/***********************************************************************
 Copyright 2002 Ben Rudiak-Gould.

 This program is free software; you can redistribute it and/or modify
 it under the terms of the GNU General Public License as published by
 the Free Software Foundation; either version 2 of the License, or
 (at your option) any later version.

 This program is distributed in the hope that it will be useful,
 but WITHOUT ANY WARRANTY; without even the implied warranty of
 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 GNU General Public License for more details.

 You should have received a copy of the GNU General Public License
 along with this program; if not, write to the Free Software
 Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA,
 or visit <http://www.gnu.org/copyleft/gpl.html>.
***********************************************************************/


#include "udfrecognize.h"
#include "../include/dvdsynth-device.h"

extern scsi_result_t KernelScsiCommand(DvsDeviceKernel* kdev, const unsigned char* cdb, int cdblen, unsigned char* buffer, unsigned long* pbuflen, int inout, SenseData* sense);

#include <stdio.h>
#include <string.h>


bool Read(DvsDeviceKernel* device, int sector, int sectors, unsigned char* buf) {
   unsigned char cdb[10] = { 0x28, 0, sector>>24, sector>>16, sector>>8, sector, 0, sectors>>8, sectors, 0 };
   unsigned long buflen = sectors*2048;
   static SenseData sense = { 0x70, 0, 0, {0,0,0,0}, 10, {0,0,0,0}, 0, 0, 0, {0,0,0} };
   return SCSIRESULT_SUCCESS == KernelScsiCommand(device, cdb, 10, buf, &buflen, 1, &sense);
}


unsigned crc_ccitt(const unsigned char *buf, unsigned len) {
   const unsigned poly = 0x11021;
   static unsigned short lookup[256];
   unsigned int r;
   unsigned int i;

   if (lookup[1] == 0) {
      unsigned int j,k;
      for (j = 0; j < 256; ++j) {
         unsigned int temp = j << 8;
         for (k = 0; k < 8; ++k) {
            unsigned int hibit = temp & 32768;
            temp <<= 1;
            if (hibit)
               temp ^= poly;
         }
         lookup[j] = temp;
      }
   }

   r = 0;
   for (i = 0; i < len; ++i) {
      r = (r << 8) ^ lookup[((r >> 8) ^ buf[i]) & 255];
   }

   return r & 65535;
}


int check_descriptor(const unsigned char* buf, int type) {
   if (buf[0]+buf[1]*256 != type) {
      return -1;
   }
//   if (buf[12] != (location&255) || buf[13] != ((location>>8)&255) || buf[13] != ((location>>16)&255) || buf[13] != (location>>24)) {
//      return -2;
//   }
   int checksum = 0;
   for (int i=0; i<16; ++i) {
      checksum += buf[i];
   }
   if ((checksum - buf[4]*2) & 255) {
      return -3;
   }
/*
   int crc = crc_ccitt(buf+16, buf[10]+buf[11]*256);
   if (buf[8]*256 + buf[9] != crc) {
      return -4;
   }
*/
   return 0;
}


unsigned get4(unsigned char* p) {
   return p[0] + p[1]*256 + p[2]*65536 + p[3]*16777216;
}


static unsigned char buf[2048];


int follow_icb(DvsDeviceKernel* device, unsigned partition_sector, unsigned sector, unsigned length, unsigned *psector, unsigned *plength) {
   if (!Read(device, sector, 1, buf)) {
      return -1;  // sector read failed
   }

   if (check_descriptor(buf, 261) < 0) {
      return -4;
   }

   unsigned l_ea = get4(buf+168);
   if (l_ea > 2048-176-8) {
      return -5;   // file entry longer than expected
   }

   *plength = get4(buf+176+l_ea);
   *psector = get4(buf+176+l_ea+4) + partition_sector;
   return 0;
}

int find_directory_entry(DvsDeviceKernel* device, unsigned partition_sector, unsigned sector, unsigned length, const char* name, bool dir, unsigned *psector, unsigned *plength) {
   int namelen = strlen(name);

   if (!Read(device, sector, 1, buf)) {
      return -1;
   }

   unsigned bufpos = 0;
   while (bufpos < 2048-38 && bufpos < length) {
      if (check_descriptor(buf, 257) < 0) {
         return -4;  // bad descriptor
      }

      unsigned l_fi = buf[bufpos+19];
      unsigned l_iu = buf[bufpos+36] + buf[bufpos+37]*256;
      if (bufpos+38+l_iu+l_fi > 2048) {
         return -7;
      }

      if ((buf[bufpos+18] & 30) == dir*2 && l_fi == namelen+1 && buf[bufpos+38+l_iu] == 8 && memcmp(buf+bufpos+38+l_iu+1, name, namelen) == 0) {
         *plength = get4(buf+bufpos+20);
         *psector = get4(buf+bufpos+24) + partition_sector;
         return 0;
      }

      bufpos += 38+l_iu+l_fi;
      bufpos = (bufpos+3) & ~3;
   }
   return -6;  // couldn't find file in directory
}


int GetDvdVideoInfo(DvsDeviceKernel* device, DvdVideoInfo* info) {
   if (!Read(device, 256, 1, buf)) {
      return -1;  // sector read failed
   }

   if (check_descriptor(buf, 2) < 0) {
      return -2;  // no AVDP found
   }

   info->mvds_length = get4(buf+16);
   info->mvds_sector = get4(buf+20);

   info->partition_sector = 0;
   info->partition_sectors = 0;
   info->fsd_sector = 0;
   info->fsd_length = 0;

   for (unsigned i = 0; i*2048 < info->mvds_length; ++i) {
      if (!Read(device, info->mvds_sector + i, 1, buf)) {
         return -1;
      }
      if (check_descriptor(buf, 5) >= 0) {
         info->partition_sector = get4(buf+188);
         info->partition_sectors = get4(buf+192);
      } else if (check_descriptor(buf, 6) >= 0) {
         info->fsd_length = get4(buf+248);
         info->fsd_sector = get4(buf+252);
      }
   }

   if (info->partition_sectors == 0 || info->fsd_length == 0) {
      return -3;  // no partition desc or logical volume desc found
   }

   info->fsd_sector += info->partition_sector;

   if (!Read(device, info->fsd_sector, 1, buf)) {
      return -1;
   }

   if (check_descriptor(buf, 256) < 0) {
      return -4;  // bad descriptor
   }

   info->root_icb_length = get4(buf+400);
   info->root_icb_sector = get4(buf+404) + info->partition_sector;

   int result;
   unsigned unused_length;

   result = follow_icb(device, info->partition_sector, info->root_icb_sector, info->root_icb_length, &info->root_sector, &info->root_length);
   if (result < 0) return result;
   result = find_directory_entry(device, info->partition_sector, info->root_sector, info->root_length, "VIDEO_TS", true, &info->video_ts_icb_sector, &info->video_ts_icb_length);
   if (result < 0) return result;
   result = follow_icb(device, info->partition_sector, info->video_ts_icb_sector, info->video_ts_icb_length, &info->video_ts_sector, &info->video_ts_length);
   if (result < 0) return result;
   result = find_directory_entry(device, info->partition_sector, info->video_ts_sector, info->video_ts_length, "VIDEO_TS.IFO", false, &info->vmg_ifo_icb_sector, &info->vmg_ifo_icb_length);
   if (result < 0) return result;
   result = follow_icb(device, info->partition_sector, info->vmg_ifo_icb_sector, info->vmg_ifo_icb_length, &info->vmg_ifo_sector, &unused_length);
   return result;
}

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -