Welcome to mirror list, hosted at ThFree Co, Russian Federation.

github.com/mpc-hc/mpc-hc.git - Unnamed repository; edit this file 'description' to name the repository.
summaryrefslogtreecommitdiff
path: root/src/decss
diff options
context:
space:
mode:
authorCasimir666 <casimir666@users.sourceforge.net>2006-06-25 01:37:43 +0400
committerCasimir666 <casimir666@users.sourceforge.net>2006-06-25 01:37:43 +0400
commit0868305e78da2b0742c2ce349efa041d5622ae21 (patch)
tree663fd93132c7927910ba7c13188d6332b2e3e5b2 /src/decss
parent43c8656956a0460fc4551e3ea7a39b9f3094a3e3 (diff)
git-svn-id: https://mpc-hc.svn.sourceforge.net/svnroot/mpc-hc/trunk@14 10f7b99b-c216-0410-bff0-8a66a9350fd8
Diffstat (limited to 'src/decss')
-rw-r--r--src/decss/CSSauth.cpp328
-rw-r--r--src/decss/CSSauth.h5
-rw-r--r--src/decss/CSSscramble.cpp247
-rw-r--r--src/decss/CSSscramble.h8
-rw-r--r--src/decss/DeCSSInputPin.cpp350
-rw-r--r--src/decss/DeCSSInputPin.h50
-rw-r--r--src/decss/VobDec.cpp184
-rw-r--r--src/decss/VobDec.h21
-rw-r--r--src/decss/VobFile.cpp639
-rw-r--r--src/decss/VobFile.h87
-rw-r--r--src/decss/decss.h5
-rw-r--r--src/decss/decss.sln27
-rw-r--r--src/decss/decss.vcproj284
-rw-r--r--src/decss/decss.vcproj.vspscc10
-rw-r--r--src/decss/stdafx.cpp8
-rw-r--r--src/decss/stdafx.h18
-rw-r--r--src/decss/udf.cpp355
-rw-r--r--src/decss/udf.h265
18 files changed, 2891 insertions, 0 deletions
diff --git a/src/decss/CSSauth.cpp b/src/decss/CSSauth.cpp
new file mode 100644
index 000000000..10aa2135b
--- /dev/null
+++ b/src/decss/CSSauth.cpp
@@ -0,0 +1,328 @@
+#include "stdafx.h"
+
+static void CSSengine(int varient,unsigned char const *input,unsigned char *output);
+
+void CSSkey1(int varient,unsigned char const *challenge,unsigned char *key)
+{
+ static unsigned char perm_challenge[] = {1,3,0,7,5, 2,9,6,4,8};
+
+ unsigned char scratch[10];
+ int i;
+
+ for (i = 9; i >= 0; --i)
+ scratch[i] = challenge[perm_challenge[i]];
+
+ CSSengine(varient, scratch, key);
+}
+
+void CSSkey2(int varient,unsigned char const *challenge,unsigned char *key)
+{
+ static unsigned char perm_challenge[] = {6,1,9,3,8, 5,7,4,0,2};
+
+ static unsigned char perm_varient[] = {
+ 0x0a, 0x08, 0x0e, 0x0c, 0x0b, 0x09, 0x0f, 0x0d,
+ 0x1a, 0x18, 0x1e, 0x1c, 0x1b, 0x19, 0x1f, 0x1d,
+ 0x02, 0x00, 0x06, 0x04, 0x03, 0x01, 0x07, 0x05,
+ 0x12, 0x10, 0x16, 0x14, 0x13, 0x11, 0x17, 0x15};
+
+ unsigned char scratch[10];
+ int i;
+
+ for (i = 9; i >= 0; --i)
+ scratch[i] = challenge[perm_challenge[i]];
+
+ CSSengine(perm_varient[varient], scratch, key);
+}
+
+void CSSbuskey(int varient,unsigned char const *challenge,unsigned char *key)
+{
+ static unsigned char perm_challenge[] = {4,0,3,5,7, 2,8,6,1,9};
+ static unsigned char perm_varient[] = {
+ 0x12, 0x1a, 0x16, 0x1e, 0x02, 0x0a, 0x06, 0x0e,
+ 0x10, 0x18, 0x14, 0x1c, 0x00, 0x08, 0x04, 0x0c,
+ 0x13, 0x1b, 0x17, 0x1f, 0x03, 0x0b, 0x07, 0x0f,
+ 0x11, 0x19, 0x15, 0x1d, 0x01, 0x09, 0x05, 0x0d};
+
+ unsigned char scratch[10];
+ int i;
+
+ for (i = 9; i >= 0; --i)
+ scratch[i] = challenge[perm_challenge[i]];
+
+ CSSengine(perm_varient[varient], scratch, key);
+}
+
+static void CSSgenbits(unsigned char *output, int len,unsigned char const *s)
+{
+ unsigned long lfsr0, lfsr1;
+ unsigned char b1_combined; /* Save the old value of bit 1 for feedback */
+
+ /* In order to ensure that the LFSR works we need to ensure that the
+ * initial values are non-zero. Thus when we initialise them from
+ * the seed, we ensure that a bit is set.
+ */
+ lfsr0 = (s[0] << 17) | (s[1] << 9) | ((s[2] & ~7) << 1) | 8 | (s[2] & 7);
+ lfsr1 = (s[3] << 9) | 0x100 | s[4];
+
+ ++output;
+
+ b1_combined = 0;
+ do {
+ int bit;
+ unsigned char val;
+
+ for (bit = 0, val = 0; bit < 8; ++bit) {
+ unsigned char o_lfsr0, o_lfsr1; /* Actually only 1 bit each */
+ unsigned char combined;
+
+ o_lfsr0 = ((lfsr0 >> 24) ^ (lfsr0 >> 21) ^ (lfsr0 >> 20) ^ (lfsr0 >> 12)) & 1;
+ lfsr0 = (lfsr0 << 1) | o_lfsr0;
+
+ o_lfsr1 = ((lfsr1 >> 16) ^ (lfsr1 >> 2)) & 1;
+ lfsr1 = (lfsr1 << 1) | o_lfsr1;
+
+#define BIT0(x) ((x) & 1)
+#define BIT1(x) (((x) >> 1) & 1)
+
+ combined = !o_lfsr1 + b1_combined + !o_lfsr0;
+ b1_combined = BIT1(combined);
+ val |= BIT0(combined) << bit;
+ }
+
+ *--output = val;
+ } while (--len > 0);
+}
+
+unsigned char CSSsecret[];
+unsigned char CSSvarients[];
+unsigned char CSStable0[];
+unsigned char CSStable1[];
+unsigned char CSStable2[];
+unsigned char CSStable3[];
+
+static void CSSengine(int varient, unsigned char const *input,unsigned char *output)
+{
+ unsigned char cse, term, index;
+ unsigned char temp1[5];
+ unsigned char temp2[5];
+ unsigned char bits[30];
+
+ int i;
+
+ /* Feed the CSSsecret into the input values such that
+ * we alter the seed to the LFSR's used above, then
+ * generate the bits to play with.
+ */
+ for (i = 5; --i >= 0; )
+ temp1[i] = input[5 + i] ^ CSSsecret[i] ^ CSStable2[i];
+
+ CSSgenbits(&bits[29], sizeof bits, temp1);
+
+ /* This term is used throughout the following to
+ * select one of 32 different variations on the
+ * algorithm.
+ */
+ cse = CSSvarients[varient] ^ CSStable2[varient];
+
+ /* Now the actual blocks doing the encryption. Each
+ * of these works on 40 bits at a time and are quite
+ * similar.
+ */
+ for (i = 5, term = 0; --i >= 0; term = input[i]) {
+ index = bits[25 + i] ^ input[i];
+ index = CSStable1[index] ^ ~CSStable2[index] ^ cse;
+
+ temp1[i] = CSStable2[index] ^ CSStable3[index] ^ term;
+ }
+ temp1[4] ^= temp1[0];
+
+ for (i = 5, term = 0; --i >= 0; term = temp1[i]) {
+ index = bits[20 + i] ^ temp1[i];
+ index = CSStable1[index] ^ ~CSStable2[index] ^ cse;
+
+ temp2[i] = CSStable2[index] ^ CSStable3[index] ^ term;
+ }
+ temp2[4] ^= temp2[0];
+
+ for (i = 5, term = 0; --i >= 0; term = temp2[i]) {
+ index = bits[15 + i] ^ temp2[i];
+ index = CSStable1[index] ^ ~CSStable2[index] ^ cse;
+ index = CSStable2[index] ^ CSStable3[index] ^ term;
+
+ temp1[i] = CSStable0[index] ^ CSStable2[index];
+ }
+ temp1[4] ^= temp1[0];
+
+ for (i = 5, term = 0; --i >= 0; term = temp1[i]) {
+ index = bits[10 + i] ^ temp1[i];
+ index = CSStable1[index] ^ ~CSStable2[index] ^ cse;
+
+ index = CSStable2[index] ^ CSStable3[index] ^ term;
+
+ temp2[i] = CSStable0[index] ^ CSStable2[index];
+ }
+ temp2[4] ^= temp2[0];
+
+ for (i = 5, term = 0; --i >= 0; term = temp2[i]) {
+ index = bits[5 + i] ^ temp2[i];
+ index = CSStable1[index] ^ ~CSStable2[index] ^ cse;
+
+ temp1[i] = CSStable2[index] ^ CSStable3[index] ^ term;
+ }
+ temp1[4] ^= temp1[0];
+
+ for (i = 5, term = 0; --i >= 0; term = temp1[i]) {
+ index = bits[i] ^ temp1[i];
+ index = CSStable1[index] ^ ~CSStable2[index] ^ cse;
+
+ output[i] = CSStable2[index] ^ CSStable3[index] ^ term;
+ }
+}
+
+static unsigned char CSSvarients[] = {
+ 0xB7, 0x74, 0x85, 0xD0, 0xCC, 0xDB, 0xCA, 0x73,
+ 0x03, 0xFE, 0x31, 0x03, 0x52, 0xE0, 0xB7, 0x42,
+ 0x63, 0x16, 0xF2, 0x2A, 0x79, 0x52, 0xFF, 0x1B,
+ 0x7A, 0x11, 0xCA, 0x1A, 0x9B, 0x40, 0xAD, 0x01};
+
+static unsigned char CSSsecret[] = {0x55, 0xD6, 0xC4, 0xC5, 0x28};
+
+static unsigned char CSStable0[] = {
+ 0xB7, 0xF4, 0x82, 0x57, 0xDA, 0x4D, 0xDB, 0xE2,
+ 0x2F, 0x52, 0x1A, 0xA8, 0x68, 0x5A, 0x8A, 0xFF,
+ 0xFB, 0x0E, 0x6D, 0x35, 0xF7, 0x5C, 0x76, 0x12,
+ 0xCE, 0x25, 0x79, 0x29, 0x39, 0x62, 0x08, 0x24,
+ 0xA5, 0x85, 0x7B, 0x56, 0x01, 0x23, 0x68, 0xCF,
+ 0x0A, 0xE2, 0x5A, 0xED, 0x3D, 0x59, 0xB0, 0xA9,
+ 0xB0, 0x2C, 0xF2, 0xB8, 0xEF, 0x32, 0xA9, 0x40,
+ 0x80, 0x71, 0xAF, 0x1E, 0xDE, 0x8F, 0x58, 0x88,
+ 0xB8, 0x3A, 0xD0, 0xFC, 0xC4, 0x1E, 0xB5, 0xA0,
+ 0xBB, 0x3B, 0x0F, 0x01, 0x7E, 0x1F, 0x9F, 0xD9,
+ 0xAA, 0xB8, 0x3D, 0x9D, 0x74, 0x1E, 0x25, 0xDB,
+ 0x37, 0x56, 0x8F, 0x16, 0xBA, 0x49, 0x2B, 0xAC,
+ 0xD0, 0xBD, 0x95, 0x20, 0xBE, 0x7A, 0x28, 0xD0,
+ 0x51, 0x64, 0x63, 0x1C, 0x7F, 0x66, 0x10, 0xBB,
+ 0xC4, 0x56, 0x1A, 0x04, 0x6E, 0x0A, 0xEC, 0x9C,
+ 0xD6, 0xE8, 0x9A, 0x7A, 0xCF, 0x8C, 0xDB, 0xB1,
+ 0xEF, 0x71, 0xDE, 0x31, 0xFF, 0x54, 0x3E, 0x5E,
+ 0x07, 0x69, 0x96, 0xB0, 0xCF, 0xDD, 0x9E, 0x47,
+ 0xC7, 0x96, 0x8F, 0xE4, 0x2B, 0x59, 0xC6, 0xEE,
+ 0xB9, 0x86, 0x9A, 0x64, 0x84, 0x72, 0xE2, 0x5B,
+ 0xA2, 0x96, 0x58, 0x99, 0x50, 0x03, 0xF5, 0x38,
+ 0x4D, 0x02, 0x7D, 0xE7, 0x7D, 0x75, 0xA7, 0xB8,
+ 0x67, 0x87, 0x84, 0x3F, 0x1D, 0x11, 0xE5, 0xFC,
+ 0x1E, 0xD3, 0x83, 0x16, 0xA5, 0x29, 0xF6, 0xC7,
+ 0x15, 0x61, 0x29, 0x1A, 0x43, 0x4F, 0x9B, 0xAF,
+ 0xC5, 0x87, 0x34, 0x6C, 0x0F, 0x3B, 0xA8, 0x1D,
+ 0x45, 0x58, 0x25, 0xDC, 0xA8, 0xA3, 0x3B, 0xD1,
+ 0x79, 0x1B, 0x48, 0xF2, 0xE9, 0x93, 0x1F, 0xFC,
+ 0xDB, 0x2A, 0x90, 0xA9, 0x8A, 0x3D, 0x39, 0x18,
+ 0xA3, 0x8E, 0x58, 0x6C, 0xE0, 0x12, 0xBB, 0x25,
+ 0xCD, 0x71, 0x22, 0xA2, 0x64, 0xC6, 0xE7, 0xFB,
+ 0xAD, 0x94, 0x77, 0x04, 0x9A, 0x39, 0xCF, 0x7C};
+
+static unsigned char CSStable1[] = {
+ 0x8C, 0x47, 0xB0, 0xE1, 0xEB, 0xFC, 0xEB, 0x56,
+ 0x10, 0xE5, 0x2C, 0x1A, 0x5D, 0xEF, 0xBE, 0x4F,
+ 0x08, 0x75, 0x97, 0x4B, 0x0E, 0x25, 0x8E, 0x6E,
+ 0x39, 0x5A, 0x87, 0x53, 0xC4, 0x1F, 0xF4, 0x5C,
+ 0x4E, 0xE6, 0x99, 0x30, 0xE0, 0x42, 0x88, 0xAB,
+ 0xE5, 0x85, 0xBC, 0x8F, 0xD8, 0x3C, 0x54, 0xC9,
+ 0x53, 0x47, 0x18, 0xD6, 0x06, 0x5B, 0x41, 0x2C,
+ 0x67, 0x1E, 0x41, 0x74, 0x33, 0xE2, 0xB4, 0xE0,
+ 0x23, 0x29, 0x42, 0xEA, 0x55, 0x0F, 0x25, 0xB4,
+ 0x24, 0x2C, 0x99, 0x13, 0xEB, 0x0A, 0x0B, 0xC9,
+ 0xF9, 0x63, 0x67, 0x43, 0x2D, 0xC7, 0x7D, 0x07,
+ 0x60, 0x89, 0xD1, 0xCC, 0xE7, 0x94, 0x77, 0x74,
+ 0x9B, 0x7E, 0xD7, 0xE6, 0xFF, 0xBB, 0x68, 0x14,
+ 0x1E, 0xA3, 0x25, 0xDE, 0x3A, 0xA3, 0x54, 0x7B,
+ 0x87, 0x9D, 0x50, 0xCA, 0x27, 0xC3, 0xA4, 0x50,
+ 0x91, 0x27, 0xD4, 0xB0, 0x82, 0x41, 0x97, 0x79,
+ 0x94, 0x82, 0xAC, 0xC7, 0x8E, 0xA5, 0x4E, 0xAA,
+ 0x78, 0x9E, 0xE0, 0x42, 0xBA, 0x28, 0xEA, 0xB7,
+ 0x74, 0xAD, 0x35, 0xDA, 0x92, 0x60, 0x7E, 0xD2,
+ 0x0E, 0xB9, 0x24, 0x5E, 0x39, 0x4F, 0x5E, 0x63,
+ 0x09, 0xB5, 0xFA, 0xBF, 0xF1, 0x22, 0x55, 0x1C,
+ 0xE2, 0x25, 0xDB, 0xC5, 0xD8, 0x50, 0x03, 0x98,
+ 0xC4, 0xAC, 0x2E, 0x11, 0xB4, 0x38, 0x4D, 0xD0,
+ 0xB9, 0xFC, 0x2D, 0x3C, 0x08, 0x04, 0x5A, 0xEF,
+ 0xCE, 0x32, 0xFB, 0x4C, 0x92, 0x1E, 0x4B, 0xFB,
+ 0x1A, 0xD0, 0xE2, 0x3E, 0xDA, 0x6E, 0x7C, 0x4D,
+ 0x56, 0xC3, 0x3F, 0x42, 0xB1, 0x3A, 0x23, 0x4D,
+ 0x6E, 0x84, 0x56, 0x68, 0xF4, 0x0E, 0x03, 0x64,
+ 0xD0, 0xA9, 0x92, 0x2F, 0x8B, 0xBC, 0x39, 0x9C,
+ 0xAC, 0x09, 0x5E, 0xEE, 0xE5, 0x97, 0xBF, 0xA5,
+ 0xCE, 0xFA, 0x28, 0x2C, 0x6D, 0x4F, 0xEF, 0x77,
+ 0xAA, 0x1B, 0x79, 0x8E, 0x97, 0xB4, 0xC3, 0xF4};
+
+static unsigned char CSStable2[] = {
+ 0xB7, 0x75, 0x81, 0xD5, 0xDC, 0xCA, 0xDE, 0x66,
+ 0x23, 0xDF, 0x15, 0x26, 0x62, 0xD1, 0x83, 0x77,
+ 0xE3, 0x97, 0x76, 0xAF, 0xE9, 0xC3, 0x6B, 0x8E,
+ 0xDA, 0xB0, 0x6E, 0xBF, 0x2B, 0xF1, 0x19, 0xB4,
+ 0x95, 0x34, 0x48, 0xE4, 0x37, 0x94, 0x5D, 0x7B,
+ 0x36, 0x5F, 0x65, 0x53, 0x07, 0xE2, 0x89, 0x11,
+ 0x98, 0x85, 0xD9, 0x12, 0xC1, 0x9D, 0x84, 0xEC,
+ 0xA4, 0xD4, 0x88, 0xB8, 0xFC, 0x2C, 0x79, 0x28,
+ 0xD8, 0xDB, 0xB3, 0x1E, 0xA2, 0xF9, 0xD0, 0x44,
+ 0xD7, 0xD6, 0x60, 0xEF, 0x14, 0xF4, 0xF6, 0x31,
+ 0xD2, 0x41, 0x46, 0x67, 0x0A, 0xE1, 0x58, 0x27,
+ 0x43, 0xA3, 0xF8, 0xE0, 0xC8, 0xBA, 0x5A, 0x5C,
+ 0x80, 0x6C, 0xC6, 0xF2, 0xE8, 0xAD, 0x7D, 0x04,
+ 0x0D, 0xB9, 0x3C, 0xC2, 0x25, 0xBD, 0x49, 0x63,
+ 0x8C, 0x9F, 0x51, 0xCE, 0x20, 0xC5, 0xA1, 0x50,
+ 0x92, 0x2D, 0xDD, 0xBC, 0x8D, 0x4F, 0x9A, 0x71,
+ 0x2F, 0x30, 0x1D, 0x73, 0x39, 0x13, 0xFB, 0x1A,
+ 0xCB, 0x24, 0x59, 0xFE, 0x05, 0x96, 0x57, 0x0F,
+ 0x1F, 0xCF, 0x54, 0xBE, 0xF5, 0x06, 0x1B, 0xB2,
+ 0x6D, 0xD3, 0x4D, 0x32, 0x56, 0x21, 0x33, 0x0B,
+ 0x52, 0xE7, 0xAB, 0xEB, 0xA6, 0x74, 0x00, 0x4C,
+ 0xB1, 0x7F, 0x82, 0x99, 0x87, 0x0E, 0x5E, 0xC0,
+ 0x8F, 0xEE, 0x6F, 0x55, 0xF3, 0x7E, 0x08, 0x90,
+ 0xFA, 0xB6, 0x64, 0x70, 0x47, 0x4A, 0x17, 0xA7,
+ 0xB5, 0x40, 0x8A, 0x38, 0xE5, 0x68, 0x3E, 0x8B,
+ 0x69, 0xAA, 0x9B, 0x42, 0xA5, 0x10, 0x01, 0x35,
+ 0xFD, 0x61, 0x9E, 0xE6, 0x16, 0x9C, 0x86, 0xED,
+ 0xCD, 0x2E, 0xFF, 0xC4, 0x5B, 0xA0, 0xAE, 0xCC,
+ 0x4B, 0x3B, 0x03, 0xBB, 0x1C, 0x2A, 0xAC, 0x0C,
+ 0x3F, 0x93, 0xC7, 0x72, 0x7A, 0x09, 0x22, 0x3D,
+ 0x45, 0x78, 0xA9, 0xA8, 0xEA, 0xC9, 0x6A, 0xF7,
+ 0x29, 0x91, 0xF0, 0x02, 0x18, 0x3A, 0x4E, 0x7C};
+
+static unsigned char CSStable3[] = {
+ 0x73, 0x51, 0x95, 0xE1, 0x12, 0xE4, 0xC0, 0x58,
+ 0xEE, 0xF2, 0x08, 0x1B, 0xA9, 0xFA, 0x98, 0x4C,
+ 0xA7, 0x33, 0xE2, 0x1B, 0xA7, 0x6D, 0xF5, 0x30,
+ 0x97, 0x1D, 0xF3, 0x02, 0x60, 0x5A, 0x82, 0x0F,
+ 0x91, 0xD0, 0x9C, 0x10, 0x39, 0x7A, 0x83, 0x85,
+ 0x3B, 0xB2, 0xB8, 0xAE, 0x0C, 0x09, 0x52, 0xEA,
+ 0x1C, 0xE1, 0x8D, 0x66, 0x4F, 0xF3, 0xDA, 0x92,
+ 0x29, 0xB9, 0xD5, 0xC5, 0x77, 0x47, 0x22, 0x53,
+ 0x14, 0xF7, 0xAF, 0x22, 0x64, 0xDF, 0xC6, 0x72,
+ 0x12, 0xF3, 0x75, 0xDA, 0xD7, 0xD7, 0xE5, 0x02,
+ 0x9E, 0xED, 0xDA, 0xDB, 0x4C, 0x47, 0xCE, 0x91,
+ 0x06, 0x06, 0x6D, 0x55, 0x8B, 0x19, 0xC9, 0xEF,
+ 0x8C, 0x80, 0x1A, 0x0E, 0xEE, 0x4B, 0xAB, 0xF2,
+ 0x08, 0x5C, 0xE9, 0x37, 0x26, 0x5E, 0x9A, 0x90,
+ 0x00, 0xF3, 0x0D, 0xB2, 0xA6, 0xA3, 0xF7, 0x26,
+ 0x17, 0x48, 0x88, 0xC9, 0x0E, 0x2C, 0xC9, 0x02,
+ 0xE7, 0x18, 0x05, 0x4B, 0xF3, 0x39, 0xE1, 0x20,
+ 0x02, 0x0D, 0x40, 0xC7, 0xCA, 0xB9, 0x48, 0x30,
+ 0x57, 0x67, 0xCC, 0x06, 0xBF, 0xAC, 0x81, 0x08,
+ 0x24, 0x7A, 0xD4, 0x8B, 0x19, 0x8E, 0xAC, 0xB4,
+ 0x5A, 0x0F, 0x73, 0x13, 0xAC, 0x9E, 0xDA, 0xB6,
+ 0xB8, 0x96, 0x5B, 0x60, 0x88, 0xE1, 0x81, 0x3F,
+ 0x07, 0x86, 0x37, 0x2D, 0x79, 0x14, 0x52, 0xEA,
+ 0x73, 0xDF, 0x3D, 0x09, 0xC8, 0x25, 0x48, 0xD8,
+ 0x75, 0x60, 0x9A, 0x08, 0x27, 0x4A, 0x2C, 0xB9,
+ 0xA8, 0x8B, 0x8A, 0x73, 0x62, 0x37, 0x16, 0x02,
+ 0xBD, 0xC1, 0x0E, 0x56, 0x54, 0x3E, 0x14, 0x5F,
+ 0x8C, 0x8F, 0x6E, 0x75, 0x1C, 0x07, 0x39, 0x7B,
+ 0x4B, 0xDB, 0xD3, 0x4B, 0x1E, 0xC8, 0x7E, 0xFE,
+ 0x3E, 0x72, 0x16, 0x83, 0x7D, 0xEE, 0xF5, 0xCA,
+ 0xC5, 0x18, 0xF9, 0xD8, 0x68, 0xAB, 0x38, 0x85,
+ 0xA8, 0xF0, 0xA1, 0x73, 0x9F, 0x5D, 0x19, 0x0B,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x33, 0x72, 0x39, 0x25, 0x67, 0x26, 0x6D, 0x71,
+ 0x36, 0x77, 0x3C, 0x20, 0x62, 0x23, 0x68, 0x74,
+ 0xC3, 0x82, 0xC9, 0x15, 0x57, 0x16, 0x5D, 0x81};
diff --git a/src/decss/CSSauth.h b/src/decss/CSSauth.h
new file mode 100644
index 000000000..9929ae887
--- /dev/null
+++ b/src/decss/CSSauth.h
@@ -0,0 +1,5 @@
+#pragma once
+
+extern void CSSkey1(int varient, byte const *challenge, byte *key);
+extern void CSSkey2(int varient, byte const *challenge, byte *key);
+extern void CSSbuskey(int varient, byte const *challenge, byte *key);
diff --git a/src/decss/CSSscramble.cpp b/src/decss/CSSscramble.cpp
new file mode 100644
index 000000000..87f251d21
--- /dev/null
+++ b/src/decss/CSSscramble.cpp
@@ -0,0 +1,247 @@
+#include "stdafx.h"
+
+#ifndef countof
+#define countof(array) (sizeof(array)/sizeof(array[0]))
+#endif
+
+unsigned int CSStab0[11]={5,0,1,2,3,4,0,1,2,3,4};
+
+unsigned char CSStab1[256]=
+{
+ 0x33,0x73,0x3b,0x26,0x63,0x23,0x6b,0x76,0x3e,0x7e,0x36,0x2b,0x6e,0x2e,0x66,0x7b,
+ 0xd3,0x93,0xdb,0x06,0x43,0x03,0x4b,0x96,0xde,0x9e,0xd6,0x0b,0x4e,0x0e,0x46,0x9b,
+ 0x57,0x17,0x5f,0x82,0xc7,0x87,0xcf,0x12,0x5a,0x1a,0x52,0x8f,0xca,0x8a,0xc2,0x1f,
+ 0xd9,0x99,0xd1,0x00,0x49,0x09,0x41,0x90,0xd8,0x98,0xd0,0x01,0x48,0x08,0x40,0x91,
+ 0x3d,0x7d,0x35,0x24,0x6d,0x2d,0x65,0x74,0x3c,0x7c,0x34,0x25,0x6c,0x2c,0x64,0x75,
+ 0xdd,0x9d,0xd5,0x04,0x4d,0x0d,0x45,0x94,0xdc,0x9c,0xd4,0x05,0x4c,0x0c,0x44,0x95,
+ 0x59,0x19,0x51,0x80,0xc9,0x89,0xc1,0x10,0x58,0x18,0x50,0x81,0xc8,0x88,0xc0,0x11,
+ 0xd7,0x97,0xdf,0x02,0x47,0x07,0x4f,0x92,0xda,0x9a,0xd2,0x0f,0x4a,0x0a,0x42,0x9f,
+ 0x53,0x13,0x5b,0x86,0xc3,0x83,0xcb,0x16,0x5e,0x1e,0x56,0x8b,0xce,0x8e,0xc6,0x1b,
+ 0xb3,0xf3,0xbb,0xa6,0xe3,0xa3,0xeb,0xf6,0xbe,0xfe,0xb6,0xab,0xee,0xae,0xe6,0xfb,
+ 0x37,0x77,0x3f,0x22,0x67,0x27,0x6f,0x72,0x3a,0x7a,0x32,0x2f,0x6a,0x2a,0x62,0x7f,
+ 0xb9,0xf9,0xb1,0xa0,0xe9,0xa9,0xe1,0xf0,0xb8,0xf8,0xb0,0xa1,0xe8,0xa8,0xe0,0xf1,
+ 0x5d,0x1d,0x55,0x84,0xcd,0x8d,0xc5,0x14,0x5c,0x1c,0x54,0x85,0xcc,0x8c,0xc4,0x15,
+ 0xbd,0xfd,0xb5,0xa4,0xed,0xad,0xe5,0xf4,0xbc,0xfc,0xb4,0xa5,0xec,0xac,0xe4,0xf5,
+ 0x39,0x79,0x31,0x20,0x69,0x29,0x61,0x70,0x38,0x78,0x30,0x21,0x68,0x28,0x60,0x71,
+ 0xb7,0xf7,0xbf,0xa2,0xe7,0xa7,0xef,0xf2,0xba,0xfa,0xb2,0xaf,0xea,0xaa,0xe2,0xff
+};
+
+unsigned char CSStab2[256]=
+{
+ 0x00,0x01,0x02,0x03,0x04,0x05,0x06,0x07,0x09,0x08,0x0b,0x0a,0x0d,0x0c,0x0f,0x0e,
+ 0x12,0x13,0x10,0x11,0x16,0x17,0x14,0x15,0x1b,0x1a,0x19,0x18,0x1f,0x1e,0x1d,0x1c,
+ 0x24,0x25,0x26,0x27,0x20,0x21,0x22,0x23,0x2d,0x2c,0x2f,0x2e,0x29,0x28,0x2b,0x2a,
+ 0x36,0x37,0x34,0x35,0x32,0x33,0x30,0x31,0x3f,0x3e,0x3d,0x3c,0x3b,0x3a,0x39,0x38,
+ 0x49,0x48,0x4b,0x4a,0x4d,0x4c,0x4f,0x4e,0x40,0x41,0x42,0x43,0x44,0x45,0x46,0x47,
+ 0x5b,0x5a,0x59,0x58,0x5f,0x5e,0x5d,0x5c,0x52,0x53,0x50,0x51,0x56,0x57,0x54,0x55,
+ 0x6d,0x6c,0x6f,0x6e,0x69,0x68,0x6b,0x6a,0x64,0x65,0x66,0x67,0x60,0x61,0x62,0x63,
+ 0x7f,0x7e,0x7d,0x7c,0x7b,0x7a,0x79,0x78,0x76,0x77,0x74,0x75,0x72,0x73,0x70,0x71,
+ 0x92,0x93,0x90,0x91,0x96,0x97,0x94,0x95,0x9b,0x9a,0x99,0x98,0x9f,0x9e,0x9d,0x9c,
+ 0x80,0x81,0x82,0x83,0x84,0x85,0x86,0x87,0x89,0x88,0x8b,0x8a,0x8d,0x8c,0x8f,0x8e,
+ 0xb6,0xb7,0xb4,0xb5,0xb2,0xb3,0xb0,0xb1,0xbf,0xbe,0xbd,0xbc,0xbb,0xba,0xb9,0xb8,
+ 0xa4,0xa5,0xa6,0xa7,0xa0,0xa1,0xa2,0xa3,0xad,0xac,0xaf,0xae,0xa9,0xa8,0xab,0xaa,
+ 0xdb,0xda,0xd9,0xd8,0xdf,0xde,0xdd,0xdc,0xd2,0xd3,0xd0,0xd1,0xd6,0xd7,0xd4,0xd5,
+ 0xc9,0xc8,0xcb,0xca,0xcd,0xcc,0xcf,0xce,0xc0,0xc1,0xc2,0xc3,0xc4,0xc5,0xc6,0xc7,
+ 0xff,0xfe,0xfd,0xfc,0xfb,0xfa,0xf9,0xf8,0xf6,0xf7,0xf4,0xf5,0xf2,0xf3,0xf0,0xf1,
+ 0xed,0xec,0xef,0xee,0xe9,0xe8,0xeb,0xea,0xe4,0xe5,0xe6,0xe7,0xe0,0xe1,0xe2,0xe3
+};
+
+unsigned char CSStab3[512]=
+{
+ 0x00,0x24,0x49,0x6d,0x92,0xb6,0xdb,0xff,0x00,0x24,0x49,0x6d,0x92,0xb6,0xdb,0xff,
+ 0x00,0x24,0x49,0x6d,0x92,0xb6,0xdb,0xff,0x00,0x24,0x49,0x6d,0x92,0xb6,0xdb,0xff,
+ 0x00,0x24,0x49,0x6d,0x92,0xb6,0xdb,0xff,0x00,0x24,0x49,0x6d,0x92,0xb6,0xdb,0xff,
+ 0x00,0x24,0x49,0x6d,0x92,0xb6,0xdb,0xff,0x00,0x24,0x49,0x6d,0x92,0xb6,0xdb,0xff,
+ 0x00,0x24,0x49,0x6d,0x92,0xb6,0xdb,0xff,0x00,0x24,0x49,0x6d,0x92,0xb6,0xdb,0xff,
+ 0x00,0x24,0x49,0x6d,0x92,0xb6,0xdb,0xff,0x00,0x24,0x49,0x6d,0x92,0xb6,0xdb,0xff,
+ 0x00,0x24,0x49,0x6d,0x92,0xb6,0xdb,0xff,0x00,0x24,0x49,0x6d,0x92,0xb6,0xdb,0xff,
+ 0x00,0x24,0x49,0x6d,0x92,0xb6,0xdb,0xff,0x00,0x24,0x49,0x6d,0x92,0xb6,0xdb,0xff,
+ 0x00,0x24,0x49,0x6d,0x92,0xb6,0xdb,0xff,0x00,0x24,0x49,0x6d,0x92,0xb6,0xdb,0xff,
+ 0x00,0x24,0x49,0x6d,0x92,0xb6,0xdb,0xff,0x00,0x24,0x49,0x6d,0x92,0xb6,0xdb,0xff,
+ 0x00,0x24,0x49,0x6d,0x92,0xb6,0xdb,0xff,0x00,0x24,0x49,0x6d,0x92,0xb6,0xdb,0xff,
+ 0x00,0x24,0x49,0x6d,0x92,0xb6,0xdb,0xff,0x00,0x24,0x49,0x6d,0x92,0xb6,0xdb,0xff,
+ 0x00,0x24,0x49,0x6d,0x92,0xb6,0xdb,0xff,0x00,0x24,0x49,0x6d,0x92,0xb6,0xdb,0xff,
+ 0x00,0x24,0x49,0x6d,0x92,0xb6,0xdb,0xff,0x00,0x24,0x49,0x6d,0x92,0xb6,0xdb,0xff,
+ 0x00,0x24,0x49,0x6d,0x92,0xb6,0xdb,0xff,0x00,0x24,0x49,0x6d,0x92,0xb6,0xdb,0xff,
+ 0x00,0x24,0x49,0x6d,0x92,0xb6,0xdb,0xff,0x00,0x24,0x49,0x6d,0x92,0xb6,0xdb,0xff,
+ 0x00,0x24,0x49,0x6d,0x92,0xb6,0xdb,0xff,0x00,0x24,0x49,0x6d,0x92,0xb6,0xdb,0xff,
+ 0x00,0x24,0x49,0x6d,0x92,0xb6,0xdb,0xff,0x00,0x24,0x49,0x6d,0x92,0xb6,0xdb,0xff,
+ 0x00,0x24,0x49,0x6d,0x92,0xb6,0xdb,0xff,0x00,0x24,0x49,0x6d,0x92,0xb6,0xdb,0xff,
+ 0x00,0x24,0x49,0x6d,0x92,0xb6,0xdb,0xff,0x00,0x24,0x49,0x6d,0x92,0xb6,0xdb,0xff,
+ 0x00,0x24,0x49,0x6d,0x92,0xb6,0xdb,0xff,0x00,0x24,0x49,0x6d,0x92,0xb6,0xdb,0xff,
+ 0x00,0x24,0x49,0x6d,0x92,0xb6,0xdb,0xff,0x00,0x24,0x49,0x6d,0x92,0xb6,0xdb,0xff,
+ 0x00,0x24,0x49,0x6d,0x92,0xb6,0xdb,0xff,0x00,0x24,0x49,0x6d,0x92,0xb6,0xdb,0xff,
+ 0x00,0x24,0x49,0x6d,0x92,0xb6,0xdb,0xff,0x00,0x24,0x49,0x6d,0x92,0xb6,0xdb,0xff,
+ 0x00,0x24,0x49,0x6d,0x92,0xb6,0xdb,0xff,0x00,0x24,0x49,0x6d,0x92,0xb6,0xdb,0xff,
+ 0x00,0x24,0x49,0x6d,0x92,0xb6,0xdb,0xff,0x00,0x24,0x49,0x6d,0x92,0xb6,0xdb,0xff,
+ 0x00,0x24,0x49,0x6d,0x92,0xb6,0xdb,0xff,0x00,0x24,0x49,0x6d,0x92,0xb6,0xdb,0xff,
+ 0x00,0x24,0x49,0x6d,0x92,0xb6,0xdb,0xff,0x00,0x24,0x49,0x6d,0x92,0xb6,0xdb,0xff,
+ 0x00,0x24,0x49,0x6d,0x92,0xb6,0xdb,0xff,0x00,0x24,0x49,0x6d,0x92,0xb6,0xdb,0xff,
+ 0x00,0x24,0x49,0x6d,0x92,0xb6,0xdb,0xff,0x00,0x24,0x49,0x6d,0x92,0xb6,0xdb,0xff,
+ 0x00,0x24,0x49,0x6d,0x92,0xb6,0xdb,0xff,0x00,0x24,0x49,0x6d,0x92,0xb6,0xdb,0xff,
+ 0x00,0x24,0x49,0x6d,0x92,0xb6,0xdb,0xff,0x00,0x24,0x49,0x6d,0x92,0xb6,0xdb,0xff
+};
+
+unsigned char CSStab4[256]=
+{
+ 0x00,0x80,0x40,0xc0,0x20,0xa0,0x60,0xe0,0x10,0x90,0x50,0xd0,0x30,0xb0,0x70,0xf0,
+ 0x08,0x88,0x48,0xc8,0x28,0xa8,0x68,0xe8,0x18,0x98,0x58,0xd8,0x38,0xb8,0x78,0xf8,
+ 0x04,0x84,0x44,0xc4,0x24,0xa4,0x64,0xe4,0x14,0x94,0x54,0xd4,0x34,0xb4,0x74,0xf4,
+ 0x0c,0x8c,0x4c,0xcc,0x2c,0xac,0x6c,0xec,0x1c,0x9c,0x5c,0xdc,0x3c,0xbc,0x7c,0xfc,
+ 0x02,0x82,0x42,0xc2,0x22,0xa2,0x62,0xe2,0x12,0x92,0x52,0xd2,0x32,0xb2,0x72,0xf2,
+ 0x0a,0x8a,0x4a,0xca,0x2a,0xaa,0x6a,0xea,0x1a,0x9a,0x5a,0xda,0x3a,0xba,0x7a,0xfa,
+ 0x06,0x86,0x46,0xc6,0x26,0xa6,0x66,0xe6,0x16,0x96,0x56,0xd6,0x36,0xb6,0x76,0xf6,
+ 0x0e,0x8e,0x4e,0xce,0x2e,0xae,0x6e,0xee,0x1e,0x9e,0x5e,0xde,0x3e,0xbe,0x7e,0xfe,
+ 0x01,0x81,0x41,0xc1,0x21,0xa1,0x61,0xe1,0x11,0x91,0x51,0xd1,0x31,0xb1,0x71,0xf1,
+ 0x09,0x89,0x49,0xc9,0x29,0xa9,0x69,0xe9,0x19,0x99,0x59,0xd9,0x39,0xb9,0x79,0xf9,
+ 0x05,0x85,0x45,0xc5,0x25,0xa5,0x65,0xe5,0x15,0x95,0x55,0xd5,0x35,0xb5,0x75,0xf5,
+ 0x0d,0x8d,0x4d,0xcd,0x2d,0xad,0x6d,0xed,0x1d,0x9d,0x5d,0xdd,0x3d,0xbd,0x7d,0xfd,
+ 0x03,0x83,0x43,0xc3,0x23,0xa3,0x63,0xe3,0x13,0x93,0x53,0xd3,0x33,0xb3,0x73,0xf3,
+ 0x0b,0x8b,0x4b,0xcb,0x2b,0xab,0x6b,0xeb,0x1b,0x9b,0x5b,0xdb,0x3b,0xbb,0x7b,0xfb,
+ 0x07,0x87,0x47,0xc7,0x27,0xa7,0x67,0xe7,0x17,0x97,0x57,0xd7,0x37,0xb7,0x77,0xf7,
+ 0x0f,0x8f,0x4f,0xcf,0x2f,0xaf,0x6f,0xef,0x1f,0x9f,0x5f,0xdf,0x3f,0xbf,0x7f,0xff
+};
+
+unsigned char CSStab5[256]=
+{
+ 0xff,0x7f,0xbf,0x3f,0xdf,0x5f,0x9f,0x1f,0xef,0x6f,0xaf,0x2f,0xcf,0x4f,0x8f,0x0f,
+ 0xf7,0x77,0xb7,0x37,0xd7,0x57,0x97,0x17,0xe7,0x67,0xa7,0x27,0xc7,0x47,0x87,0x07,
+ 0xfb,0x7b,0xbb,0x3b,0xdb,0x5b,0x9b,0x1b,0xeb,0x6b,0xab,0x2b,0xcb,0x4b,0x8b,0x0b,
+ 0xf3,0x73,0xb3,0x33,0xd3,0x53,0x93,0x13,0xe3,0x63,0xa3,0x23,0xc3,0x43,0x83,0x03,
+ 0xfd,0x7d,0xbd,0x3d,0xdd,0x5d,0x9d,0x1d,0xed,0x6d,0xad,0x2d,0xcd,0x4d,0x8d,0x0d,
+ 0xf5,0x75,0xb5,0x35,0xd5,0x55,0x95,0x15,0xe5,0x65,0xa5,0x25,0xc5,0x45,0x85,0x05,
+ 0xf9,0x79,0xb9,0x39,0xd9,0x59,0x99,0x19,0xe9,0x69,0xa9,0x29,0xc9,0x49,0x89,0x09,
+ 0xf1,0x71,0xb1,0x31,0xd1,0x51,0x91,0x11,0xe1,0x61,0xa1,0x21,0xc1,0x41,0x81,0x01,
+ 0xfe,0x7e,0xbe,0x3e,0xde,0x5e,0x9e,0x1e,0xee,0x6e,0xae,0x2e,0xce,0x4e,0x8e,0x0e,
+ 0xf6,0x76,0xb6,0x36,0xd6,0x56,0x96,0x16,0xe6,0x66,0xa6,0x26,0xc6,0x46,0x86,0x06,
+ 0xfa,0x7a,0xba,0x3a,0xda,0x5a,0x9a,0x1a,0xea,0x6a,0xaa,0x2a,0xca,0x4a,0x8a,0x0a,
+ 0xf2,0x72,0xb2,0x32,0xd2,0x52,0x92,0x12,0xe2,0x62,0xa2,0x22,0xc2,0x42,0x82,0x02,
+ 0xfc,0x7c,0xbc,0x3c,0xdc,0x5c,0x9c,0x1c,0xec,0x6c,0xac,0x2c,0xcc,0x4c,0x8c,0x0c,
+ 0xf4,0x74,0xb4,0x34,0xd4,0x54,0x94,0x14,0xe4,0x64,0xa4,0x24,0xc4,0x44,0x84,0x04,
+ 0xf8,0x78,0xb8,0x38,0xd8,0x58,0x98,0x18,0xe8,0x68,0xa8,0x28,0xc8,0x48,0x88,0x08,
+ 0xf0,0x70,0xb0,0x30,0xd0,0x50,0x90,0x10,0xe0,0x60,0xa0,0x20,0xc0,0x40,0x80,0x00
+};
+
+void CSSdescramble(unsigned char *sec,unsigned char *tkey)
+{
+ unsigned int t1,t2,t3,t4,t5,t6;
+ unsigned char *end=sec+0x800;
+
+ t1=tkey[0]^sec[0x54]|0x100;
+ t2=tkey[1]^sec[0x55];
+ t3=(*((unsigned int *)(tkey+2)))^(*((unsigned int *)(sec+0x56)));
+ t4=t3&7;
+ t3=t3*2+8-t4;
+ sec+=0x80;
+ t5=0;
+ while(sec!=end)
+ {
+ t4=CSStab2[t2]^CSStab3[t1];
+ t2=t1>>1;
+ t1=((t1&1)<<8)^t4;
+ t4=CSStab5[t4];
+ t6=(((((((t3>>3)^t3)>>1)^t3)>>8)^t3)>>5)&0xff;
+ t3=(t3<<8)|t6;
+ t6=CSStab4[t6];
+ t5+=t6+t4;
+ *sec++=CSStab1[*sec]^(t5&0xff);
+ t5>>=8;
+ }
+}
+
+void CSSdisckey(unsigned char *dkey,unsigned char *pkey)
+{
+ unsigned int t1,t2,t3,t4,t5,t6;
+ unsigned char k[5];
+ int i;
+
+ t1=pkey[0]|0x100;
+ t2=pkey[1];
+ t3=*((unsigned int *)(pkey+2));
+ t4=t3&7;
+ t3=t3*2+8-t4;
+ t5=0;
+ for(i=0;i<5;i++)
+ {
+ t4=CSStab2[t2]^CSStab3[t1];
+ t2=t1>>1;
+ t1=((t1&1)<<8)^t4;
+ t4=CSStab4[t4];
+ t6=(((((((t3>>3)^t3)>>1)^t3)>>8)^t3)>>5)&0xff;
+ t3=(t3<<8)|t6;
+ t6=CSStab4[t6];
+ t5+=t6+t4;
+ k[i]=t5&0xff;
+ t5>>=8;
+ }
+ for(i=9;i>=0;i--)
+ dkey[CSStab0[i+1]]=k[CSStab0[i+1]]^CSStab1[dkey[CSStab0[i+1]]]^dkey[CSStab0[i]];
+}
+
+void CSStitlekey(unsigned char *tkey,unsigned char *dkey)
+{
+ unsigned int t1,t2,t3,t4,t5,t6;
+ unsigned char k[5];
+ int i;
+
+ t1=dkey[0]|0x100;
+ t2=dkey[1];
+ t3=*((unsigned int *)(dkey+2));
+ t4=t3&7;
+ t3=t3*2+8-t4;
+ t5=0;
+ for(i=0;i<5;i++)
+ {
+ t4=CSStab2[t2]^CSStab3[t1];
+ t2=t1>>1;
+ t1=((t1&1)<<8)^t4;
+ t4=CSStab4[t4];
+ t6=(((((((t3>>3)^t3)>>1)^t3)>>8)^t3)>>5)&0xff;
+ t3=(t3<<8)|t6;
+ t6=CSStab5[t6];
+ t5+=t6+t4;
+ k[i]=t5&0xff;
+ t5>>=8;
+ }
+ for(i=9;i>=0;i--)
+ tkey[CSStab0[i+1]]=k[CSStab0[i+1]]^CSStab1[tkey[CSStab0[i+1]]]^tkey[CSStab0[i]];
+}
+
+unsigned char g_PlayerKeys[][6] =
+{
+ // from mplayer:
+ {0x01, 0xaf, 0xe3, 0x12, 0x80},
+ {0x12, 0x11, 0xca, 0x04, 0x3b},
+ {0x14, 0x0c, 0x9e, 0xd0, 0x09},
+ {0x14, 0x71, 0x35, 0xba, 0xe2},
+ {0x1a, 0xa4, 0x33, 0x21, 0xa6},
+ {0x26, 0xec, 0xc4, 0xa7, 0x4e},
+ {0x2c, 0xb2, 0xc1, 0x09, 0xee},
+ {0x2f, 0x25, 0x9e, 0x96, 0xdd},
+ {0x33, 0x2f, 0x49, 0x6c, 0xe0},
+ {0x35, 0x5b, 0xc1, 0x31, 0x0f},
+ {0x36, 0x67, 0xb2, 0xe3, 0x85},
+ {0x39, 0x3d, 0xf1, 0xf1, 0xbd},
+ {0x3b, 0x31, 0x34, 0x0d, 0x91},
+ {0x45, 0xed, 0x28, 0xeb, 0xd3},
+ {0x48, 0xb7, 0x6c, 0xce, 0x69},
+ {0x4b, 0x65, 0x0d, 0xc1, 0xee},
+ {0x4c, 0xbb, 0xf5, 0x5b, 0x23},
+ {0x51, 0x67, 0x67, 0xc5, 0xe0},
+ {0x53, 0x94, 0xe1, 0x75, 0xbf},
+ {0x57, 0x2c, 0x8b, 0x31, 0xae},
+ {0x63, 0xdb, 0x4c, 0x5b, 0x4a},
+ {0x7b, 0x1e, 0x5e, 0x2b, 0x57},
+ {0x85, 0xf3, 0x85, 0xa0, 0xe0},
+ {0xab, 0x1e, 0xe7, 0x7b, 0x72},
+ {0xab, 0x36, 0xe3, 0xeb, 0x76},
+ {0xb1, 0xb8, 0xf9, 0x38, 0x03},
+ {0xb8, 0x5d, 0xd8, 0x53, 0xbd},
+ {0xbf, 0x92, 0xc3, 0xb0, 0xe2},
+ {0xcf, 0x1a, 0xb2, 0xf8, 0x0a},
+ {0xec, 0xa0, 0xcf, 0xb3, 0xff},
+ {0xfc, 0x95, 0xa9, 0x87, 0x35}
+ // TODO: find more player keys
+};
+
+int g_nPlayerKeys = countof(g_PlayerKeys);
diff --git a/src/decss/CSSscramble.h b/src/decss/CSSscramble.h
new file mode 100644
index 000000000..0ea8d9f42
--- /dev/null
+++ b/src/decss/CSSscramble.h
@@ -0,0 +1,8 @@
+#pragma once
+
+extern void CSSdisckey(unsigned char *dkey,unsigned char *pkey);
+extern void CSStitlekey(unsigned char *tkey,unsigned char *dkey);
+extern void CSSdescramble(unsigned char *sector,unsigned char *tkey);
+
+extern unsigned char g_PlayerKeys[][6];
+extern int g_nPlayerKeys; \ No newline at end of file
diff --git a/src/decss/DeCSSInputPin.cpp b/src/decss/DeCSSInputPin.cpp
new file mode 100644
index 000000000..2d121bf4c
--- /dev/null
+++ b/src/decss/DeCSSInputPin.cpp
@@ -0,0 +1,350 @@
+/*
+ * Copyright (C) 2003-2006 Gabest
+ * http://www.gabest.org
+ *
+ * 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, 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 GNU Make; see the file COPYING. If not, write to
+ * the Free Software Foundation, 675 Mass Ave, Cambridge, MA 02139, USA.
+ * http://www.gnu.org/copyleft/gpl.html
+ *
+ */
+
+#include "stdafx.h"
+#include <atlbase.h>
+#include <streams.h>
+#include <dvdmedia.h>
+#include <ks.h>
+#include <ksmedia.h>
+#include "DeCSSInputPin.h"
+#include "..\DSUtil\DSUtil.h"
+#include "CSSauth.h"
+#include "CSSscramble.h"
+
+#include <initguid.h>
+#include "..\..\include\moreuuids.h"
+
+//
+// CDeCSSInputPin
+//
+
+CDeCSSInputPin::CDeCSSInputPin(TCHAR* pObjectName, CTransformFilter* pFilter, HRESULT* phr, LPWSTR pName)
+ : CTransformInputPin(pObjectName, pFilter, phr, pName)
+{
+ m_varient = -1;
+ memset(m_Challenge, 0, sizeof(m_Challenge));
+ memset(m_KeyCheck, 0, sizeof(m_KeyCheck));
+ memset(m_DiscKey, 0, sizeof(m_DiscKey));
+ memset(m_TitleKey, 0, sizeof(m_TitleKey));
+}
+
+STDMETHODIMP CDeCSSInputPin::NonDelegatingQueryInterface(REFIID riid, void** ppv)
+{
+ CheckPointer(ppv, E_POINTER);
+
+ return
+ QI(IKsPropertySet)
+ __super::NonDelegatingQueryInterface(riid, ppv);
+}
+
+// IMemInputPin
+
+STDMETHODIMP CDeCSSInputPin::Receive(IMediaSample* pSample)
+{
+ long len = pSample->GetActualDataLength();
+
+ BYTE* p = NULL;
+ if(SUCCEEDED(pSample->GetPointer(&p)) && len > 0)
+ {
+ BYTE* base = p;
+
+ if(m_mt.majortype == MEDIATYPE_DVD_ENCRYPTED_PACK && len == 2048 && (p[0x14]&0x30))
+ {
+ CSSdescramble(p, m_TitleKey);
+ p[0x14] &= ~0x30;
+
+ if(CComQIPtr<IMediaSample2> pMS2 = pSample)
+ {
+ AM_SAMPLE2_PROPERTIES props;
+ memset(&props, 0, sizeof(props));
+ if(SUCCEEDED(pMS2->GetProperties(sizeof(props), (BYTE*)&props))
+ && (props.dwTypeSpecificFlags & AM_UseNewCSSKey))
+ {
+ props.dwTypeSpecificFlags &= ~AM_UseNewCSSKey;
+ pMS2->SetProperties(sizeof(props), (BYTE*)&props);
+ }
+ }
+ }
+ }
+
+ HRESULT hr = Transform(pSample);
+
+ return hr == S_OK ? __super::Receive(pSample) :
+ hr == S_FALSE ? S_OK : hr;
+}
+
+void CDeCSSInputPin::StripPacket(BYTE*& p, long& len)
+{
+ GUID majortype = m_mt.majortype;
+
+ if(majortype == MEDIATYPE_MPEG2_PACK || majortype == MEDIATYPE_DVD_ENCRYPTED_PACK)
+ if(len > 0 && *(DWORD*)p == 0xba010000) // MEDIATYPE_*_PACK
+ {
+ len -= 14; p += 14;
+ if(int stuffing = (p[-1]&7)) {len -= stuffing; p += stuffing;}
+ majortype = MEDIATYPE_MPEG2_PES;
+ }
+
+ if(majortype == MEDIATYPE_MPEG2_PES)
+ if(len > 0 && *(DWORD*)p == 0xbb010000)
+ {
+ len -= 4; p += 4;
+ int hdrlen = ((p[0]<<8)|p[1]) + 2;
+ len -= hdrlen; p += hdrlen;
+ }
+
+ if(majortype == MEDIATYPE_MPEG2_PES)
+ if(len > 0
+ && ((*(DWORD*)p&0xf0ffffff) == 0xe0010000
+ || (*(DWORD*)p&0xe0ffffff) == 0xc0010000
+ || (*(DWORD*)p&0xbdffffff) == 0xbd010000)) // PES
+ {
+ bool ps1 = (*(DWORD*)p&0xbdffffff) == 0xbd010000;
+
+ len -= 4; p += 4;
+ int expected = ((p[0]<<8)|p[1]);
+ len -= 2; p += 2;
+ BYTE* p0 = p;
+
+ for(int i = 0; i < 16 && *p == 0xff; i++, len--, p++);
+
+ if((*p&0xc0) == 0x80) // mpeg2
+ {
+ len -= 2; p += 2;
+ len -= *p+1; p += *p+1;
+ }
+ else // mpeg1
+ {
+ if((*p&0xc0) == 0x40)
+ {
+ len -= 2; p += 2;
+ }
+
+ if((*p&0x30) == 0x30 || (*p&0x30) == 0x20)
+ {
+ bool pts = !!(*p&0x20), dts = !!(*p&0x10);
+ if(pts) len -= 5; p += 5;
+ if(dts) {ASSERT((*p&0xf0) == 0x10); len -= 5; p += 5;}
+ }
+ else
+ {
+ len--; p++;
+ }
+ }
+
+ if(ps1)
+ {
+ len--; p++;
+ if(m_mt.subtype == MEDIASUBTYPE_DVD_LPCM_AUDIO) {len -= 6; p += 6;}
+ else if(m_mt.subtype == MEDIASUBTYPE_DOLBY_AC3 || m_mt.subtype == MEDIASUBTYPE_WAVE_DOLBY_AC3
+ || m_mt.subtype == MEDIASUBTYPE_DTS || m_mt.subtype == MEDIASUBTYPE_WAVE_DTS) {len -= 3; p += 3;}
+ }
+
+ if(expected > 0)
+ {
+ expected -= (p - p0);
+ len = min(expected, len);
+ }
+ }
+
+ if(len < 0) {ASSERT(0); len = 0;}
+}
+
+// IKsPropertySet
+
+STDMETHODIMP CDeCSSInputPin::Set(REFGUID PropSet, ULONG Id, LPVOID pInstanceData, ULONG InstanceLength, LPVOID pPropertyData, ULONG DataLength)
+{
+ if(PropSet != AM_KSPROPSETID_CopyProt)
+ return E_NOTIMPL;
+
+ switch(Id)
+ {
+ case AM_PROPERTY_COPY_MACROVISION:
+ break;
+ case AM_PROPERTY_DVDCOPY_CHLG_KEY: // 3. auth: receive drive nonce word, also store and encrypt the buskey made up of the two nonce words
+ {
+ AM_DVDCOPY_CHLGKEY* pChlgKey = (AM_DVDCOPY_CHLGKEY*)pPropertyData;
+ for(int i = 0; i < 10; i++)
+ m_Challenge[i] = pChlgKey->ChlgKey[9-i];
+
+ CSSkey2(m_varient, m_Challenge, &m_Key[5]);
+
+ CSSbuskey(m_varient, m_Key, m_KeyCheck);
+ }
+ break;
+ case AM_PROPERTY_DVDCOPY_DISC_KEY: // 5. receive the disckey
+ {
+ AM_DVDCOPY_DISCKEY* pDiscKey = (AM_DVDCOPY_DISCKEY*)pPropertyData; // pDiscKey->DiscKey holds the disckey encrypted with itself and the 408 disckeys encrypted with the playerkeys
+
+ bool fSuccess = false;
+
+ for(int j = 0; j < g_nPlayerKeys; j++)
+ {
+ for(int k = 1; k < 409; k++)
+ {
+ BYTE DiscKey[6];
+ for(int i = 0; i < 5; i++)
+ DiscKey[i] = pDiscKey->DiscKey[k*5+i] ^ m_KeyCheck[4-i];
+ DiscKey[5] = 0;
+
+ CSSdisckey(DiscKey, g_PlayerKeys[j]);
+
+ BYTE Hash[6];
+ for(int i = 0; i < 5; i++)
+ Hash[i] = pDiscKey->DiscKey[i] ^ m_KeyCheck[4-i];
+ Hash[5] = 0;
+
+ CSSdisckey(Hash, DiscKey);
+
+ if(!memcmp(Hash, DiscKey, 6))
+ {
+ memcpy(m_DiscKey, DiscKey, 6);
+ j = g_nPlayerKeys;
+ fSuccess = true;
+ break;
+ }
+ }
+ }
+
+ if(!fSuccess)
+ return E_FAIL;
+ }
+ break;
+ case AM_PROPERTY_DVDCOPY_DVD_KEY1: // 2. auth: receive our drive-encrypted nonce word and decrypt it for verification
+ {
+ AM_DVDCOPY_BUSKEY* pKey1 = (AM_DVDCOPY_BUSKEY*)pPropertyData;
+ for(int i = 0; i < 5; i++)
+ m_Key[i] = pKey1->BusKey[4-i];
+
+ m_varient = -1;
+
+ for(int i = 31; i >= 0; i--)
+ {
+ CSSkey1(i, m_Challenge, m_KeyCheck);
+
+ if(memcmp(m_KeyCheck, &m_Key[0], 5) == 0)
+ m_varient = i;
+ }
+ }
+ break;
+ case AM_PROPERTY_DVDCOPY_REGION:
+ break;
+ case AM_PROPERTY_DVDCOPY_SET_COPY_STATE:
+ break;
+ case AM_PROPERTY_DVDCOPY_TITLE_KEY: // 6. receive the title key and decrypt it with the disc key
+ {
+ AM_DVDCOPY_TITLEKEY* pTitleKey = (AM_DVDCOPY_TITLEKEY*)pPropertyData;
+ for(int i = 0; i < 5; i++)
+ m_TitleKey[i] = pTitleKey->TitleKey[i] ^ m_KeyCheck[4-i];
+ m_TitleKey[5] = 0;
+ CSStitlekey(m_TitleKey, m_DiscKey);
+ }
+ break;
+ default:
+ return E_PROP_ID_UNSUPPORTED;
+ }
+
+ return S_OK;
+}
+
+STDMETHODIMP CDeCSSInputPin::Get(REFGUID PropSet, ULONG Id, LPVOID pInstanceData, ULONG InstanceLength, LPVOID pPropertyData, ULONG DataLength, ULONG* pBytesReturned)
+{
+ if(PropSet != AM_KSPROPSETID_CopyProt)
+ return E_NOTIMPL;
+
+ switch(Id)
+ {
+ case AM_PROPERTY_DVDCOPY_CHLG_KEY: // 1. auth: send our nonce word
+ {
+ AM_DVDCOPY_CHLGKEY* pChlgKey = (AM_DVDCOPY_CHLGKEY*)pPropertyData;
+ for(int i = 0; i < 10; i++)
+ pChlgKey->ChlgKey[i] = 9 - (m_Challenge[i] = i);
+ *pBytesReturned = sizeof(AM_DVDCOPY_CHLGKEY);
+ }
+ break;
+ case AM_PROPERTY_DVDCOPY_DEC_KEY2: // 4. auth: send back the encrypted drive nonce word to finish the authentication
+ {
+ AM_DVDCOPY_BUSKEY* pKey2 = (AM_DVDCOPY_BUSKEY*)pPropertyData;
+ for(int i = 0; i < 5; i++)
+ pKey2->BusKey[4-i] = m_Key[5+i];
+ *pBytesReturned = sizeof(AM_DVDCOPY_BUSKEY);
+ }
+ break;
+ case AM_PROPERTY_DVDCOPY_REGION:
+ {
+ DVD_REGION* pRegion = (DVD_REGION*)pPropertyData;
+ pRegion->RegionData = 0;
+ pRegion->SystemRegion = 0;
+ *pBytesReturned = sizeof(DVD_REGION);
+ }
+ break;
+ case AM_PROPERTY_DVDCOPY_SET_COPY_STATE:
+ {
+ AM_DVDCOPY_SET_COPY_STATE* pState = (AM_DVDCOPY_SET_COPY_STATE*)pPropertyData;
+ pState->DVDCopyState = AM_DVDCOPYSTATE_AUTHENTICATION_REQUIRED;
+ *pBytesReturned = sizeof(AM_DVDCOPY_SET_COPY_STATE);
+ }
+ break;
+ default:
+ return E_PROP_ID_UNSUPPORTED;
+ }
+
+ return S_OK;
+}
+
+STDMETHODIMP CDeCSSInputPin::QuerySupported(REFGUID PropSet, ULONG Id, ULONG* pTypeSupport)
+{
+ if(PropSet != AM_KSPROPSETID_CopyProt)
+ return E_NOTIMPL;
+
+ switch(Id)
+ {
+ case AM_PROPERTY_COPY_MACROVISION:
+ *pTypeSupport = KSPROPERTY_SUPPORT_SET;
+ break;
+ case AM_PROPERTY_DVDCOPY_CHLG_KEY:
+ *pTypeSupport = KSPROPERTY_SUPPORT_GET | KSPROPERTY_SUPPORT_SET;
+ break;
+ case AM_PROPERTY_DVDCOPY_DEC_KEY2:
+ *pTypeSupport = KSPROPERTY_SUPPORT_GET;
+ break;
+ case AM_PROPERTY_DVDCOPY_DISC_KEY:
+ *pTypeSupport = KSPROPERTY_SUPPORT_SET;
+ break;
+ case AM_PROPERTY_DVDCOPY_DVD_KEY1:
+ *pTypeSupport = KSPROPERTY_SUPPORT_SET;
+ break;
+ case AM_PROPERTY_DVDCOPY_REGION:
+ *pTypeSupport = KSPROPERTY_SUPPORT_GET | KSPROPERTY_SUPPORT_SET;
+ break;
+ case AM_PROPERTY_DVDCOPY_SET_COPY_STATE:
+ *pTypeSupport = KSPROPERTY_SUPPORT_GET | KSPROPERTY_SUPPORT_SET;
+ break;
+ case AM_PROPERTY_DVDCOPY_TITLE_KEY:
+ *pTypeSupport = KSPROPERTY_SUPPORT_SET;
+ break;
+ default:
+ return E_PROP_ID_UNSUPPORTED;
+ }
+
+ return S_OK;
+} \ No newline at end of file
diff --git a/src/decss/DeCSSInputPin.h b/src/decss/DeCSSInputPin.h
new file mode 100644
index 000000000..99058dde4
--- /dev/null
+++ b/src/decss/DeCSSInputPin.h
@@ -0,0 +1,50 @@
+/*
+ * Copyright (C) 2003-2006 Gabest
+ * http://www.gabest.org
+ *
+ * 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, 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 GNU Make; see the file COPYING. If not, write to
+ * the Free Software Foundation, 675 Mass Ave, Cambridge, MA 02139, USA.
+ * http://www.gnu.org/copyleft/gpl.html
+ *
+ */
+
+#pragma once
+
+class CDeCSSInputPin : public CTransformInputPin, public IKsPropertySet
+{
+ int m_varient;
+ BYTE m_Challenge[10], m_KeyCheck[5], m_Key[10];
+ BYTE m_DiscKey[6], m_TitleKey[6];
+
+protected:
+ // return S_FALSE here if you don't want the base class
+ // to call CTransformFilter::Receive with this sample
+ virtual HRESULT Transform(IMediaSample* pSample) {return S_OK;}
+
+public:
+ CDeCSSInputPin(TCHAR* pObjectName, CTransformFilter* pFilter, HRESULT* phr, LPWSTR pName);
+
+ DECLARE_IUNKNOWN
+ STDMETHODIMP NonDelegatingQueryInterface(REFIID riid, void** ppv);
+
+ void StripPacket(BYTE*& p, long& len);
+
+ // IMemInputPin
+ STDMETHODIMP Receive(IMediaSample* pSample);
+
+ // IKsPropertySet
+ STDMETHODIMP Set(REFGUID PropSet, ULONG Id, LPVOID InstanceData, ULONG InstanceLength, LPVOID PropertyData, ULONG DataLength);
+ STDMETHODIMP Get(REFGUID PropSet, ULONG Id, LPVOID InstanceData, ULONG InstanceLength, LPVOID PropertyData, ULONG DataLength, ULONG* pBytesReturned);
+ STDMETHODIMP QuerySupported(REFGUID PropSet, ULONG Id, ULONG* pTypeSupport);
+}; \ No newline at end of file
diff --git a/src/decss/VobDec.cpp b/src/decss/VobDec.cpp
new file mode 100644
index 000000000..dbf8e0a7f
--- /dev/null
+++ b/src/decss/VobDec.cpp
@@ -0,0 +1,184 @@
+#include "StdAfx.h"
+#include "vobdec.h"
+
+static BYTE reverse[0x100], table[0x100] =
+{
+ 0x33, 0x73, 0x3B, 0x26, 0x63, 0x23, 0x6B, 0x76, 0x3E, 0x7E, 0x36, 0x2B, 0x6E, 0x2E, 0x66, 0x7B,
+ 0xD3, 0x93, 0xDB, 0x06, 0x43, 0x03, 0x4B, 0x96, 0xDE, 0x9E, 0xD6, 0x0B, 0x4E, 0x0E, 0x46, 0x9B,
+ 0x57, 0x17, 0x5F, 0x82, 0xC7, 0x87, 0xCF, 0x12, 0x5A, 0x1A, 0x52, 0x8F, 0xCA, 0x8A, 0xC2, 0x1F,
+ 0xD9, 0x99, 0xD1, 0x00, 0x49, 0x09, 0x41, 0x90, 0xD8, 0x98, 0xD0, 0x01, 0x48, 0x08, 0x40, 0x91,
+ 0x3D, 0x7D, 0x35, 0x24, 0x6D, 0x2D, 0x65, 0x74, 0x3C, 0x7C, 0x34, 0x25, 0x6C, 0x2C, 0x64, 0x75,
+ 0xDD, 0x9D, 0xD5, 0x04, 0x4D, 0x0D, 0x45, 0x94, 0xDC, 0x9C, 0xD4, 0x05, 0x4C, 0x0C, 0x44, 0x95,
+ 0x59, 0x19, 0x51, 0x80, 0xC9, 0x89, 0xC1, 0x10, 0x58, 0x18, 0x50, 0x81, 0xC8, 0x88, 0xC0, 0x11,
+ 0xD7, 0x97, 0xDF, 0x02, 0x47, 0x07, 0x4F, 0x92, 0xDA, 0x9A, 0xD2, 0x0F, 0x4A, 0x0A, 0x42, 0x9F,
+ 0x53, 0x13, 0x5B, 0x86, 0xC3, 0x83, 0xCB, 0x16, 0x5E, 0x1E, 0x56, 0x8B, 0xCE, 0x8E, 0xC6, 0x1B,
+ 0xB3, 0xF3, 0xBB, 0xA6, 0xE3, 0xA3, 0xEB, 0xF6, 0xBE, 0xFE, 0xB6, 0xAB, 0xEE, 0xAE, 0xE6, 0xFB,
+ 0x37, 0x77, 0x3F, 0x22, 0x67, 0x27, 0x6F, 0x72, 0x3A, 0x7A, 0x32, 0x2F, 0x6A, 0x2A, 0x62, 0x7F,
+ 0xB9, 0xF9, 0xB1, 0xA0, 0xE9, 0xA9, 0xE1, 0xF0, 0xB8, 0xF8, 0xB0, 0xA1, 0xE8, 0xA8, 0xE0, 0xF1,
+ 0x5D, 0x1D, 0x55, 0x84, 0xCD, 0x8D, 0xC5, 0x14, 0x5C, 0x1C, 0x54, 0x85, 0xCC, 0x8C, 0xC4, 0x15,
+ 0xBD, 0xFD, 0xB5, 0xA4, 0xED, 0xAD, 0xE5, 0xF4, 0xBC, 0xFC, 0xB4, 0xA5, 0xEC, 0xAC, 0xE4, 0xF5,
+ 0x39, 0x79, 0x31, 0x20, 0x69, 0x29, 0x61, 0x70, 0x38, 0x78, 0x30, 0x21, 0x68, 0x28, 0x60, 0x71,
+ 0xB7, 0xF7, 0xBF, 0xA2, 0xE7, 0xA7, 0xEF, 0xF2, 0xBA, 0xFA, 0xB2, 0xAF, 0xEA, 0xAA, 0xE2, 0xFF,
+};
+
+CVobDec::CVobDec()
+{
+ m_fFoundKey = false;
+
+ for(DWORD loop0 = 0; loop0 < 0x100; loop0++)
+ {
+ BYTE value = 0;
+
+ for(DWORD loop1 = 0; loop1 < 8; loop1++)
+ {
+ value |= ((loop0 >> loop1) & 1) << (7 - loop1);
+ }
+
+ reverse[loop0] = value;
+ }
+
+}
+
+CVobDec::~CVobDec()
+{
+}
+
+void CVobDec::ClockLfsr0Forward(int &lfsr0)
+{
+ int temp = (lfsr0 << 3) | (lfsr0 >> 14);
+ lfsr0 = (lfsr0 >> 8) | ((((((temp << 3) ^ temp) << 3) ^ temp ^ lfsr0) & 0xFF) << 9);
+}
+
+void CVobDec::ClockLfsr1Forward(int &lfsr1)
+{
+ lfsr1 = (lfsr1 >> 8) | ((((((((lfsr1 >> 8) ^ lfsr1) >> 1) ^ lfsr1) >> 3) ^ lfsr1) & 0xFF) << 17);
+}
+
+void CVobDec::ClockBackward(int &lfsr0, int &lfsr1)
+{
+ int temp0, temp1;
+
+ lfsr0 = ((lfsr0 << 8) ^ ((((lfsr0 >> 3) ^ lfsr0) >> 6) & 0xFF)) & ((1 << 17) - 1);
+ temp0 = ((lfsr1 >> 17) ^ (lfsr1 >> 4)) & 0xFF;
+ temp1 = (lfsr1 << 5) | (temp0 >> 3);
+ temp1 = ((temp1 >> 1) ^ temp1) & 0xFF;
+ lfsr1 = ((lfsr1 << 8) | ((((((temp1 >> 2) ^ temp1) >> 1) ^ temp1) >> 3) ^ temp1 ^ temp0)) & ((1 << 25) - 1);
+}
+
+void CVobDec::Salt(const BYTE salt[5], int &lfsr0, int &lfsr1)
+{
+ lfsr0 ^= (reverse[salt[0]] << 9) | reverse[salt[1]];
+ lfsr1 ^= ((reverse[salt[2]] & 0xE0) << 17) | ((reverse[salt[2]] & 0x1F) << 16) | (reverse[salt[3]] << 8) | reverse[salt[4]];
+}
+
+int CVobDec::FindLfsr(const BYTE *crypt, int offset, const BYTE *plain)
+{
+ int loop0, loop1, lfsr0, lfsr1, carry, count;
+
+ for(loop0 = count = 0; loop0 != (1 << 18); loop0++)
+ {
+ lfsr0 = loop0 >> 1;
+ carry = loop0 & 0x01;
+
+ for(loop1 = lfsr1 = 0; loop1 != 4; loop1++)
+ {
+ ClockLfsr0Forward(lfsr0);
+ carry = (table[crypt[offset + loop1]] ^ plain[loop1]) - ((lfsr0 >> 9) ^ 0xFF) - carry;
+ lfsr1 = (lfsr1 >> 8) | ((carry & 0xFF) << 17);
+ carry = (carry >> 8) & 0x01;
+ }
+ for( ; loop1 != 7; loop1++)
+ {
+ ClockLfsr0Forward(lfsr0);
+ ClockLfsr1Forward(lfsr1);
+ carry += ((lfsr0 >> 9) ^ 0xFF) + (lfsr1 >> 17);
+ if((carry & 0xFF) != (table[crypt[offset + loop1]] ^ plain[loop1]))
+ {
+ break;
+ }
+ carry >>= 8;
+ }
+ if(loop1 == 7)
+ {
+ for(loop1 = 0; loop1 != 6; loop1++)
+ {
+ ClockBackward(lfsr0, lfsr1);
+ }
+ carry = ((lfsr0 >> 9) ^ 0xFF) + (lfsr1 >> 17) + (loop0 & 0x01);
+ if((carry & 0xFF) == (table[crypt[offset]] ^ plain[0]))
+ {
+ for(loop1 = 0; loop1 != offset + 1; loop1++)
+ {
+ ClockBackward(lfsr0, lfsr1);
+ }
+ if(lfsr0 & 0x100 && lfsr1 & 0x200000)
+ {
+ m_lfsr0 = lfsr0;
+ m_lfsr1 = lfsr1;
+ count++;
+ }
+ }
+ }
+ }
+
+ return count;
+}
+
+bool CVobDec::FindKey(BYTE* buff)
+{
+ BYTE plain[7] = {0x00, 0x00, 0x01, 0xBE, 0x00, 0x00, 0xFF};
+ int offset, left, flag = 0, block = 0, count, maxblock = 20000;
+
+ m_fFoundKey = false;
+
+ if(buff[0x14] & 0x30)
+ {
+ flag |= 0x01;
+
+ if(*(DWORD*)&buff[0x00] == 0xba010000 && (*(DWORD*)&buff[0x0e] & 0xffffff) == 0x010000)
+ {
+ offset = 0x14 + (buff[0x12] << 8) + buff[0x13];
+ if(0x80 <= offset && offset <= 0x7F9)
+ {
+ flag |= 0x02;
+ left = 0x800 - offset - 6;
+ plain[4] = (char)(left >> 8);
+ plain[5] = (char)left;
+ if((count = FindLfsr(buff + 0x80, offset - 0x80, plain)) == 1)
+ {
+ Salt(buff + 0x54, m_lfsr0, m_lfsr1);
+ m_fFoundKey = true;
+ }
+ else if(count)
+ {
+// printf(_T("\rblock %d reported %d possible keys, skipping\n"), block, count);
+ }
+ }
+ }
+ }
+
+ return(m_fFoundKey);
+}
+
+void CVobDec::Decrypt(BYTE* buff)
+{
+ if(buff[0x14] & 0x30)
+ {
+ buff[0x14] &= ~0x30;
+
+ int lfsr0 = m_lfsr0, lfsr1 = m_lfsr1;
+
+ Salt(buff + 0x54, lfsr0, lfsr1);
+
+ buff += 0x80;
+
+ for(int loop0 = 0, carry = 0; loop0 != 0x800 - 0x80; loop0++, buff++)
+ {
+ ClockLfsr0Forward(lfsr0);
+ ClockLfsr1Forward(lfsr1);
+ carry += ((lfsr0 >> 9) ^ 0xFF) + (lfsr1 >> 17);
+ *buff = BYTE(table[*buff] ^ carry);
+ carry >>= 8;
+ }
+ }
+}
diff --git a/src/decss/VobDec.h b/src/decss/VobDec.h
new file mode 100644
index 000000000..9b3e5cef8
--- /dev/null
+++ b/src/decss/VobDec.h
@@ -0,0 +1,21 @@
+#pragma once
+
+class CVobDec
+{
+ int m_lfsr0, m_lfsr1;
+
+ void ClockLfsr0Forward(int& lfsr0);
+ void ClockLfsr1Forward(int& lfsr1);
+ void ClockBackward(int& lfsr0, int& lfsr1);
+ void Salt(const BYTE salt[5], int& lfsr0, int& lfsr1);
+ int FindLfsr(const BYTE* crypt, int offset, const BYTE* plain);
+
+public:
+ CVobDec();
+ virtual ~CVobDec();
+
+ bool m_fFoundKey;
+
+ bool FindKey(BYTE* buff);
+ void Decrypt(BYTE* buff);
+};
diff --git a/src/decss/VobFile.cpp b/src/decss/VobFile.cpp
new file mode 100644
index 000000000..9215c0c48
--- /dev/null
+++ b/src/decss/VobFile.cpp
@@ -0,0 +1,639 @@
+#include "StdAfx.h"
+#include <io.h>
+#include "VobFile.h"
+#include "CSSauth.h"
+#include "CSSscramble.h"
+#include "udf.h"
+
+//
+// CDVDSession
+//
+
+CDVDSession::CDVDSession()
+ : m_session(DVD_END_ALL_SESSIONS)
+ , m_hDrive(INVALID_HANDLE_VALUE)
+{
+}
+
+CDVDSession::~CDVDSession()
+{
+ EndSession();
+}
+
+bool CDVDSession::Open(LPCTSTR path)
+{
+ Close();
+
+ CString fn = path;
+ CString drive = _T("\\\\.\\") + fn.Left(fn.Find(':')+1);
+
+ m_hDrive = CreateFile(drive, GENERIC_READ, FILE_SHARE_READ, NULL,
+ OPEN_EXISTING, FILE_ATTRIBUTE_READONLY|FILE_FLAG_SEQUENTIAL_SCAN, (HANDLE)NULL);
+ if(m_hDrive == INVALID_HANDLE_VALUE)
+ return(false);
+
+ return(true);
+}
+
+void CDVDSession::Close()
+{
+ if(m_hDrive != INVALID_HANDLE_VALUE)
+ {
+ CloseHandle(m_hDrive);
+ m_hDrive = INVALID_HANDLE_VALUE;
+ }
+}
+
+bool CDVDSession::BeginSession()
+{
+ EndSession();
+
+ if(m_hDrive == INVALID_HANDLE_VALUE)
+ return(false);
+
+ DWORD BytesReturned;
+ if(!DeviceIoControl(m_hDrive, IOCTL_DVD_START_SESSION, NULL, 0, &m_session, sizeof(m_session), &BytesReturned, NULL))
+ {
+ m_session = DVD_END_ALL_SESSIONS;
+ if(!DeviceIoControl(m_hDrive, IOCTL_DVD_END_SESSION, &m_session, sizeof(m_session), NULL, 0, &BytesReturned, NULL)
+ || !DeviceIoControl(m_hDrive, IOCTL_DVD_START_SESSION, NULL, 0, &m_session, sizeof(m_session), &BytesReturned, NULL))
+ {
+ CloseHandle(m_hDrive);
+ DWORD err = GetLastError();
+ return(false);
+ }
+ }
+
+ return(true);
+}
+
+void CDVDSession::EndSession()
+{
+ if(m_session != DVD_END_ALL_SESSIONS)
+ {
+ DWORD BytesReturned;
+ DeviceIoControl(m_hDrive, IOCTL_DVD_END_SESSION, &m_session, sizeof(m_session), NULL, 0, &BytesReturned, NULL);
+ m_session = DVD_END_ALL_SESSIONS;
+ }
+}
+
+bool CDVDSession::Authenticate()
+{
+ if(m_session == DVD_END_ALL_SESSIONS)
+ return(false);
+
+ BYTE Challenge[10], Key[10];
+
+ for(int i = 0; i < 10; i++) Challenge[i] = i;
+
+ if(!SendKey(DvdChallengeKey, Challenge))
+ return(false);
+
+ if(!ReadKey(DvdBusKey1, Key))
+ return(false);
+
+ int varient = -1;
+
+ for(int i = 31; i >= 0; i--)
+ {
+ BYTE KeyCheck[5];
+ CSSkey1(i, Challenge, KeyCheck);
+ if(!memcmp(KeyCheck, Key, 5))
+ varient = i;
+ }
+
+ if(!ReadKey(DvdChallengeKey, Challenge))
+ return(false);
+
+ CSSkey2(varient, Challenge, &Key[5]);
+
+ if(!SendKey(DvdBusKey2, &Key[5]))
+ return(false);
+
+ CSSbuskey(varient, Key, m_SessionKey);
+
+ return(true);
+}
+
+bool CDVDSession::GetDiscKey()
+{
+ if(m_session == DVD_END_ALL_SESSIONS)
+ return(false);
+
+ BYTE DiscKeys[2048];
+ if(!ReadKey(DvdDiskKey, DiscKeys))
+ return(false);
+
+ for(int i = 0; i < g_nPlayerKeys; i++)
+ {
+ for(int j = 1; j < 409; j++)
+ {
+ BYTE DiscKey[6];
+ memcpy(DiscKey, &DiscKeys[j*5], 5);
+ DiscKey[5] = 0;
+
+ CSSdisckey(DiscKey, g_PlayerKeys[i]);
+
+ BYTE Hash[6];
+ memcpy(Hash, &DiscKeys[0], 5);
+ Hash[5] = 0;
+
+ CSSdisckey(Hash, DiscKey);
+
+ if(!memcmp(Hash, DiscKey, 6))
+ {
+ memcpy(m_DiscKey, DiscKey, 6);
+ return(true);
+ }
+ }
+ }
+
+ return(false);
+}
+
+bool CDVDSession::GetTitleKey(int lba, BYTE* pKey)
+{
+ if(m_session == DVD_END_ALL_SESSIONS)
+ return(false);
+
+ if(!ReadKey(DvdTitleKey, pKey, lba))
+ return(false);
+
+ if(!(pKey[0]|pKey[1]|pKey[2]|pKey[3]|pKey[4]))
+ return(false);
+
+ pKey[5] = 0;
+
+ CSStitlekey(pKey, m_DiscKey);
+
+ return(true);
+}
+
+static void Reverse(BYTE* d, BYTE* s, int len)
+{
+ if(d == s)
+ {
+ for(s += len-1; d < s; d++, s--)
+ *d ^= *s, *s ^= *d, *d ^= *s;
+ }
+ else
+ {
+ for(int i = 0; i < len; i++)
+ d[i] = s[len-1 - i];
+ }
+}
+
+bool CDVDSession::SendKey(DVD_KEY_TYPE KeyType, BYTE* pKeyData)
+{
+ CAutoPtr<DVD_COPY_PROTECT_KEY> key;
+
+ switch(KeyType)
+ {
+ case DvdChallengeKey:
+ key.Attach((DVD_COPY_PROTECT_KEY*)new BYTE[DVD_CHALLENGE_KEY_LENGTH]);
+ key->KeyLength = DVD_CHALLENGE_KEY_LENGTH;
+ Reverse(key->KeyData, pKeyData, 10);
+ break;
+ case DvdBusKey2:
+ key.Attach((DVD_COPY_PROTECT_KEY*)new BYTE[DVD_BUS_KEY_LENGTH]);
+ key->KeyLength = DVD_BUS_KEY_LENGTH;
+ Reverse(key->KeyData, pKeyData, 5);
+ break;
+ default:
+ break;
+ }
+
+ if(!key)
+ return(false);
+
+ key->SessionId = m_session;
+ key->KeyType = KeyType;
+ key->KeyFlags = 0;
+
+ DWORD BytesReturned;
+ return(!!DeviceIoControl(m_hDrive, IOCTL_DVD_SEND_KEY, key, key->KeyLength, NULL, 0, &BytesReturned, NULL));
+}
+
+bool CDVDSession::ReadKey(DVD_KEY_TYPE KeyType, BYTE* pKeyData, int lba)
+{
+ CAutoPtr<DVD_COPY_PROTECT_KEY> key;
+
+ switch(KeyType)
+ {
+ case DvdChallengeKey:
+ key.Attach((DVD_COPY_PROTECT_KEY*)new BYTE[DVD_CHALLENGE_KEY_LENGTH]);
+ key->KeyLength = DVD_CHALLENGE_KEY_LENGTH;
+ key->Parameters.TitleOffset.QuadPart = 0;
+ break;
+ case DvdBusKey1:
+ key.Attach((DVD_COPY_PROTECT_KEY*)new BYTE[DVD_BUS_KEY_LENGTH]);
+ key->KeyLength = DVD_BUS_KEY_LENGTH;
+ key->Parameters.TitleOffset.QuadPart = 0;
+ break;
+ case DvdDiskKey:
+ key.Attach((DVD_COPY_PROTECT_KEY*)new BYTE[DVD_DISK_KEY_LENGTH]);
+ key->KeyLength = DVD_DISK_KEY_LENGTH;
+ key->Parameters.TitleOffset.QuadPart = 0;
+ break;
+ case DvdTitleKey:
+ key.Attach((DVD_COPY_PROTECT_KEY*)new BYTE[DVD_TITLE_KEY_LENGTH]);
+ key->KeyLength = DVD_TITLE_KEY_LENGTH;
+ key->Parameters.TitleOffset.QuadPart = 2048i64*lba;
+ break;
+ default:
+ break;
+ }
+
+ if(!key)
+ return(false);
+
+ key->SessionId = m_session;
+ key->KeyType = KeyType;
+ key->KeyFlags = 0;
+
+ DWORD BytesReturned;
+ if(!DeviceIoControl(m_hDrive, IOCTL_DVD_READ_KEY, key, key->KeyLength, key, key->KeyLength, &BytesReturned, NULL))
+ {
+ DWORD err = GetLastError();
+ return(false);
+ }
+
+ switch(KeyType)
+ {
+ case DvdChallengeKey:
+ Reverse(pKeyData, key->KeyData, 10);
+ break;
+ case DvdBusKey1:
+ Reverse(pKeyData, key->KeyData, 5);
+ break;
+ case DvdDiskKey:
+ memcpy(pKeyData, key->KeyData, 2048);
+ for(int i = 0; i < 2048/5; i++)
+ pKeyData[i] ^= m_SessionKey[4-(i%5)];
+ break;
+ case DvdTitleKey:
+ memcpy(pKeyData, key->KeyData, 5);
+ for(int i = 0; i < 5; i++)
+ pKeyData[i] ^= m_SessionKey[4-(i%5)];
+ break;
+ default:
+ break;
+ }
+
+ return(true);
+}
+
+//
+// CLBAFile
+//
+
+CLBAFile::CLBAFile()
+{
+}
+
+CLBAFile::~CLBAFile()
+{
+}
+
+bool CLBAFile::IsOpen()
+{
+ return(m_hFile != hFileNull);
+}
+
+bool CLBAFile::Open(LPCTSTR path)
+{
+ Close();
+
+ return(!!CFile::Open(path, modeRead|typeBinary|shareDenyWrite|osSequentialScan));
+}
+
+void CLBAFile::Close()
+{
+ if(m_hFile != hFileNull)
+ CFile::Close();
+}
+
+int CLBAFile::GetLength()
+{
+ return (int)(CFile::GetLength()/2048);
+}
+
+int CLBAFile::GetPosition()
+{
+ return (int)(CFile::GetPosition()/2048);
+}
+
+int CLBAFile::Seek(int lba)
+{
+ return (int)(CFile::Seek(2048i64*lba, CFile::begin)/2048);
+}
+
+bool CLBAFile::Read(BYTE* buff)
+{
+ return CFile::Read(buff, 2048) == 2048;
+}
+
+//
+// CVobFile
+//
+
+CVobFile::CVobFile()
+{
+ Close();
+}
+
+CVobFile::~CVobFile()
+{
+}
+
+bool CVobFile::IsDVD()
+{
+ return m_fDVD;
+}
+
+bool CVobFile::HasDiscKey(BYTE* key)
+{
+ if(key) memcpy(key, m_DiscKey, 5);
+ return m_fHasDiscKey;
+}
+
+bool CVobFile::HasTitleKey(BYTE* key)
+{
+ if(key) memcpy(key, m_TitleKey, 5);
+ return m_fHasTitleKey;
+}
+
+bool CVobFile::Open(CString fn, CAtlList<CString>& vobs)
+{
+ CFile f;
+ if(!f.Open(fn, CFile::modeRead|CFile::typeBinary|CFile::shareDenyWrite))
+ return(false);
+
+ char hdr[13];
+ f.Read(hdr, 12);
+ hdr[12] = 0;
+ if(strcmp(hdr, "DVDVIDEO-VTS"))
+ return(false);
+
+ f.Close();
+
+ int offset = -1;
+
+ vobs.RemoveAll();
+
+ fn = fn.Left(fn.ReverseFind('.')+1);
+ fn.TrimRight(_T(".0123456789"));
+ for(int i = 0; i < 100; i++)
+ {
+ CString vob;
+ vob.Format(_T("%s%d.vob"), fn, i);
+
+ CFileStatus status;
+ if(!CFile::GetStatus(vob, status))
+ {
+ if(i == 0) continue;
+ else break;
+ }
+
+ if(status.m_size&0x7ff)
+ {
+ vobs.RemoveAll();
+ break;
+ }
+
+ if(status.m_size > 0)
+ vobs.AddTail(vob);
+
+ if(i == 0)
+ offset = (int)(status.m_size/0x800);
+ }
+
+ return Open(vobs, offset);
+}
+
+bool CVobFile::Open(CAtlList<CString>& vobs, int offset)
+{
+ Close();
+
+ if(vobs.GetCount() == 0)
+ return(false);
+
+ if(vobs.GetCount() == 1)
+ offset = -1;
+
+ m_offset = offset;
+
+ POSITION pos = vobs.GetHeadPosition();
+ while(pos)
+ {
+ CString fn = vobs.GetNext(pos);
+
+ WIN32_FIND_DATA fd;
+ HANDLE h = FindFirstFile(fn, &fd);
+ if(h == INVALID_HANDLE_VALUE)
+ {
+ m_files.RemoveAll();
+ return(false);
+ }
+ FindClose(h);
+
+ file_t f;
+ f.fn = fn;
+ f.size = (int)(((__int64(fd.nFileSizeHigh)<<32)|fd.nFileSizeLow)/2048);
+ m_files.Add(f);
+
+ m_size += f.size;
+ }
+
+ if(m_files.GetCount() > 0 && CDVDSession::Open(m_files[0].fn))
+ {
+ for(int i = 0; !m_fHasTitleKey && i < m_files.GetCount(); i++)
+ {
+ if(BeginSession())
+ {
+ m_fDVD = true;
+ Authenticate();
+ m_fHasDiscKey = GetDiscKey();
+ EndSession();
+ }
+ else
+ {
+ CString fn = m_files[0].fn;
+ fn.MakeLower();
+
+ if(fn.Find(_T(":\\video_ts")) == 1 && GetDriveType(fn.Left(3)) == DRIVE_CDROM)
+ {
+ m_fDVD = true;
+ }
+
+ break;
+ }
+
+ if(tp_udf_file f = udf_find_file(m_hDrive, 0, CStringA(m_files[i].fn.Mid(m_files[i].fn.Find(':')+1))))
+ {
+ DWORD start, end;
+ if(udf_get_lba(m_hDrive, f, &start, &end))
+ {
+ if(BeginSession())
+ {
+ Authenticate();
+ m_fHasTitleKey = GetTitleKey(start + f->partition_lba, m_TitleKey);
+ EndSession();
+ }
+ }
+
+ udf_free(f);
+ }
+
+ BYTE key[5];
+ if(HasTitleKey(key) && i == 0 && offset >= 0)
+ {
+ i++;
+
+ if(BeginSession())
+ {
+ m_fDVD = true;
+ Authenticate();
+ m_fHasDiscKey = GetDiscKey();
+ EndSession();
+ }
+ else
+ {
+ break;
+ }
+
+ if(tp_udf_file f = udf_find_file(m_hDrive, 0, CStringA(m_files[i].fn.Mid(m_files[i].fn.Find(':')+1))))
+ {
+ DWORD start, end;
+ if(udf_get_lba(m_hDrive, f, &start, &end))
+ {
+ if(BeginSession())
+ {
+ Authenticate();
+ m_fHasTitleKey = GetTitleKey(start + f->partition_lba, m_TitleKey);
+ EndSession();
+ }
+ }
+
+ udf_free(f);
+ }
+
+ if(!m_fHasTitleKey)
+ {
+ memcpy(m_TitleKey, key, 5);
+ m_fHasTitleKey = true;
+ }
+ }
+ }
+ }
+/*
+ if(m_files.GetCount() > 0 && !m_fDVD)
+ {
+ CString fn = m_files[0].fn;
+ fn.MakeLower();
+
+ if(fn.Find(_T(":\\video_ts")) == 1 && GetDriveType(fn.Left(3)) == DRIVE_CDROM)
+ {
+ m_fDVD = true;
+ }
+ }
+*/
+ m_offset = max(offset, 0);
+
+ return(true);
+}
+
+void CVobFile::Close()
+{
+ CDVDSession::Close();
+ m_files.RemoveAll();
+ m_iFile = -1;
+ m_pos = m_size = m_offset = 0;
+ m_file.Close();
+ m_fDVD = m_fHasDiscKey = m_fHasTitleKey = false;
+}
+
+int CVobFile::GetLength()
+{
+ return(m_size - m_offset);
+}
+
+int CVobFile::GetPosition()
+{
+ return(m_pos - m_offset);
+}
+
+int CVobFile::Seek(int pos)
+{
+ pos = min(max(pos+m_offset, m_offset), m_size-1);
+
+ int i = -1;
+ int size = 0;
+
+ // this suxx, but won't take long
+ do size += m_files[++i].size;
+ while(i < m_files.GetCount() && pos >= size);
+
+ if(i != m_iFile && i < m_files.GetCount())
+ {
+ if(!m_file.Open(m_files[i].fn))
+ return(m_pos);
+
+ m_iFile = i;
+ }
+
+ m_pos = pos;
+
+ pos -= (size - m_files[i].size);
+ m_file.Seek(pos);
+
+ return(GetPosition());
+}
+
+bool CVobFile::Read(BYTE* buff)
+{
+ if(m_pos >= m_size) return(false);
+
+ if(m_file.IsOpen() && m_file.GetPosition() == m_file.GetLength())
+ {
+ m_file.Close();
+ }
+
+ if(!m_file.IsOpen())
+ {
+ if(m_iFile >= m_files.GetCount()-1)
+ {
+ return(false);
+ }
+
+ if(!m_file.Open(m_files[++m_iFile].fn))
+ {
+ m_iFile = -1;
+ return(false);
+ }
+ }
+
+ if(!m_file.Read(buff))
+ {
+ // dvd still locked?
+ return(false);
+ }
+
+ m_pos++;
+
+ if(buff[0x14] & 0x30)
+ {
+ if(m_fHasTitleKey)
+ {
+ CSSdescramble(buff, m_TitleKey);
+ buff[0x14] &= ~0x30;
+ }
+ else
+ {
+ // under win9x this is normal, but I'm not developing under win9x :P
+ ASSERT(0);
+ }
+ }
+
+ return(true);
+}
diff --git a/src/decss/VobFile.h b/src/decss/VobFile.h
new file mode 100644
index 000000000..4be1dbcb7
--- /dev/null
+++ b/src/decss/VobFile.h
@@ -0,0 +1,87 @@
+#pragma once
+
+#pragma warning(disable : 4200)
+
+#include <atlbase.h>
+#include <atlcoll.h>
+//#include <winioctl.h> // platform sdk
+#include "..\..\include\winddk\ntddcdvd.h"
+
+class CDVDSession
+{
+protected:
+ HANDLE m_hDrive;
+
+ DVD_SESSION_ID m_session;
+ bool BeginSession();
+ void EndSession();
+
+ BYTE m_SessionKey[5];
+ bool Authenticate();
+
+ BYTE m_DiscKey[6], m_TitleKey[6];
+ bool GetDiscKey();
+ bool GetTitleKey(int lba, BYTE* pKey);
+
+public:
+ CDVDSession();
+ virtual ~CDVDSession();
+
+ bool Open(LPCTSTR path);
+ void Close();
+
+ operator HANDLE() {return m_hDrive;}
+ operator DVD_SESSION_ID() {return m_session;}
+
+ bool SendKey(DVD_KEY_TYPE KeyType, BYTE* pKeyData);
+ bool ReadKey(DVD_KEY_TYPE KeyType, BYTE* pKeyData, int lba = 0);
+};
+
+class CLBAFile : private CFile
+{
+public:
+ CLBAFile();
+ virtual ~CLBAFile();
+
+ bool IsOpen();
+
+ bool Open(LPCTSTR path);
+ void Close();
+
+ int GetLength();
+ int GetPosition();
+ int Seek(int lba);
+ bool Read(BYTE* buff);
+};
+
+class CVobFile : public CDVDSession
+{
+ // all files
+ typedef struct {CString fn; int size;} file_t;
+ CAtlArray<file_t> m_files;
+ int m_iFile;
+ int m_pos, m_size, m_offset;
+
+ // currently opened file
+ CLBAFile m_file;
+
+ // attribs
+ bool m_fDVD, m_fHasDiscKey, m_fHasTitleKey;
+
+public:
+ CVobFile();
+ virtual ~CVobFile();
+
+ bool IsDVD();
+ bool HasDiscKey(BYTE* key);
+ bool HasTitleKey(BYTE* key);
+
+ bool Open(CString fn, CAtlList<CString>& files /* out */); // vts ifo
+ bool Open(CAtlList<CString>& files, int offset = -1); // vts vobs, video vob offset in lba
+ void Close();
+
+ int GetLength();
+ int GetPosition();
+ int Seek(int pos);
+ bool Read(BYTE* buff);
+};
diff --git a/src/decss/decss.h b/src/decss/decss.h
new file mode 100644
index 000000000..93fd76c45
--- /dev/null
+++ b/src/decss/decss.h
@@ -0,0 +1,5 @@
+#pragma once
+
+#include "CSSauth.h"
+#include "CSSscramble.h"
+#include "DVDSession.h" \ No newline at end of file
diff --git a/src/decss/decss.sln b/src/decss/decss.sln
new file mode 100644
index 000000000..fcd6c1181
--- /dev/null
+++ b/src/decss/decss.sln
@@ -0,0 +1,27 @@
+Microsoft Visual Studio Solution File, Format Version 8.00
+Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "decss", "decss.vcproj", "{1A2DFD1A-3C6C-44D1-909D-294AF646B575}"
+ ProjectSection(ProjectDependencies) = postProject
+ EndProjectSection
+EndProject
+Global
+ GlobalSection(SolutionConfiguration) = preSolution
+ Debug = Debug
+ Debug Unicode = Debug Unicode
+ Release = Release
+ Release Unicode = Release Unicode
+ EndGlobalSection
+ GlobalSection(ProjectConfiguration) = postSolution
+ {1A2DFD1A-3C6C-44D1-909D-294AF646B575}.Debug.ActiveCfg = Debug|Win32
+ {1A2DFD1A-3C6C-44D1-909D-294AF646B575}.Debug.Build.0 = Debug|Win32
+ {1A2DFD1A-3C6C-44D1-909D-294AF646B575}.Debug Unicode.ActiveCfg = Debug Unicode|Win32
+ {1A2DFD1A-3C6C-44D1-909D-294AF646B575}.Debug Unicode.Build.0 = Debug Unicode|Win32
+ {1A2DFD1A-3C6C-44D1-909D-294AF646B575}.Release.ActiveCfg = Release|Win32
+ {1A2DFD1A-3C6C-44D1-909D-294AF646B575}.Release.Build.0 = Release|Win32
+ {1A2DFD1A-3C6C-44D1-909D-294AF646B575}.Release Unicode.ActiveCfg = Release Unicode|Win32
+ {1A2DFD1A-3C6C-44D1-909D-294AF646B575}.Release Unicode.Build.0 = Release Unicode|Win32
+ EndGlobalSection
+ GlobalSection(ExtensibilityGlobals) = postSolution
+ EndGlobalSection
+ GlobalSection(ExtensibilityAddIns) = postSolution
+ EndGlobalSection
+EndGlobal
diff --git a/src/decss/decss.vcproj b/src/decss/decss.vcproj
new file mode 100644
index 000000000..4effa274f
--- /dev/null
+++ b/src/decss/decss.vcproj
@@ -0,0 +1,284 @@
+<?xml version="1.0" encoding="Windows-1252"?>
+<VisualStudioProject
+ ProjectType="Visual C++"
+ Version="7.10"
+ Name="decss"
+ ProjectGUID="{1A2DFD1A-3C6C-44D1-909D-294AF646B575}"
+ SccProjectName=""
+ SccAuxPath=""
+ SccLocalPath=""
+ SccProvider=""
+ Keyword="Win32Proj">
+ <Platforms>
+ <Platform
+ Name="Win32"/>
+ </Platforms>
+ <Configurations>
+ <Configuration
+ Name="Debug|Win32"
+ OutputDirectory="Debug"
+ IntermediateDirectory="Debug"
+ ConfigurationType="4"
+ UseOfMFC="2"
+ CharacterSet="2">
+ <Tool
+ Name="VCCLCompilerTool"
+ Optimization="0"
+ PreprocessorDefinitions="WIN32;_DEBUG;_LIB"
+ MinimalRebuild="TRUE"
+ BasicRuntimeChecks="3"
+ RuntimeLibrary="3"
+ UsePrecompiledHeader="3"
+ WarningLevel="3"
+ Detect64BitPortabilityProblems="FALSE"
+ DebugInformationFormat="4"/>
+ <Tool
+ Name="VCCustomBuildTool"/>
+ <Tool
+ Name="VCLibrarianTool"
+ OutputFile="../../lib/$(ProjectName)D.lib"/>
+ <Tool
+ Name="VCMIDLTool"/>
+ <Tool
+ Name="VCPostBuildEventTool"/>
+ <Tool
+ Name="VCPreBuildEventTool"/>
+ <Tool
+ Name="VCPreLinkEventTool"/>
+ <Tool
+ Name="VCResourceCompilerTool"/>
+ <Tool
+ Name="VCWebServiceProxyGeneratorTool"/>
+ <Tool
+ Name="VCXMLDataGeneratorTool"/>
+ <Tool
+ Name="VCManagedWrapperGeneratorTool"/>
+ <Tool
+ Name="VCAuxiliaryManagedWrapperGeneratorTool"/>
+ </Configuration>
+ <Configuration
+ Name="Release|Win32"
+ OutputDirectory="Release"
+ IntermediateDirectory="Release"
+ ConfigurationType="4"
+ UseOfMFC="1"
+ CharacterSet="2">
+ <Tool
+ Name="VCCLCompilerTool"
+ Optimization="2"
+ InlineFunctionExpansion="1"
+ OmitFramePointers="TRUE"
+ PreprocessorDefinitions="WIN32;NDEBUG;_LIB"
+ StringPooling="TRUE"
+ RuntimeLibrary="0"
+ EnableFunctionLevelLinking="TRUE"
+ UsePrecompiledHeader="3"
+ WarningLevel="3"
+ Detect64BitPortabilityProblems="FALSE"
+ DebugInformationFormat="3"/>
+ <Tool
+ Name="VCCustomBuildTool"/>
+ <Tool
+ Name="VCLibrarianTool"
+ OutputFile="../../lib/$(ProjectName)R.lib"/>
+ <Tool
+ Name="VCMIDLTool"/>
+ <Tool
+ Name="VCPostBuildEventTool"/>
+ <Tool
+ Name="VCPreBuildEventTool"/>
+ <Tool
+ Name="VCPreLinkEventTool"/>
+ <Tool
+ Name="VCResourceCompilerTool"/>
+ <Tool
+ Name="VCWebServiceProxyGeneratorTool"/>
+ <Tool
+ Name="VCXMLDataGeneratorTool"/>
+ <Tool
+ Name="VCManagedWrapperGeneratorTool"/>
+ <Tool
+ Name="VCAuxiliaryManagedWrapperGeneratorTool"/>
+ </Configuration>
+ <Configuration
+ Name="Debug Unicode|Win32"
+ OutputDirectory="Debug Unicode"
+ IntermediateDirectory="Debug Unicode"
+ ConfigurationType="4"
+ UseOfMFC="2"
+ CharacterSet="1">
+ <Tool
+ Name="VCCLCompilerTool"
+ Optimization="0"
+ PreprocessorDefinitions="WIN32;_DEBUG;_LIB"
+ MinimalRebuild="TRUE"
+ BasicRuntimeChecks="3"
+ RuntimeLibrary="3"
+ UsePrecompiledHeader="3"
+ WarningLevel="3"
+ Detect64BitPortabilityProblems="FALSE"
+ DebugInformationFormat="4"/>
+ <Tool
+ Name="VCCustomBuildTool"/>
+ <Tool
+ Name="VCLibrarianTool"
+ OutputFile="../../lib/$(ProjectName)DU.lib"/>
+ <Tool
+ Name="VCMIDLTool"/>
+ <Tool
+ Name="VCPostBuildEventTool"/>
+ <Tool
+ Name="VCPreBuildEventTool"/>
+ <Tool
+ Name="VCPreLinkEventTool"/>
+ <Tool
+ Name="VCResourceCompilerTool"/>
+ <Tool
+ Name="VCWebServiceProxyGeneratorTool"/>
+ <Tool
+ Name="VCXMLDataGeneratorTool"/>
+ <Tool
+ Name="VCManagedWrapperGeneratorTool"/>
+ <Tool
+ Name="VCAuxiliaryManagedWrapperGeneratorTool"/>
+ </Configuration>
+ <Configuration
+ Name="Release Unicode|Win32"
+ OutputDirectory="Release Unicode"
+ IntermediateDirectory="Release Unicode"
+ ConfigurationType="4"
+ UseOfMFC="1"
+ CharacterSet="1">
+ <Tool
+ Name="VCCLCompilerTool"
+ Optimization="2"
+ InlineFunctionExpansion="1"
+ OmitFramePointers="TRUE"
+ PreprocessorDefinitions="WIN32;NDEBUG;_LIB"
+ StringPooling="TRUE"
+ RuntimeLibrary="0"
+ EnableFunctionLevelLinking="TRUE"
+ UsePrecompiledHeader="3"
+ WarningLevel="3"
+ Detect64BitPortabilityProblems="FALSE"
+ DebugInformationFormat="3"/>
+ <Tool
+ Name="VCCustomBuildTool"/>
+ <Tool
+ Name="VCLibrarianTool"
+ OutputFile="../../lib/$(ProjectName)RU.lib"/>
+ <Tool
+ Name="VCMIDLTool"/>
+ <Tool
+ Name="VCPostBuildEventTool"/>
+ <Tool
+ Name="VCPreBuildEventTool"/>
+ <Tool
+ Name="VCPreLinkEventTool"/>
+ <Tool
+ Name="VCResourceCompilerTool"/>
+ <Tool
+ Name="VCWebServiceProxyGeneratorTool"/>
+ <Tool
+ Name="VCXMLDataGeneratorTool"/>
+ <Tool
+ Name="VCManagedWrapperGeneratorTool"/>
+ <Tool
+ Name="VCAuxiliaryManagedWrapperGeneratorTool"/>
+ </Configuration>
+ </Configurations>
+ <References>
+ </References>
+ <Files>
+ <Filter
+ Name="Source Files"
+ Filter="cpp;c;cxx;def;odl;idl;hpj;bat;asm">
+ <File
+ RelativePath="CSSauth.cpp">
+ </File>
+ <File
+ RelativePath="CSSscramble.cpp">
+ </File>
+ <File
+ RelativePath=".\DeCSSInputPin.cpp">
+ </File>
+ <File
+ RelativePath="stdafx.cpp">
+ <FileConfiguration
+ Name="Debug|Win32">
+ <Tool
+ Name="VCCLCompilerTool"
+ UsePrecompiledHeader="1"/>
+ </FileConfiguration>
+ <FileConfiguration
+ Name="Release|Win32">
+ <Tool
+ Name="VCCLCompilerTool"
+ UsePrecompiledHeader="1"/>
+ </FileConfiguration>
+ <FileConfiguration
+ Name="Debug Unicode|Win32">
+ <Tool
+ Name="VCCLCompilerTool"
+ UsePrecompiledHeader="1"/>
+ </FileConfiguration>
+ <FileConfiguration
+ Name="Release Unicode|Win32">
+ <Tool
+ Name="VCCLCompilerTool"
+ UsePrecompiledHeader="1"/>
+ </FileConfiguration>
+ </File>
+ <File
+ RelativePath="VobDec.cpp">
+ </File>
+ <File
+ RelativePath="VobFile.cpp">
+ </File>
+ </Filter>
+ <Filter
+ Name="Header Files"
+ Filter="h;hpp;hxx;hm;inl;inc">
+ <File
+ RelativePath="CSSauth.h">
+ </File>
+ <File
+ RelativePath="CSSscramble.h">
+ </File>
+ <File
+ RelativePath="decss.h">
+ </File>
+ <File
+ RelativePath=".\DeCSSInputPin.h">
+ </File>
+ <File
+ RelativePath="stdafx.h">
+ </File>
+ <File
+ RelativePath="VobDec.h">
+ </File>
+ <File
+ RelativePath="VobFile.h">
+ </File>
+ </Filter>
+ <Filter
+ Name="Resource Files"
+ Filter="rc;ico;cur;bmp;dlg;rc2;rct;bin;rgs;gif;jpg;jpeg;jpe">
+ </Filter>
+ <Filter
+ Name="vstrip"
+ Filter="">
+ <File
+ RelativePath="udf.cpp">
+ </File>
+ <File
+ RelativePath="udf.h">
+ </File>
+ </Filter>
+ </Files>
+ <Globals>
+ <Global
+ Name="DevPartner_IsInstrumented"
+ Value="0"/>
+ </Globals>
+</VisualStudioProject>
diff --git a/src/decss/decss.vcproj.vspscc b/src/decss/decss.vcproj.vspscc
new file mode 100644
index 000000000..78331ece4
--- /dev/null
+++ b/src/decss/decss.vcproj.vspscc
@@ -0,0 +1,10 @@
+""
+{
+"FILE_VERSION" = "9237"
+"ENLISTMENT_CHOICE" = "NEVER"
+"PROJECT_FILE_RELATIVE_PATH" = "relative:decss"
+"NUMBER_OF_EXCLUDED_FILES" = "0"
+"ORIGINAL_PROJECT_FILE_PATH" = ""
+"NUMBER_OF_NESTED_PROJECTS" = "0"
+"SOURCE_CONTROL_SETTINGS_PROVIDER" = "PROVIDER"
+}
diff --git a/src/decss/stdafx.cpp b/src/decss/stdafx.cpp
new file mode 100644
index 000000000..f06429c1f
--- /dev/null
+++ b/src/decss/stdafx.cpp
@@ -0,0 +1,8 @@
+// stdafx.cpp : source file that includes just the standard includes
+// decss.pch will be the pre-compiled header
+// stdafx.obj will contain the pre-compiled type information
+
+#include "stdafx.h"
+
+// TODO: reference any additional headers you need in STDAFX.H
+// and not in this file
diff --git a/src/decss/stdafx.h b/src/decss/stdafx.h
new file mode 100644
index 000000000..58101e98b
--- /dev/null
+++ b/src/decss/stdafx.h
@@ -0,0 +1,18 @@
+// stdafx.h : include file for standard system include files,
+// or project specific include files that are used frequently, but
+// are changed infrequently
+//
+
+#pragma once
+
+#define WIN32_LEAN_AND_MEAN // Exclude rarely-used stuff from Windows headers
+#define _ATL_CSTRING_EXPLICIT_CONSTRUCTORS // some CString constructors will be explicit
+
+#ifndef VC_EXTRALEAN
+#define VC_EXTRALEAN // Exclude rarely-used stuff from Windows headers
+#endif
+
+#include <afx.h>
+#include <afxwin.h> // MFC core and standard components
+
+// TODO: reference additional headers your program requires here
diff --git a/src/decss/udf.cpp b/src/decss/udf.cpp
new file mode 100644
index 000000000..a91a6cde2
--- /dev/null
+++ b/src/decss/udf.cpp
@@ -0,0 +1,355 @@
+/*************************************************************************
+ vStrip by [maven] (maven@maven.de)
+ udf.c: routines for udf-parsing (because windows just doesn't cut it),
+ refs: udf102.pdf, udf200.pdf, ecma 167
+ (tabsize 2)
+*************************************************************************/
+
+#include "stdafx.h"
+#include "udf.h"
+
+static bool aspi_GetSectorInfo(const HANDLE hDrive, DWORD* sec_size, DWORD* max_sec)
+{
+ LARGE_INTEGER size;
+ size.LowPart = GetFileSize(hDrive, (DWORD*)&size.HighPart);
+
+ *sec_size = 2048;
+ *max_sec = size.QuadPart / *sec_size;
+
+ return true;
+}
+
+static bool aspi_ReadSectors(const HANDLE hDrive, int lba, int nSectors, DWORD sec_size, BYTE* sector)
+{
+ DWORD nbr = 0;
+ return lba*sec_size == SetFilePointer(hDrive, lba*sec_size, NULL, FILE_BEGIN)
+ && ReadFile(hDrive, sector, nSectors*sec_size, &nbr, NULL);
+}
+
+static bool udf_GetLBA(const tp_udf_FileEntry fe, const DWORD sec_size, DWORD *start, DWORD *end)
+{
+ if (fe->LengthofAllocationDescriptors == 0)
+ return false;
+ switch (fe->ICBTag.Flags & udf_icbf_Mask)
+ {
+ case udf_icbf_ShortAd:
+ {
+ tp_udf_short_ad ad = (tp_udf_short_ad)(fe->ExtendedAttributes + fe->LengthofExtendedAttributes);
+
+ *start = ad->Location;
+ *end = *start + ((ad->Length & udf_LengthMask) - 1) / sec_size;
+ return true;
+ }
+ break;
+ case udf_icbf_LongAd:
+ {
+ tp_udf_long_ad ad = (tp_udf_long_ad)(fe->ExtendedAttributes + fe->LengthofExtendedAttributes);
+
+ *start = ad->Location.Location; // ignore partition number
+ *end = *start + ((ad->Length & udf_LengthMask) - 1) / sec_size;
+ return true;
+ }
+ break;
+ case udf_icbf_ExtAd:
+ {
+ tp_udf_ext_ad ad = (tp_udf_ext_ad)(fe->ExtendedAttributes + fe->LengthofExtendedAttributes);
+
+ *start = ad->Location.Location; // ignore partition number
+ *end = *start + ((ad->Length & udf_LengthMask) - 1) / sec_size;
+ return true;
+ }
+ break;
+ }
+ return false;
+}
+
+tp_udf_file udf_get_root(const HANDLE hDrive, const WORD partition_number)
+{
+ BYTE sector[fio_SECTOR_SIZE];
+ tp_udf_tag tag = (tp_udf_tag)sector;
+ DWORD sec_size, max_sec, i, j;
+ DWORD MVDS_lba, MVDS_lba_end, MVDS_back_lba, MVDS_back_lba_end;
+ DWORD FileDescriptorSequence_lba, FileDescriptorSequence_lba_end;
+ DWORD partition_lba, parent_icb;
+ tp_udf_AnchorVolumeDescriptorPointer avd;
+ bool res, part_valid, vol_valid;
+
+ if (!aspi_GetSectorInfo(hDrive, &sec_size, &max_sec))
+ return NULL;
+
+ if (sec_size != fio_SECTOR_SIZE || max_sec < 256)
+ return NULL;
+
+ // read AnchorVolumeDescriptorPointer at 256 (or MaxSec) (Tag == 2)
+ res = aspi_ReadSectors(hDrive, 256, 1, sec_size, sector);
+ if (!res || tag->TagIdentifier != udf_TAG_AnchorVolumeDescriptor)
+ {
+ res = aspi_ReadSectors(hDrive, max_sec, 1, sec_size, sector);
+ if (!res || tag->TagIdentifier != udf_TAG_AnchorVolumeDescriptor)
+ return NULL;
+ }
+
+ // check Static Structures
+
+ // get MainVolumeDescriptorSequence Location & Length
+ avd = (tp_udf_AnchorVolumeDescriptorPointer)sector;
+ MVDS_lba = avd->MainVolumeDescriptorSequenceExtent.Location;
+ MVDS_lba_end = MVDS_lba + (avd->MainVolumeDescriptorSequenceExtent.Length - 1) / sec_size;
+ MVDS_back_lba = avd->ReserveVolumeDescriptorSequenceExtent.Location;
+ MVDS_back_lba_end = MVDS_back_lba + (avd->ReserveVolumeDescriptorSequenceExtent.Length - 1) / sec_size;
+
+ // read MVDS_Location..MVDS_Location + (MVDS_Length - 1) / SectorSize sectors
+
+ part_valid = vol_valid = false;
+ i = 1;
+ do
+ { // try twice (if we need to) for ReserveAnchor
+ j = MVDS_lba;
+ do
+ {
+ res = aspi_ReadSectors(hDrive, j++, 1, sec_size, sector);
+ if (res)
+ {
+ if (tag->TagIdentifier == udf_TAG_PartitionDescriptor && !part_valid)
+ { // get stuff out of partition
+ tp_udf_PartitionDescriptor par = (tp_udf_PartitionDescriptor )sector;
+
+ part_valid = par->PartitionNumber == partition_number;
+ if (part_valid)
+ { // extract par->PartitionStartingLocation, par->PartitionLength
+ partition_lba = par->PartitionStartingLocation;
+ }
+ }
+ else if (tag->TagIdentifier == udf_TAG_LogicalVolumeDescriptor && !vol_valid)
+ { // get stuff out of volume
+ tp_udf_LogicalVolumeDescriptor vol = (tp_udf_LogicalVolumeDescriptor)sector;
+
+ // check_volume sector size
+ vol_valid = (vol->LogicalBlockSize == sec_size) && (partition_number == vol->FileSetDescriptorSequence.Location.PartitionNumber);
+ if (vol_valid)
+ { // extract vol->FileSetDescriptorSequence
+ FileDescriptorSequence_lba = vol->FileSetDescriptorSequence.Location.Location;
+ FileDescriptorSequence_lba_end = FileDescriptorSequence_lba + ((vol->FileSetDescriptorSequence.Length & udf_LengthMask) - 1) / sec_size;
+ }
+ }
+ }
+ else
+ tag->TagIdentifier = 0;
+ } while (j <= MVDS_lba_end && tag->TagIdentifier != udf_TAG_TerminatingDescriptor && ((!part_valid) || (!vol_valid)));
+
+ if ((!part_valid) || (!vol_valid))
+ { // try backup
+ MVDS_lba = MVDS_back_lba;
+ MVDS_lba_end = MVDS_back_lba_end;
+ }
+ } while (i-- && ((!part_valid) || (!vol_valid)));
+
+ if (part_valid && vol_valid)
+ { // read FileSetDescriptor, get RootDir Location & Length, RootDir Length != 0
+ res = aspi_ReadSectors(hDrive, FileDescriptorSequence_lba + partition_lba, 1, sec_size, sector);
+ if (res && tag->TagIdentifier == udf_TAG_FileSetDescriptor)
+ {
+ tp_udf_FileSetDescriptor fsd = (tp_udf_FileSetDescriptor)sector;
+
+ if (partition_number == fsd->RootDirectoryICB.Location.PartitionNumber)
+ {
+ parent_icb = fsd->RootDirectoryICB.Location.Location;
+ res = aspi_ReadSectors(hDrive, partition_lba + parent_icb, 1, sec_size, sector);
+ if (res && tag->TagIdentifier == udf_TAG_FileEntry)
+ {
+ tp_udf_FileEntry fe = (tp_udf_FileEntry)sector;
+
+ if (fe->ICBTag.FileType == udf_FT_Directory)
+ {
+ tp_udf_file root = (tp_udf_file)malloc(sizeof *root);
+
+ root->partition_lba = partition_lba;
+ udf_GetLBA(fe, sec_size, &root->dir_lba, &root->dir_end_lba);
+ root->dir_left = (DWORD)fe->InformationLength; // don't want directories of more than 4gb
+ root->sector = NULL;
+ root->fid = NULL;
+ root->sec_size = sec_size;
+ strcpy(root->name, "/");
+ root->is_dir = true;
+ root->is_parent = false;
+ return root;
+ }
+ }
+ }
+ }
+ }
+
+ return NULL;
+}
+
+static void udf_GetName(const BYTE *data, const DWORD len, char *target)
+{
+ DWORD p = 1, i = 0;
+
+ if (len == 0 || !(data[0] & 0x18))
+ target[0] = '\0';
+
+ if (data[0] & 0x10)
+ { // ignore MSB of unicode16
+ p++;
+
+ while (p < len)
+ target[i++] = data[p += 2];
+ }
+ else
+ {
+ while (p < len)
+ target[i++] = data[p++];
+ }
+
+ target[i]='\0';
+}
+
+tp_udf_file udf_get_sub(const HANDLE hDrive, tp_udf_file f)
+{
+ if (f->is_dir && !f->is_parent && f->fid)
+ {
+ BYTE sector[fio_SECTOR_SIZE];
+ tp_udf_tag tag = (tp_udf_tag)sector;
+ bool res;
+
+ res = aspi_ReadSectors(hDrive, f->partition_lba + f->fid->ICB.Location.Location, 1, f->sec_size, sector);
+ if (res && tag->TagIdentifier == udf_TAG_FileEntry)
+ {
+ tp_udf_FileEntry fe = (tp_udf_FileEntry)sector;
+
+ if (fe->ICBTag.FileType == udf_FT_Directory)
+ {
+ tp_udf_file newf = (tp_udf_file)malloc(sizeof *newf);
+
+ strcpy(newf->name, f->name); // maybe just ""?
+ newf->sec_size = f->sec_size;
+ newf->partition_lba = f->partition_lba;
+ udf_GetLBA(fe, f->sec_size, &newf->dir_lba, &newf->dir_end_lba);
+ newf->dir_left = (DWORD)fe->InformationLength; // don't want directories of more than 4gb
+ newf->sector = NULL;
+ newf->fid = NULL;
+ newf->is_dir = true;
+ newf->is_parent = false;
+ return newf;
+ }
+ }
+ }
+ return NULL;
+}
+
+tp_udf_file udf_get_next(const HANDLE hDrive, tp_udf_file f)
+{
+ bool res = true;
+
+ if (f->dir_left <= 0)
+ {
+ f->fid = NULL;
+ return NULL;
+ }
+
+ if (f->fid)
+ { // advance to next FileIdentifierDescriptor
+ DWORD ofs = 4 * ((sizeof *(f->fid) + f->fid->LengthofImplementationUse + f->fid->LengthofFileIdentifier + 3) / 4);
+
+ f->fid = (tp_udf_FileIdentifierDescriptor)((BYTE *)f->fid + ofs);
+ }
+
+ if (f->fid == NULL)
+ {
+ DWORD size = f->sec_size * (f->dir_end_lba - f->dir_lba + 1);
+
+ if (!f->sector)
+ f->sector = (BYTE*)malloc(size);
+ res = aspi_ReadSectors(hDrive, f->partition_lba + f->dir_lba, (WORD)(f->dir_end_lba - f->dir_lba + 1), f->sec_size, f->sector);
+ if (res)
+ f->fid = (tp_udf_FileIdentifierDescriptor)f->sector;
+ else
+ f->fid = NULL;
+ }
+
+ if (f->fid && f->fid->DescriptorTag.TagIdentifier == udf_TAG_FileIdentifierDescriptor)
+ {
+ DWORD ofs = 4 * ((sizeof *f->fid + f->fid->LengthofImplementationUse + f->fid->LengthofFileIdentifier + 3) / 4);
+
+ f->dir_left -= ofs;
+ f->is_dir = (f->fid->FileCharacteristics & udf_FID_Directory) != 0;
+ f->is_parent = (f->fid->FileCharacteristics & udf_FID_Parent) != 0;
+ udf_GetName(f->fid->ImplementationUse + f->fid->LengthofImplementationUse, f->fid->LengthofFileIdentifier, f->name);
+ return f;
+ }
+ return NULL;
+}
+
+void udf_free(tp_udf_file f)
+{
+ if (f)
+ {
+ if (f->sector)
+ free(f->sector);
+ free(f);
+ }
+}
+
+#define udf_PATH_DELIMITERS "/\\"
+
+static tp_udf_file udf_ff_traverse(const HANDLE hDrive, tp_udf_file f, char *token)
+{
+ while (udf_get_next(hDrive, f))
+ {
+ if (stricmp(token, f->name) == 0)
+ {
+ char *next_tok = strtok(NULL, udf_PATH_DELIMITERS);
+
+ if (!next_tok)
+ return f; // found
+ else if (f->is_dir)
+ {
+ tp_udf_file f2 = udf_get_sub(hDrive, f);
+
+ if (f2)
+ {
+ tp_udf_file f3 = udf_ff_traverse(hDrive, f2, next_tok);
+
+ if (!f3)
+ udf_free(f2);
+ return f3;
+ }
+ }
+ }
+ }
+ return NULL;
+}
+
+tp_udf_file udf_find_file(const HANDLE hDrive, const WORD partition, const char *name)
+{
+ tp_udf_file f = udf_get_root(hDrive, partition), f2 = NULL;
+
+ if (f)
+ {
+ char tokenline[udf_MAX_PATHLEN];
+ char *token;
+
+ strcpy(tokenline, name);
+ token = strtok(tokenline, udf_PATH_DELIMITERS);
+ if (token)
+ f2 = udf_ff_traverse(hDrive, f, token);
+ udf_free(f);
+ }
+ return f2;
+}
+
+bool udf_get_lba(const HANDLE hDrive, const tp_udf_file f, DWORD *start_lba, DWORD *end_lba)
+{
+ if (f->fid)
+ {
+ BYTE sector[2048];
+ tp_udf_FileEntry fe = (tp_udf_FileEntry)sector;
+ bool res;
+
+ res = aspi_ReadSectors(hDrive, f->partition_lba + f->fid->ICB.Location.Location, 1, f->sec_size, sector);
+ if (res && fe->DescriptorTag.TagIdentifier == udf_TAG_FileEntry)
+ return udf_GetLBA(fe, f->sec_size, start_lba, end_lba);
+ }
+ return false;
+}
diff --git a/src/decss/udf.h b/src/decss/udf.h
new file mode 100644
index 000000000..c108f59d1
--- /dev/null
+++ b/src/decss/udf.h
@@ -0,0 +1,265 @@
+#pragma once
+
+/*************************************************************************
+ vStrip by [maven] (maven@maven.de)
+*************************************************************************/
+
+typedef unsigned __int64 QWORD;
+#define fio_SECTOR_SIZE 2048
+
+typedef char dstring; // last BYTE of string indicates encoding/length
+
+#define udf_LengthMask 0x3fffffff
+
+#define udf_TAG_PrimaryVolumeDescriptor 0x0001
+#define udf_TAG_AnchorVolumeDescriptor 0x0002
+#define udf_TAG_PartitionDescriptor 0x0005
+#define udf_TAG_LogicalVolumeDescriptor 0x0006
+#define udf_TAG_TerminatingDescriptor 0x0008
+#define udf_TAG_FileSetDescriptor 0x0100
+#define udf_TAG_FileIdentifierDescriptor 0x0101
+#define udf_TAG_IndirectEntry 0x0103
+#define udf_TAG_TerminalEntry 0x0104
+#define udf_TAG_FileEntry 0x0105
+
+#define udf_FT_IndirectEntry 0x03
+#define udf_FT_Directory 0x04
+#define udf_FT_File 0x05
+#define udf_FT_TerminalEntry 0x0b
+
+#define udf_icbf_Mask 0x0007
+#define udf_icbf_ShortAd 0x0000
+#define udf_icbf_LongAd 0x0001
+#define udf_icbf_ExtAd 0x0002
+#define udf_icbf_Direct 0x0003
+#define udf_icbf_Contiguous 0x0100
+
+#define udf_FID_Directory 0x02
+#define udf_FID_Parent 0x08
+
+#pragma pack(push, 1)
+
+typedef struct
+{
+ DWORD Length; // 00, high 2 bits: 0 ^= recorded & used, 1 ^= not recorded & used, 2 ^= not recorded & not used, 3 ^= linked list
+ DWORD Location; // 04
+} t_udf_short_ad, *tp_udf_short_ad; // 08
+
+typedef struct
+{
+ DWORD Length; // 00
+ DWORD Location; // 04
+} t_udf_extent_ad, *tp_udf_extent_ad; // 08
+
+typedef struct
+{
+ DWORD Location; // 00, relative to volume
+ WORD PartitionNumber; // 04
+} t_udf_lb_addr; // 06
+
+typedef struct
+{
+ DWORD Length; // 00, high 2 bits: 0 ^= recorded & used, 1 ^= not recorded & used, 2 ^= not recorded & not used, 3 ^= linked list
+ t_udf_lb_addr Location; // 04
+ BYTE ImplementationUse[6]; // 10
+} t_udf_long_ad, *tp_udf_long_ad; // 16
+
+typedef struct
+{
+ DWORD Length; // 00, high 2 bits: 0 ^= recorded & used, 1 ^= not recorded & used, 2 ^= not recorded & not used, 3 ^= linked list
+ DWORD RecordedLength; // 04
+ DWORD InformationLength; // 08
+ t_udf_lb_addr Location; // 12
+ BYTE ImplementationUse[2]; // 18
+} t_udf_ext_ad, *tp_udf_ext_ad; // 20
+
+typedef struct
+{
+ BYTE CharacterSetType; // 00
+ BYTE CharacterSetInfo[63]; // 01
+} t_udf_charspec; // 64
+
+typedef struct
+{ /* ECMA 167 1/7.3 */
+ WORD TypeAndTimezone; // 00
+ WORD Year; // 02
+ BYTE Month; // 04
+ BYTE Day; // 05
+ BYTE Hour; // 06
+ BYTE Minute; // 07
+ BYTE Second; // 08
+ BYTE Centiseconds; // 09
+ BYTE HundredsofMicroseconds; // 10
+ BYTE Microseconds; // 11
+} t_udf_timestamp; // 12
+
+typedef struct
+{ /* ISO 13346 3/7.2 */
+ WORD TagIdentifier; // 00
+ WORD DescriptorVersion; // 02
+ BYTE TagChecksum; // 04
+ BYTE Reserved; // 05
+ WORD TagSerialNumber; // 06
+ WORD DescriptorCRC; // 08
+ WORD DescriptorCRCLength; // 10
+ DWORD TagLocation; // 12
+} t_udf_tag, *tp_udf_tag; // 16
+
+typedef struct
+{ /* ISO 13346 1/7.4 */
+ BYTE Flags; // 00
+ char Identifier[23]; // 01
+ char IdentifierSuffix[8]; // 24
+} t_udf_EntityID; // 32
+
+typedef struct
+{ /* ISO 13346 3/10.2 */
+ t_udf_tag DescriptorTag; // 00
+ t_udf_extent_ad MainVolumeDescriptorSequenceExtent; // 16
+ t_udf_extent_ad ReserveVolumeDescriptorSequenceExtent; // 24
+ BYTE Reserved[480]; // 32
+} t_udf_AnchorVolumeDescriptorPointer, *tp_udf_AnchorVolumeDescriptorPointer; // 512
+
+typedef struct
+{ /* ISO 13346 3/10.6 */
+ t_udf_tag DescriptorTag; // 00
+ DWORD VolumeDescriptorSequenceNumber; // 16
+ t_udf_charspec DescriptorCharacterSet; // 20
+ dstring LogicalVolumeIdentifier[128]; // 84
+ DWORD LogicalBlockSize; // 212
+ t_udf_EntityID DomainIdentifier; // 244
+// BYTE LogicalVolumeContentsUse[16]; // 276
+ t_udf_long_ad FileSetDescriptorSequence; // 276
+ DWORD MapTableLength; // 292
+ DWORD NumberofPartitionMaps; // 296
+ t_udf_EntityID ImplementationIdentifier; // 300
+ BYTE ImplementationUse[128]; // 332
+ t_udf_extent_ad IntegritySequenceExtent; // 460
+ BYTE PartitionMaps[1]; // 468
+} t_udf_LogicalVolumeDescriptor, *tp_udf_LogicalVolumeDescriptor;
+
+typedef struct
+{
+ t_udf_short_ad UnallocatedSpaceTable; // 00
+ t_udf_short_ad UnallocatedSpaceBitmap; // 08
+ t_udf_short_ad PartitionIntegrityTable; // 16
+ t_udf_short_ad FreedSpaceTable; // 24
+ t_udf_short_ad FreedSpaceBitmap; // 32
+ BYTE Reserved[88]; // 40
+} t_udf_PartitionHeaderDescriptor; // 128
+
+typedef struct
+{ /* ECMA 167 3/10.5 */
+ t_udf_tag DescriptorTag; // 00
+ DWORD VolumeDescriptorSequenceNumber; // 16
+ WORD PartitionFlags; // 20
+ WORD PartitionNumber; // 22
+ t_udf_EntityID PartitionContents; // 24
+ t_udf_PartitionHeaderDescriptor PartitionHeaderDescriptor; // 56
+ DWORD AccessType; // 184, 0 unspecified, 1 read only, 2 write once, 3 rewriteable, 4 overwriteable
+ DWORD PartitionStartingLocation; // 188
+ DWORD PartitionLength; // 192
+ t_udf_EntityID ImplementationIdentifier; // 196
+ BYTE ImplementationUse[128]; // 228
+ BYTE Reserved[156]; // 356
+} t_udf_PartitionDescriptor, *tp_udf_PartitionDescriptor; // 512
+
+typedef struct
+{ /* ECMA 167 4/14.1 */
+ t_udf_tag DescriptorTag; // 00
+ t_udf_timestamp RecordingDateandTime; // 16
+ WORD InterchangeLevel; // 28
+ WORD MaximumInterchangeLevel; // 30
+ DWORD CharacterSetList; // 32
+ DWORD MaximumCharacterSetList; // 36
+ DWORD FileSetNumber; // 40
+ DWORD FileSetDescriptorNumber; // 44
+ t_udf_charspec LogicalVolumeIdentifierCharacterSet; // 48
+ dstring LogicalVolumeIdentifier[128]; // 112
+ t_udf_charspec FileSetCharacterSet; // 240
+ dstring FileSetIdentifer[32]; // 304
+ dstring CopyrightFileIdentifier[32]; // 336
+ dstring AbstractFileIdentifier[32]; // 368
+ t_udf_long_ad RootDirectoryICB; // 400
+ t_udf_EntityID DomainIdentifier; // 416
+ t_udf_long_ad NextExtent; // 448
+ t_udf_long_ad StreamDirectoryICB; // 464
+ BYTE Reserved[32]; // 480
+} t_udf_FileSetDescriptor, *tp_udf_FileSetDescriptor; // 512
+
+typedef struct
+{ /* ECMA 167 4/14.6 */
+ DWORD PriorRecordedNumberofDirectEntries; // 00
+ WORD StrategyType; // 04
+ BYTE StrategyParameter[2]; // 06
+ WORD NumberofEntries; // 08
+ BYTE Reserved; // 10
+ BYTE FileType; // 11
+ t_udf_lb_addr ParentICBLocation; // 12
+ WORD Flags; // 18
+} t_udf_icbtag; // 20
+
+typedef struct
+{ /* ECMA 167 4/14.9 */
+ t_udf_tag DescriptorTag; // 00
+ t_udf_icbtag ICBTag; // 16
+ DWORD Uid; // 36
+ DWORD Gid; // 40
+ DWORD Permissions; // 44
+ WORD FileLinkCount; // 48
+ BYTE RecordFormat; // 50
+ BYTE RecordDisplayAttributes; // 51
+ DWORD RecordLength; // 52
+ QWORD InformationLength; // 56
+ QWORD LogicalBlocksRecorded; // 64
+ t_udf_timestamp AccessTime; // 72
+ t_udf_timestamp ModificationTime; // 84
+ t_udf_timestamp AttributeTime; // 96
+ DWORD Checkpoint; // 108
+ t_udf_long_ad ExtendedAttributeICB; // 112
+ t_udf_EntityID ImplementationIdentifier; // 128
+ QWORD UniqueID; // 160
+ DWORD LengthofExtendedAttributes; // 168
+ DWORD LengthofAllocationDescriptors; // 172
+ BYTE ExtendedAttributes[]; // 176
+// BYTE AllocationDescriptors[]; // 176
+} t_udf_FileEntry, *tp_udf_FileEntry; // >= 176
+
+typedef struct
+{ /* ECMA 167 4/14.4 */
+ t_udf_tag DescriptorTag; // 00
+ WORD FileVersionNumber; // 16
+ BYTE FileCharacteristics; // 18
+ BYTE LengthofFileIdentifier; // 19
+ t_udf_long_ad ICB; // 20
+ WORD LengthofImplementationUse; // 36
+ BYTE ImplementationUse[]; // 38
+// char FileIdentifier[]; // 38
+// BYTE Padding[]; // 38
+} t_udf_FileIdentifierDescriptor, *tp_udf_FileIdentifierDescriptor; // >= 38
+
+#define udf_MAX_NAMELEN 256
+#define udf_MAX_PATHLEN 2048
+
+typedef struct
+{
+ // public
+ char name[udf_MAX_NAMELEN];
+ bool is_dir, is_parent;
+ // internal
+ BYTE *sector;
+ tp_udf_FileIdentifierDescriptor fid;
+ DWORD partition_lba;
+ DWORD dir_lba, dir_end_lba;
+ DWORD sec_size;
+ int dir_left;
+} t_udf_file, *tp_udf_file;
+
+#pragma pack(pop)
+
+tp_udf_file udf_find_file(const HANDLE hDrive, const WORD partition, const char *name);
+tp_udf_file udf_get_root(const HANDLE hDrive, const WORD partition_number);
+tp_udf_file udf_get_next(const HANDLE hDrive, tp_udf_file f); // advances f
+tp_udf_file udf_get_sub(const HANDLE hDrive, tp_udf_file f); // creates new f
+bool udf_get_lba(const HANDLE hDrive, const tp_udf_file f, DWORD *start_lba, DWORD *end_lba);
+void udf_free(tp_udf_file f);