diff -ur libdvdread-0.9.7.orig/dvdread/dvd_input.c libdvdread-0.9.7/dvdread/dvd_input.c
--- libdvdread-0.9.7.orig/dvdread/dvd_input.c	2008-02-25 10:55:39.000000000 +0100
+++ libdvdread-0.9.7/dvdread/dvd_input.c	2008-04-18 18:34:56.000000000 +0200
@@ -376,6 +376,8 @@
   }
 #endif /* HAVE_DVDCSS_DVDCSS_H */
 
+	fprintf(stderr, "libdvdread patched to play DVDs with DVD-Movie-Protect 0.2\n");
+
   dvdcss_library_init = 1;
   
   if(dvdcss_library) {
diff -ur libdvdread-0.9.7.orig/dvdread/dvd_udf.c libdvdread-0.9.7/dvdread/dvd_udf.c
--- libdvdread-0.9.7.orig/dvdread/dvd_udf.c	2008-02-25 10:55:39.000000000 +0100
+++ libdvdread-0.9.7/dvdread/dvd_udf.c	2008-04-18 18:59:15.000000000 +0200
@@ -39,6 +39,9 @@
 #include <sys/stat.h>
 #include <unistd.h>
 #include <errno.h>
+#ifndef __WIN32__
+#include <fnmatch.h>
+#endif
 
 #if defined(HAVE_INTTYPES_H)
 #include <inttypes.h>
@@ -50,6 +53,9 @@
 #include "dvd_udf.h"
 #include "dvdread_internal.h"
 
+#include "ifo_types.h"
+#include "ifo_read.h"
+
 #ifndef EMEDIUMTYPE
 #define EMEDIUMTYPE ENOENT
 #endif
@@ -962,7 +968,7 @@
   return part->valid;
 }
 
-uint32_t UDFFindFile( dvd_reader_t *device, char *filename,
+static uint32_t UDFFindFileReal( dvd_reader_t *device, char *filename,
                       uint32_t *filesize )
 {
   uint8_t *LogBlock;
@@ -1065,6 +1071,202 @@
   }
 }
 
+static uint32_t min(uint32_t a, uint32_t b)
+{
+	if (a > b)
+		return b;
+	else
+		return a;
+}
+
+/* VOBs may be arbitrarily split.
+ * This is the usual size http://www.mpucoder.com/DVD/vobov.html */
+const uint32_t max_vob_size =  0x7FFFF;
+
+static uint32_t file_size(ifo_handle_t *ifo_handle, char *extension, int vmg, int part);
+
+/* Return the number of VOBs in a title (without VTS_??_0.VOB) */
+static int number_of_vob_parts(ifo_handle_t *ifo_handle)
+{
+	return (ifo_handle->vtsi_mat->vts_last_sector
+			- ifo_handle->vtsi_mat->vtsm_vobs 
+			- file_size(ifo_handle, "IFO", 0, 0)) / max_vob_size + 1;
+}
+
+/* get the file size in blocks. Multiply it with DVD_VIDEO_LB_LEN
+ * to get the number of bytes. 
+ * vmg: is the file a VMG (VIDEO_TS.???) */
+static uint32_t file_size(ifo_handle_t *ifo_handle, char *extension, int vmg, int part)
+{
+	if (!strcmp(extension, "IFO")) {
+		if (vmg)
+			return ifo_handle->vmgi_mat->vmgi_last_sector;
+		else
+			return ifo_handle->vtsi_mat->vtsi_last_sector;
+	}
+	else if (!strcmp(extension, "VOB")) {
+		// VIDEO_TS.VOB
+		if (vmg) {
+			return ifo_handle->vmgi_mat->vmg_last_sector
+				- ifo_handle->vmgi_mat->vmgm_vobs
+				- file_size(ifo_handle, "IFO", vmg, 0);
+		}
+		// VTS_??_?.VOB
+		else {
+			if (0 == part)
+				return ifo_handle->vtsi_mat->vtstt_vobs 
+					- ifo_handle->vtsi_mat->vtsm_vobs;
+			else
+				return min(max_vob_size,
+						ifo_handle->vtsi_mat->vts_last_sector
+						- ifo_handle->vtsi_mat->vtsm_vobs - (part -1) * max_vob_size
+						- file_size(ifo_handle, "IFO", vmg, 0));
+		}
+	}
+
+	return 0;
+}
+
+static uint32_t get_offset(dvd_reader_t *device)
+{
+	uint32_t tmp_filesize;
+	return UDFFindFileReal(device, "/VIDEO_TS/VIDEO_TS.IFO", &tmp_filesize);
+}
+
+static void check_equal_ifo_udf(dvd_reader_t *device, char *filename, uint32_t offset, uint32_t filesize, int part)
+{
+	uint32_t udf_filesize;
+	uint32_t udf_offset = UDFFindFileReal(device, filename, &udf_filesize);
+
+	if (part > 1)
+		return;
+
+	if (0 == udf_offset)
+		warnx("libdvdread: File %s not in UDF file system (IFO offset: %d)", filename, offset);
+	else if (udf_offset != offset)
+		warnx("libdvdread: Offset different for %s:\tUDF: %d\t IFO: %d", filename, udf_offset, offset);
+
+	if (part <= 0 && udf_offset != 0 && udf_filesize != filesize)
+		warnx("libdvdread: file size different for %s:\tUDF: %d\t IFO: %d", filename, udf_filesize, filesize);
+}
+
+/**
+ * Get the offset from the ifo files to allow playback of DVDs
+ * with a deliberately broken UDF file system (aka DVD-Movie-Protect).
+ * When the file is not an IFO or VOB, it calls the real UDF routine.
+ */
+uint32_t UDFFindFile( dvd_reader_t *device, char *filename,
+		      uint32_t *filesize )
+{
+	if (!fnmatch("/VIDEO_TS/VIDEO_TS.???", filename, FNM_PATHNAME)) {
+		char *extension = &filename[strlen(filename)-3];
+
+		if (!strcmp(extension, "IFO")) {
+				*filesize = 20 * DVD_VIDEO_LB_LEN;
+				uint32_t tmp_filesize;
+				return UDFFindFileReal(device, filename, &tmp_filesize);
+		}
+		else if(!strcmp(extension, "VOB"))
+		{
+			ifo_handle_t *ifo_handle = ifoOpen(device, 0);
+			if (NULL == ifo_handle)
+				return 0;
+			uint32_t offset = get_offset(device) + ifo_handle->vmgi_mat->vmgm_vobs;
+
+			*filesize = DVD_VIDEO_LB_LEN * file_size(ifo_handle, extension, 1, 0);
+			ifoClose(ifo_handle);
+
+			check_equal_ifo_udf(device, filename, offset, *filesize, 0);
+
+			return offset;
+		}
+		else
+			return UDFFindFileReal(device, filename, filesize);
+
+	}
+
+  if (!fnmatch("/VIDEO_TS/VTS_[0-9][0-9]_[0-9].???", filename, FNM_PATHNAME))
+	{
+
+		size_t len = strlen(filename);
+		char *extension = &filename[len-3];
+		if (strcmp(extension, "IFO") && strcmp(extension, "VOB"))
+			return UDFFindFileReal (device, filename, filesize);
+
+		int title = atoi(&filename[len-8]);
+		int part = atoi(&filename[len-5]);
+
+		ifo_handle_t *ifo_handle = ifoOpen(device, 0);
+		if (0 == ifo_handle)
+			return 0;
+
+		uint32_t offset = get_offset(device);
+
+		int i;
+		for (i=0; i<ifo_handle->tt_srpt->nr_of_srpts; i++)
+			if (title == ifo_handle->tt_srpt->title[i].title_set_nr)
+				break;
+
+		if (i == ifo_handle->tt_srpt->nr_of_srpts) {
+			/* not found */
+			ifoClose(ifo_handle);
+			return 0;
+		}
+
+		offset += ifo_handle->tt_srpt->title[i].title_set_sector;
+		ifoClose(ifo_handle);
+
+		if (!strcmp(extension, "IFO")) {
+			*filesize = 25 * DVD_VIDEO_LB_LEN; /* TODO get real size */
+			return offset;
+		}
+
+		if (!strcmp(extension, "VOB")) {
+			ifo_handle = ifoOpen(device, title);
+			if (0 == ifo_handle)
+				return 0;
+
+
+			switch(part) {
+				case 0:
+					if (0 == ifo_handle->vtsi_mat->vtsm_vobs) {
+						ifoClose(ifo_handle);
+						return 0;
+					}
+					offset += ifo_handle->vtsi_mat->vtsm_vobs;
+					break;
+				case 1:
+					if (0 == ifo_handle->vtsi_mat->vtstt_vobs) {
+						ifoClose(ifo_handle);
+						return 0;
+					}
+					offset += ifo_handle->vtsi_mat->vtstt_vobs;
+					break;
+				default: 
+					if (part > number_of_vob_parts(ifo_handle))
+						return 0;
+					offset += ifo_handle->vtsi_mat->vtstt_vobs
+						+ (part -1 ) * max_vob_size;
+					break;
+			}
+			ifoClose(ifo_handle);
+		}
+
+		ifo_handle = ifoOpen(device, title);
+		if (0 == ifo_handle)
+			return 0;
+
+		*filesize = DVD_VIDEO_LB_LEN * file_size(ifo_handle, extension, 0, part);
+		ifoClose(ifo_handle);
+
+		check_equal_ifo_udf(device, filename, offset, *filesize, part);
+
+		if (offset != 0)
+			return offset;
+	}
+
+	return UDFFindFileReal( device, filename, filesize);
+}
 
 
 /**
