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

📄 dvdunrestrict_kernel.c

📁 DVD工具dvdsynth的源码
💻 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 + -