📄 dvdunrestrict_kernel.c
字号:
/***********************************************************************
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 "../include/dvdsynth-device.h"
#include "DVDUnrestrict.h"
struct DvsDockingBayKernelGlobal* g_callbacks;
unsigned get4(const unsigned char* p) {
return p[0]*16777216 + p[1]*65536 + p[2]*256 + p[3];
}
unsigned get4rba(unsigned base, const unsigned char* p) {
unsigned x = get4(p);
return x ? base+x : (unsigned)-1;
}
void HandleSector(struct DVDUnrestrictKernel* self, unsigned lba, unsigned char* data, int len) {
unsigned word0 = get4(&data[0]);
if (word0 == 0x000001BA && get4(&data[38]) == 0x000001BF && get4(&data[42]) == 0x03D40000) {
/* PCI/DSI pack */
data[49] = 0; /* turn off macrovision */
g_callbacks->MemSet(data+53, 0, 4); /* enable all user ops */
} else {
if (word0 == 0x44564456 && get4(&data[4]) == 0x4944454F) {
unsigned word8 = get4(&data[8]);
if (word8 == 0x2D564D47) {
/* VMG ifo */
unsigned ifo_sector = lba;
unsigned pgc_uops_offset = get4(data+0x84) + 8;
if (pgc_uops_offset+4 <= len) {
g_callbacks->MemSet(data+pgc_uops_offset, 0, 4);
}
self->tt_srpt_sector = get4rba(ifo_sector, data+0xC4);
self->pgci_sector = (unsigned)-1;
self->pgci_ut_sector = get4rba(ifo_sector, data+0xC8);
data[35] = 0; /* enable all regions */
} else if (word8 == 0x2D565453) {
/* VTS ifo */
unsigned ifo_sector = lba;
self->tt_srpt_sector = (unsigned)-1;
self->pgci_sector = get4rba(ifo_sector, data+0xCC);
self->pgci_ut_sector = get4rba(ifo_sector, data+0xD0);
}
}
if (lba == self->tt_srpt_sector) {
int num_titles = data[0]*256 + data[1];
int i;
for (i=0; i<num_titles && i*12 + 8 < len; ++i)
data[i*12 + 8] &= 0xFC;
}
if (lba == self->pgci_ut_sector) {
int num_lang_units = data[0]*256 + data[1];
int lang_unit;
for (lang_unit = 0; lang_unit < num_lang_units; ++lang_unit) {
unsigned lu_offset;
int num_pgcs, pgc;
if (lang_unit*8 + 12 + 4 > len) break;
lu_offset = get4(&data[lang_unit*8 + 12]);
if (lu_offset+2 > len) break;
num_pgcs = data[lu_offset]*256 + data[lu_offset+1];
for (pgc = 0; pgc < num_pgcs; ++pgc) {
unsigned pgc_uops_offset;
if (lu_offset + pgc*8 + 12 + 4 > len) break;
pgc_uops_offset = lu_offset + get4(&data[lu_offset + pgc*8 + 12]) + 8;
if (pgc_uops_offset + 4 <= len) {
g_callbacks->MemSet(data+pgc_uops_offset, 0, 4);
}
}
}
}
if (lba == self->pgci_sector) {
int num_pgcs = data[0]*256 + data[1];
int pgc;
for (pgc = 0; pgc < num_pgcs; ++pgc) {
unsigned pgc_uops_offset;
if (pgc*8 + 12 + 4 > len) break;
pgc_uops_offset = get4(&data[pgc*8 + 12]) + 8;
if (pgc_uops_offset + 4 <= len) {
g_callbacks->MemSet(data+pgc_uops_offset, 0, 4);
}
}
}
}
}
scsi_result_t ScsiCommand(struct DvsDeviceKernel* _self, const unsigned char* cdb, int cdblen, unsigned char* buffer, unsigned long* pbuflen, int inout, SenseData* sense) {
struct DVDUnrestrictKernel* self = (struct DVDUnrestrictKernel*)_self;
scsi_result_t result = self->child->ScsiCommand(self->child, cdb, cdblen, buffer, pbuflen, inout, sense);
if (cdb[0] == SCSIOP_READ && result == SCSIRESULT_SUCCESS) {
unsigned first_sector = get4(&cdb[2]);
unsigned num_sectors = cdb[7]*256+cdb[8];
int i;
for (i=0; i<num_sectors; ++i) {
HandleSector(self, first_sector + i, buffer + i*2048, (num_sectors-i) * 2048);
}
} else if (cdb[0] == SCSIOP_READ_DVD_STRUCTURE && cdb[7] == 0x01 && result == SCSIRESULT_SUCCESS) {
if (*pbuflen > 5)
buffer[5] = 0; /* enable all regions */
}
return result;
}
void* __cdecl GetDispatchFunc() { return &ScsiCommand; }
void __cdecl DvdsynthDriverInit(struct DvsDockingBayKernelGlobal* callbacks) {
g_callbacks = callbacks;
}
unsigned __stdcall DLLEntry(void* hinst, unsigned reason, void* reserved) { return 1; }
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -