📄 udfrecognize.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 + -