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

📄 dvdsubber_kernel.cpp

📁 DVD工具dvdsynth的源码
💻 CPP
📖 第 1 页 / 共 2 页
字号:
/***********************************************************************
 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 "DVDSubber.h"
#include "../include/dvdsynth-device.h"
#include <stdio.h>


template<class T> static inline T Min(T a, T b) { return a<b?a:b; }
template<class T> static inline T Max(T a, T b) { return a<b?b:a; }


DvsDockingBayKernelGlobal* g_callbacks;


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

void Put4(unsigned char* dst, unsigned val) {
   dst[0] = val>>24;
   dst[1] = val>>16;
   dst[2] = val>>8;
   dst[3] = val;
}


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_udf_descriptor(const unsigned char* buf, int type) {
   if (buf[0]+buf[1]*256 != type) {
      return -1;
   }
   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]+buf[9]*256 != crc) {
      return -4;
   }
   return 0;
}


unsigned DVDSubberKernel::Hard2Soft(unsigned sector) {
   unsigned increase = 0;
   SubpictureInfo* si = subpic_inf;
   for (int i=0; i<num_subpics; ++i) {
      if (si->hard_lba > sector)
         break;
      increase += si->num_sectors;
      si = si->next;
   }
   return sector+increase;
}


unsigned DVDSubberKernel::Soft2Hard(unsigned sector) {
   SubpictureInfo* si = subpic_inf;
   for (int i=0; i<num_subpics; ++i) {
      if (sector < si->hard_lba) {
         break;
      } else if (sector < si->hard_lba + si->num_sectors) {
         return si->hard_lba;
      } else {
         sector -= si->num_sectors;
      }
   }
   return sector;
}


void DVDSubberKernel::GenerateSubpictureSector(SubpictureInfo* si, unsigned subpic_rba, unsigned char* buffer) {
   g_callbacks->MemCpy(&buffer[4], saved_scr, 6);
   if (saved_scr_lba != si->hard_lba - 1) {
      SenseData sense;
      if (SCSIRESULT_SUCCESS == ReadHardSectors(si->hard_lba - 1, 1, buffer, &sense)) {
         g_callbacks->MemCpy(saved_scr, &buffer[4], 6);
      } else {
         g_callbacks->MemCpy(&buffer[4], saved_scr, 6);
      }
      saved_scr_lba = si->hard_lba - 1;
   }
   Put4(&buffer[0], 0x000001BA);
   Put4(&buffer[10], 0x0189C3F8);
   Put4(&buffer[14], 0x000001BD);
   Put4(&buffer[18], 0x07EC8180);
   size_t filled_in;
   if (subpic_rba == 0) {
      buffer[22] = 5;
      unsigned ptm = si->ptm;
      buffer[23] = ((ptm >> 29) & 0x0E) | 0x21;
      buffer[24] = ptm >> 22;
      buffer[25] = (ptm >> 14) | 1;
      buffer[26] = ptm >> 7;
      buffer[27] = ptm * 2 + 1;
      buffer[28] = 0x20 + disc_info->titlesets[title].number_of_existing_subpicture_tracks;
      filled_in = 29 + g_callbacks->ReadFile(data_file_handle, si->file_offset, 0, Min(2019U, unsigned(si->data_len)), buffer + 29);
   } else {
      Put4(&buffer[20], 0x81000020 + disc_info->titlesets[title].number_of_existing_subpicture_tracks);
      unsigned subpic_data_offset = subpic_rba * 2024 - 5;
      unsigned subpic_data_len = Min(2024U, unsigned(si->data_len - subpic_data_offset));
      filled_in = 24 + g_callbacks->ReadFile(data_file_handle, si->file_offset + subpic_data_offset, 0, subpic_data_len, buffer + 24);
   }
   if (filled_in < 2048) {
      buffer[18] = (filled_in - 20) >> 8;
      buffer[19] = (filled_in - 20);
      if (filled_in < 2048-6) {
         Put4(&buffer[filled_in+2], (2048-6)-filled_in);
         Put4(&buffer[filled_in], 0x000001BE);
         g_callbacks->MemSet(buffer+filled_in+6, -1, (2048-6)-filled_in);
      } else {
         int stuffing = 2048-filled_in;
         buffer[13] += stuffing;
         for (int i=filled_in-1; i>=14; --i) {
            buffer[i+stuffing] = buffer[i];
            buffer[i] = 255;
         }
      }
   }
}


unsigned GetICBStartLBA(const unsigned char* buffer, unsigned buf_lba) {
   // x86-specific!
   unsigned partition_begin = buf_lba - *(unsigned*)(buffer+12);
   unsigned l_ea = *(unsigned*)(buffer+168);
   if (l_ea > 2048-176-8) {
      return 0;
   }
   return partition_begin + *(unsigned*)(buffer+176+l_ea+4);
}


void SetICBLengthInBlocks(const unsigned char* buffer, unsigned length) {
   // x86-specific!
   *(unsigned*)(buffer+56) = length << 11;
   *(unsigned*)(buffer+60) = length >> 21;
   *(unsigned*)(buffer+64) = length;
   *(unsigned*)(buffer+68) = 0;
   unsigned l_ea = *(unsigned*)(buffer+168);
   *(unsigned*)(buffer+176+l_ea) = length << 11;
}


void RecalcCRC(unsigned char* buffer) {
   buffer[4] -= buffer[8]+buffer[9];
   *(unsigned short*)(buffer+8) = crc_ccitt(buffer+16, *(unsigned short*)(buffer+10));
   buffer[4] += buffer[8]+buffer[9];
}


void SetICBStartLBA(unsigned char* buffer, unsigned buf_lba, unsigned new_lba) {
   // x86-specific!
   unsigned partition_begin = buf_lba - *(unsigned*)(buffer+12);
   unsigned l_ea = *(unsigned*)(buffer+168);
   *(unsigned*)(buffer+176+l_ea+4) = new_lba - partition_begin;
}


void DVDSubberKernel::PatchHardSector(unsigned hard_lba, unsigned char* buffer) {
   for (int ts = disc_info->num_title_sets-1; ts >= 0; --ts) {
      TitleSetInfo& tsi = disc_info->titlesets[ts];
      if (hard_lba >= tsi.vts_ifo_sector) {
         if (hard_lba >= tsi.vts_bup_sector) {
            PatchVTSIFO(ts, tsi, hard_lba - tsi.vts_bup_sector, buffer);
         } else if (hard_lba >= tsi.vts_vobs_sector) {
            if (Get4(buffer) == 0x000001BA) {
               g_callbacks->MemCpy(saved_scr, &buffer[4], 6);
               saved_scr_lba = hard_lba;
               // FIXME: should I check for pack header stuffing?
               switch (Get4(buffer+14)) {
               case 0x000001BB:
                  {
                  TranslateRelativeSector(&buffer[0x02D], tsi.vts_vobs_sector, false);
                  TranslateRelativeSector(&buffer[0x40B], tsi.vts_vobs_sector, false);
                  TranslateRelativeSector(&buffer[0x42D], hard_lba, true);
                  for (int refframe=0; refframe<4; ++refframe) {
                     TranslateRelativeSector(&buffer[0x40F+refframe*4], hard_lba, false);
                  }
                  for (int angle=0; angle<9; ++angle) {
                     TranslateRelativeSector(&buffer[0x069+angle*4], hard_lba, false);
                     TranslateRelativeSector(&buffer[0x4BB+angle*4], hard_lba, true);
                  }
                  for (int various=0; various<42; ++various) {
                     TranslateRelativeSector(&buffer[0x4F1+various*4], hard_lba, false);
                  }
                  Put4(&buffer[0x5A9 + 4 * tsi.number_of_existing_subpicture_tracks], 0x7FFFFFFF);
                  break;
                  }
               case 0x000001BD:
                  {
                  // The R2 Cagliostro DVD has four subtitle tracks, but
                  // only two are mentioned in the INF file. (The other
                  // two seem to be copies of the first two.) To prevent
                  // added subtitles from mixing with existing undocumented
                  // subtitles, I convert them into padding blocks here.
                  unsigned char substream_id = buffer[23 + buffer[22]];
                  if (substream_id == 0x20 + tsi.number_of_existing_subpicture_tracks) {
                     Put4(buffer+14, 0x000001BE);
                     g_callbacks->MemSet(buffer+20, 0xFF, 2048-20);
                  }
                  break;
                  }
               }
            }
         } else if (hard_lba >= tsi.vtsm_vobs_sector) {
            // no action
         } else {
            PatchVTSIFO(ts, tsi, hard_lba - tsi.vts_ifo_sector, buffer);
         }
         return;
      }
   }

   if (hard_lba >= disc_info->vmg_bup_sector) {
      PatchVMGIFO(hard_lba - disc_info->vmg_bup_sector, buffer);
   } else if (hard_lba >= disc_info->vmg_vobs_sector) {
      // no action

⌨️ 快捷键说明

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