diff options
Diffstat (limited to 'src')
-rw-r--r-- | src/input/libdvdread/bswap.h | 13 | ||||
-rw-r--r-- | src/input/libdvdread/diff_against_cvs.patch | 768 | ||||
-rw-r--r-- | src/input/libdvdread/dvd_input.c | 86 | ||||
-rw-r--r-- | src/input/libdvdread/dvd_input.h | 16 | ||||
-rw-r--r-- | src/input/libdvdread/dvd_reader.c | 262 | ||||
-rw-r--r-- | src/input/libdvdread/dvd_reader.h | 82 | ||||
-rw-r--r-- | src/input/libdvdread/dvd_udf.c | 629 | ||||
-rw-r--r-- | src/input/libdvdread/dvd_udf.h | 8 | ||||
-rw-r--r-- | src/input/libdvdread/dvdread_internal.h | 12 | ||||
-rw-r--r-- | src/input/libdvdread/ifo_print.c | 218 | ||||
-rw-r--r-- | src/input/libdvdread/ifo_read.c | 367 | ||||
-rw-r--r-- | src/input/libdvdread/ifo_read.h | 3 | ||||
-rw-r--r-- | src/input/libdvdread/ifo_types.h | 228 | ||||
-rw-r--r-- | src/input/libdvdread/md5.c | 417 | ||||
-rw-r--r-- | src/input/libdvdread/md5.h | 161 | ||||
-rw-r--r-- | src/input/libdvdread/nav_print.c | 16 | ||||
-rw-r--r-- | src/input/libdvdread/nav_read.c | 123 | ||||
-rw-r--r-- | src/input/libdvdread/nav_types.h | 32 |
18 files changed, 2464 insertions, 977 deletions
diff --git a/src/input/libdvdread/bswap.h b/src/input/libdvdread/bswap.h index dd7417059..9c7402957 100644 --- a/src/input/libdvdread/bswap.h +++ b/src/input/libdvdread/bswap.h @@ -30,6 +30,11 @@ #else +/* For __FreeBSD_version */ +#if defined(HAVE_SYS_PARAM_H) +#include <sys/param.h> +#endif + #if defined(__linux__) #include <byteswap.h> #define B2N_16(x) x = bswap_16(x) @@ -48,9 +53,15 @@ #define B2N_32(x) x = swap32(x) #define B2N_64(x) x = swap64(x) +#elif defined(__FreeBSD__) && __FreeBSD_version >= 470000 +#include <sys/endian.h> +#define B2N_16(x) x = be16toh(x) +#define B2N_32(x) x = be32toh(x) +#define B2N_64(x) x = be64toh(x) + /* This is a slow but portable implementation, it has multiple evaluation * problems so beware. - * FreeBSD and Solaris don't have <byteswap.h> or any other such + * Old FreeBSD's and Solaris don't have <byteswap.h> or any other such * functionality! */ diff --git a/src/input/libdvdread/diff_against_cvs.patch b/src/input/libdvdread/diff_against_cvs.patch index f5470a554..349b4c1ee 100644 --- a/src/input/libdvdread/diff_against_cvs.patch +++ b/src/input/libdvdread/diff_against_cvs.patch @@ -1,6 +1,6 @@ ---- src/input/libdvdread/dvd_input.c 2002-11-27 21:56:47.000000000 +0100 -+++ src/input/libdvdread/dvd_input.c 2002-11-27 21:50:03.000000000 +0100 -@@ -63,7 +63,7 @@ +--- src/input/libdvdread/dvd_input.c 2003-02-13 22:48:24.000000000 +0100 ++++ src/input/libdvdread/dvd_input.c 2003-02-28 14:12:36.000000000 +0100 +@@ -74,7 +74,7 @@ dvd_input_t dev; /* Allocate the handle structure */ @@ -9,7 +9,7 @@ if(dev == NULL) { fprintf(stderr, "libdvdread: Could not allocate memory.\n"); return NULL; -@@ -143,7 +143,7 @@ +@@ -154,7 +154,7 @@ dvd_input_t dev; /* Allocate the library structure */ @@ -18,17 +18,9 @@ if(dev == NULL) { fprintf(stderr, "libdvdread: Could not allocate memory.\n"); return NULL; ---- src/input/libdvdread/dvd_reader.c 2002-11-27 21:56:47.000000000 +0100 -+++ src/input/libdvdread/dvd_reader.c 2002-11-27 21:51:31.000000000 +0100 -@@ -28,7 +28,6 @@ - #include <unistd.h> - #include <limits.h> - #include <dirent.h> -- - #if defined(__FreeBSD__) || defined(__OpenBSD__) || defined(__NetBSD__) || defined(__bsdi__)|| defined(__DARWIN__) - #define SYS_BSD 1 - #endif -@@ -41,6 +40,7 @@ +--- src/input/libdvdread/dvd_reader.c 2003-02-13 23:31:21.000000000 +0100 ++++ src/input/libdvdread/dvd_reader.c 2003-02-28 14:24:48.000000000 +0100 +@@ -44,6 +44,7 @@ #include <mntent.h> #endif @@ -36,7 +28,7 @@ #include "dvd_udf.h" #include "dvd_input.h" #include "dvd_reader.h" -@@ -289,7 +289,7 @@ +@@ -349,7 +350,7 @@ if( cdir >= 0 ) { chdir( path_copy ); @@ -45,7 +37,7 @@ fchdir( cdir ); close( cdir ); if( new_path ) { -@@ -452,7 +452,7 @@ +@@ -513,7 +514,7 @@ static int findDVDFile( dvd_reader_t *dvd, const char *file, char *filename ) { @@ -54,7 +46,7 @@ const char *nodirfile; int ret; -@@ -486,7 +486,7 @@ +@@ -547,7 +548,7 @@ */ static dvd_file_t *DVDOpenFilePath( dvd_reader_t *dvd, char *filename ) { @@ -63,7 +55,7 @@ dvd_file_t *dvd_file; struct stat fileinfo; dvd_input_t dev; -@@ -570,7 +570,7 @@ +@@ -631,7 +632,7 @@ static dvd_file_t *DVDOpenVOBPath( dvd_reader_t *dvd, int title, int menu ) { char filename[ MAX_UDF_FILE_NAME_LEN ]; @@ -72,7 +64,7 @@ struct stat fileinfo; dvd_file_t *dvd_file; int i; -@@ -867,7 +867,7 @@ +@@ -930,7 +931,7 @@ ssize_t DVDReadBytes( dvd_file_t *dvd_file, void *data, size_t byte_size ) { @@ -81,17 +73,19 @@ unsigned int numsec, seek_sector, seek_byte; int ret; -@@ -881,7 +881,8 @@ +@@ -944,8 +945,9 @@ numsec = ( ( seek_byte + byte_size ) / DVD_VIDEO_LB_LEN ) + ( ( ( seek_byte + byte_size ) % DVD_VIDEO_LB_LEN ) ? 1 : 0 ); - secbuf = (unsigned char *) malloc( numsec * DVD_VIDEO_LB_LEN ); +- if( !secbuf ) { + secbuf_base = (unsigned char *) malloc( numsec * DVD_VIDEO_LB_LEN + 2048 ); + secbuf = (unsigned char *)(((int)secbuf_base & ~2047) + 2048); - if( !secbuf ) { ++ if( !secbuf_base ) { fprintf( stderr, "libdvdread: Can't allocate memory " "for file read!\n" ); -@@ -897,12 +898,12 @@ + return 0; +@@ -960,12 +962,12 @@ } if( ret != (int) numsec ) { @@ -106,9 +100,85 @@ dvd_file->seek_pos += byte_size; return byte_size; ---- src/input/libdvdread/dvd_udf.c 2002-11-27 21:56:47.000000000 +0100 -+++ src/input/libdvdread/dvd_udf.c 2002-11-27 21:50:03.000000000 +0100 -@@ -123,7 +123,7 @@ +@@ -997,9 +999,10 @@ + if( dvd_file != NULL ) { + ssize_t bytes_read; + size_t file_size = dvd_file->filesize * DVD_VIDEO_LB_LEN; +- char *buffer = malloc( file_size ); ++ char *buffer_base = malloc( file_size + 2048 ); ++ char *buffer = (unsigned char *)(((int)buffer_base & ~2047) + 2048); + +- if( buffer == NULL ) { ++ if( buffer_base == NULL ) { + fprintf( stderr, "libdvdread: DVDDiscId, failed to " + "allocate memory for file read!\n" ); + return -1; +@@ -1009,13 +1012,14 @@ + fprintf( stderr, "libdvdread: DVDDiscId read returned %d bytes" + ", wanted %d\n", bytes_read, file_size ); + DVDCloseFile( dvd_file ); ++ free( buffer_base ); + return -1; + } + + md5_process_bytes( buffer, file_size, &ctx ); + + DVDCloseFile( dvd_file ); +- free( buffer ); ++ free( buffer_base ); + } + } + md5_finish_ctx( &ctx, discid ); +@@ -1028,7 +1032,7 @@ + char *volid, unsigned int volid_size, + unsigned char *volsetid, unsigned int volsetid_size ) + { +- unsigned char *buffer; ++ unsigned char *buffer, *buffer_base; + int ret; + + /* Check arguments. */ +@@ -1040,8 +1044,10 @@ + return -1; + } + +- buffer = malloc( DVD_VIDEO_LB_LEN ); +- if( buffer == NULL ) { ++ buffer_base = malloc( DVD_VIDEO_LB_LEN + 2048 ); ++ buffer = (unsigned char *)(((int)buffer_base & ~2047) + 2048); ++ ++ if( buffer_base == NULL ) { + fprintf( stderr, "libdvdread: DVDISOVolumeInfo, failed to " + "allocate memory for file read!\n" ); + return -1; +@@ -1051,6 +1057,7 @@ + if( ret != 1 ) { + fprintf( stderr, "libdvdread: DVDISOVolumeInfo, failed to " + "read ISO9660 Primary Volume Descriptor!\n" ); ++ free( buffer_base ); + return -1; + } + +@@ -1076,6 +1083,7 @@ + } + memcpy(volsetid, &buffer[190], volsetid_size); + } ++ free( buffer_base ); + return 0; + } + +--- src/input/libdvdread/dvd_udf.c 2003-02-13 22:57:17.000000000 +0100 ++++ src/input/libdvdread/dvd_udf.c 2003-02-28 14:53:36.000000000 +0100 +@@ -237,7 +237,7 @@ + + if(c == NULL) { + c = calloc(1, sizeof(struct udf_cache)); +- // fprintf(stderr, "calloc: %d\n", sizeof(struct udf_cache)); ++ /* fprintf(stderr, "calloc: %d\n", sizeof(struct udf_cache)); */ + if(c == NULL) { + return 0; + } +@@ -346,7 +346,7 @@ static int UDFDescriptor( uint8_t *data, uint16_t *TagID ) { *TagID = GETN2(0); @@ -117,7 +187,7 @@ return 0; } -@@ -141,7 +141,7 @@ +@@ -364,7 +364,7 @@ ad->Flags = ad->Length >> 30; ad->Length &= 0x3FFFFFFF; ad->Location = GETN4(4); @@ -126,7 +196,7 @@ return 0; } -@@ -152,7 +152,7 @@ +@@ -375,7 +375,7 @@ ad->Length &= 0x3FFFFFFF; ad->Location = GETN4(4); ad->Partition = GETN2(8); @@ -135,7 +205,7 @@ return 0; } -@@ -163,7 +163,7 @@ +@@ -386,7 +386,7 @@ ad->Length &= 0x3FFFFFFF; ad->Location = GETN4(12); ad->Partition = GETN2(16); @@ -144,7 +214,7 @@ return 0; } -@@ -194,9 +194,9 @@ +@@ -417,9 +417,9 @@ { uint32_t lbsize, MT_L, N_PM; Unicodedecode(&data[84], 128, VolumeDescriptor); @@ -157,7 +227,7 @@ if (lbsize != DVD_VIDEO_LB_LEN) return 1; return 0; } -@@ -211,10 +211,10 @@ +@@ -434,10 +434,10 @@ UDFICB( &data[ 16 ], FileType, &flags ); /* Init ad for an empty file (i.e. there isn't a AD, L_AD == 0 ) */ @@ -171,7 +241,7 @@ L_EA = GETN4( 168 ); L_AD = GETN4( 172 ); -@@ -264,7 +264,8 @@ +@@ -487,7 +487,8 @@ static int UDFMapICB( dvd_reader_t *device, struct AD ICB, uint8_t *FileType, struct Partition *partition, struct AD *File ) { @@ -180,9 +250,9 @@ + uint8_t *LogBlock = (uint8_t *)(((int)LogBlock_base & ~2047) + 2048); uint32_t lbnum; uint16_t TagID; - -@@ -296,7 +297,8 @@ - struct Partition *partition, struct AD *FileICB ) + struct icbmap tmpmap; +@@ -531,12 +532,13 @@ + int cache_file_info) { char filename[ MAX_UDF_FILE_NAME_LEN ]; - uint8_t directory[ 2 * DVD_VIDEO_LB_LEN ]; @@ -191,19 +261,48 @@ uint32_t lbnum; uint16_t TagID; uint8_t filechar; -@@ -342,7 +344,10 @@ + unsigned int p; +- uint8_t *cached_dir = NULL; ++ uint8_t *cached_dir_base = NULL, *cached_dir; + uint32_t dir_lba; + struct AD tmpICB; + int found = 0; +@@ -550,11 +552,12 @@ + + if(!GetUDFCache(device, LBUDFCache, lbnum, &cached_dir)) { + dir_lba = (Dir.Length + DVD_VIDEO_LB_LEN) / DVD_VIDEO_LB_LEN; +- if((cached_dir = malloc(dir_lba * DVD_VIDEO_LB_LEN)) == NULL) { ++ if((cached_dir_base = malloc(dir_lba * DVD_VIDEO_LB_LEN + 2048)) == NULL) { + return 0; + } ++ cached_dir = (uint8_t *)(((int)cached_dir_base & ~2047) + 2048); + if( DVDReadLBUDF( device, lbnum, dir_lba, cached_dir, 0) <= 0 ) { +- free(cached_dir); ++ free(cached_dir_base); + cached_dir = NULL; + } + /* +@@ -642,7 +645,8 @@ + static int UDFGetAVDP( dvd_reader_t *device, + struct avdp_t *avdp) + { +- uint8_t Anchor[ DVD_VIDEO_LB_LEN ]; ++ uint8_t Anchor_base[ DVD_VIDEO_LB_LEN + 2048 ]; ++ uint8_t *Anchor = (uint8_t *)(((int)Anchor_base & ~2047) + 2048); + uint32_t lbnum, MVDS_location, MVDS_length; + uint16_t TagID; + uint32_t lastsector; +@@ -713,7 +717,8 @@ static int UDFFindPartition( dvd_reader_t *device, int partnum, struct Partition *part ) { -- uint8_t LogBlock[ DVD_VIDEO_LB_LEN ], Anchor[ DVD_VIDEO_LB_LEN ]; +- uint8_t LogBlock[ DVD_VIDEO_LB_LEN ]; + uint8_t LogBlock_base[ DVD_VIDEO_LB_LEN + 2048 ]; + uint8_t *LogBlock = (uint8_t *)(((int)LogBlock_base & ~2047) + 2048); -+ uint8_t Anchor_base[ DVD_VIDEO_LB_LEN + 2048 ]; -+ uint8_t *Anchor = (uint8_t *)(((int)Anchor_base & ~2047) + 2048); uint32_t lbnum, MVDS_location, MVDS_length; uint16_t TagID; - uint32_t lastsector; -@@ -434,7 +439,8 @@ + int i, volvalid; +@@ -775,7 +780,8 @@ uint32_t UDFFindFile( dvd_reader_t *device, char *filename, uint32_t *filesize ) { @@ -213,7 +312,7 @@ uint32_t lbnum; uint16_t TagID; struct Partition partition; -@@ -460,7 +466,7 @@ +@@ -805,7 +811,7 @@ } /* File Set Descriptor */ @@ -222,18 +321,19 @@ UDFLongAD( &LogBlock[ 400 ], &RootICB ); } } while( ( lbnum < partition.Start + partition.Length ) ---- src/input/libdvdread/ifo_print.c 2002-11-27 21:56:47.000000000 +0100 -+++ src/input/libdvdread/ifo_print.c 2002-11-27 21:50:03.000000000 +0100 -@@ -25,7 +25,7 @@ - #include <ctype.h> - #include <assert.h> - --#include "config.h" // Needed for WORDS_BIGENDIAN -+#include "config.h" /* Needed for WORDS_BIGENDIAN */ - #include "ifo_types.h" - #include "ifo_read.h" - #include "ifo_print.h" -@@ -71,7 +71,7 @@ +@@ -919,7 +925,8 @@ + + static int UDFGetPVD(dvd_reader_t *device, struct pvd_t *pvd) + { +- uint8_t pvd_buf[DVD_VIDEO_LB_LEN]; ++ uint8_t pvd_buf_base[DVD_VIDEO_LB_LEN + 2048]; ++ uint8_t *pvd_buf = (uint8_t *)(((int)pvd_buf_base & ~2047) + 2048); + + if(GetUDFCache(device, PVDCache, 0, pvd)) { + return 1; +--- src/input/libdvdread/ifo_print.c 2003-02-02 03:23:53.000000000 +0100 ++++ src/input/libdvdread/ifo_print.c 2003-02-28 14:40:32.000000000 +0100 +@@ -73,7 +73,7 @@ printf("%02x ", command->bytes[i]); printf("| "); @@ -242,7 +342,7 @@ printf("\n"); } -@@ -126,19 +126,19 @@ +@@ -129,19 +129,19 @@ printf("(please send a bug report) "); } @@ -265,7 +365,7 @@ break; default: printf("(please send a bug report)"); -@@ -184,7 +184,7 @@ +@@ -198,7 +198,7 @@ if(attr->film_mode) { printf("film"); } else { @@ -274,16 +374,16 @@ } } -@@ -235,7 +235,7 @@ +@@ -251,7 +251,7 @@ switch(attr->lang_type) { case 0: - // not specified + /* not specified */ - assert(attr->lang_code == 0 || attr->lang_code == 0xffff); + CHECK_VALUE(attr->lang_code == 0 || attr->lang_code == 0xffff); break; case 1: -@@ -247,7 +247,7 @@ +@@ -264,7 +264,7 @@ switch(attr->application_mode) { case 0: @@ -292,7 +392,7 @@ break; case 1: printf("karaoke mode "); -@@ -294,19 +294,19 @@ +@@ -311,19 +311,19 @@ case 0: printf("Not specified "); break; @@ -317,16 +417,7 @@ default: printf("(please send a bug report) "); } -@@ -796,7 +796,7 @@ - - printf("Number of Countries: %i\n", ptl_mait->nr_of_countries); - printf("Number of VTSs: %i\n", ptl_mait->nr_of_vtss); -- //printf("Last byte: %i\n", ptl_mait->last_byte); -+ /* printf("Last byte: %i\n", ptl_mait->last_byte); */ - - for(i = 0; i < ptl_mait->nr_of_countries; i++) { - printf("Country code: %c%c\n", -@@ -846,7 +846,7 @@ +@@ -913,7 +913,7 @@ int i, entries; printf("Number of VOBs in this VOBS: %i\n", c_adt->nr_of_vobs); @@ -335,7 +426,7 @@ entries = (c_adt->last_byte + 1 - C_ADT_SIZE)/sizeof(c_adt_t); for(i = 0; i < entries; i++) { -@@ -996,7 +996,7 @@ +@@ -1066,7 +1066,7 @@ printf("\nText Data Manager Information\n"); printf( "-----------------------------\n"); if(ifohandle->txtdt_mgi) { @@ -344,8 +435,8 @@ } else { printf("No Text Data Manager Information present\n"); } ---- src/input/libdvdread/ifo_print.h 2002-11-27 21:56:47.000000000 +0100 -+++ src/input/libdvdread/ifo_print.h 2002-11-27 21:50:03.000000000 +0100 +--- src/input/libdvdread/ifo_print.h 2002-08-15 22:13:21.000000000 +0200 ++++ src/input/libdvdread/ifo_print.h 2003-02-28 14:12:36.000000000 +0100 @@ -20,8 +20,8 @@ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA */ @@ -357,52 +448,43 @@ #ifdef __cplusplus extern "C" { ---- src/input/libdvdread/ifo_read.c 2002-11-27 21:56:47.000000000 +0100 -+++ src/input/libdvdread/ifo_read.c 2002-11-27 21:50:03.000000000 +0100 -@@ -26,7 +26,7 @@ - - #include "dvd_reader.h" - --#include "config.h" // Needed for WORDS_BIGENDIAN -+#include "config.h" /* Needed for WORDS_BIGENDIAN */ - #include "bswap.h" - #include "ifo_types.h" - #include "ifo_read.h" -@@ -643,7 +643,7 @@ +--- src/input/libdvdread/ifo_read.c 2003-01-17 21:49:16.000000000 +0100 ++++ src/input/libdvdread/ifo_read.c 2003-02-28 14:43:40.000000000 +0100 +@@ -659,7 +659,7 @@ /* Check that time is 0:0:0:0 also if nr_of_programs == 0 */ if(pgc->nr_of_programs == 0) { CHECK_ZERO(pgc->still_time); - CHECK_ZERO(pgc->pg_playback_mode); // ?? + CHECK_ZERO(pgc->pg_playback_mode); /* ?? */ - assert(pgc->program_map_offset == 0); - assert(pgc->cell_playback_offset == 0); - assert(pgc->cell_position_offset == 0); -@@ -829,24 +829,24 @@ + CHECK_VALUE(pgc->program_map_offset == 0); + CHECK_VALUE(pgc->cell_playback_offset == 0); + CHECK_VALUE(pgc->cell_position_offset == 0); +@@ -844,24 +844,24 @@ CHECK_ZERO(tt_srpt->zero_1); - assert(tt_srpt->nr_of_srpts != 0); -- assert(tt_srpt->nr_of_srpts < 100); // ?? -+ assert(tt_srpt->nr_of_srpts < 100); /* ?? */ - assert((int)tt_srpt->nr_of_srpts * sizeof(title_info_t) <= info_length); + CHECK_VALUE(tt_srpt->nr_of_srpts != 0); +- CHECK_VALUE(tt_srpt->nr_of_srpts < 100); // ?? ++ CHECK_VALUE(tt_srpt->nr_of_srpts < 100); /* ?? */ + CHECK_VALUE((int)tt_srpt->nr_of_srpts * sizeof(title_info_t) <= info_length); for(i = 0; i < tt_srpt->nr_of_srpts; i++) { - assert(tt_srpt->title[i].pb_ty.zero_1 == 0); - assert(tt_srpt->title[i].nr_of_angles != 0); - assert(tt_srpt->title[i].nr_of_angles < 10); -- //assert(tt_srpt->title[i].nr_of_ptts != 0); + CHECK_VALUE(tt_srpt->title[i].pb_ty.zero_1 == 0); + CHECK_VALUE(tt_srpt->title[i].nr_of_angles != 0); + CHECK_VALUE(tt_srpt->title[i].nr_of_angles < 10); +- //CHECK_VALUE(tt_srpt->title[i].nr_of_ptts != 0); - // XXX: this assertion breaks Ghostbusters: -- assert(tt_srpt->title[i].nr_of_ptts < 1000); // ?? -+ /* assert(tt_srpt->title[i].nr_of_ptts != 0); */ +- CHECK_VALUE(tt_srpt->title[i].nr_of_ptts < 1000); // ?? ++ /* CHECK_VALUE(tt_srpt->title[i].nr_of_ptts != 0); */ + /* XXX: this assertion breaks Ghostbusters: */ -+ assert(tt_srpt->title[i].nr_of_ptts < 1000); /* ?? */ - assert(tt_srpt->title[i].title_set_nr != 0); -- assert(tt_srpt->title[i].title_set_nr < 100); // ?? -+ assert(tt_srpt->title[i].title_set_nr < 100); /* ?? */ - assert(tt_srpt->title[i].vts_ttn != 0); -- assert(tt_srpt->title[i].vts_ttn < 100); // ?? -- //assert(tt_srpt->title[i].title_set_sector != 0); -+ assert(tt_srpt->title[i].vts_ttn < 100); /* ?? */ -+ /* assert(tt_srpt->title[i].title_set_sector != 0); */ ++ CHECK_VALUE(tt_srpt->title[i].nr_of_ptts < 1000); /* ?? */ + CHECK_VALUE(tt_srpt->title[i].title_set_nr != 0); +- CHECK_VALUE(tt_srpt->title[i].title_set_nr < 100); // ?? ++ CHECK_VALUE(tt_srpt->title[i].title_set_nr < 100); /* ?? */ + CHECK_VALUE(tt_srpt->title[i].vts_ttn != 0); +- CHECK_VALUE(tt_srpt->title[i].vts_ttn < 100); // ?? +- //CHECK_VALUE(tt_srpt->title[i].title_set_sector != 0); ++ CHECK_VALUE(tt_srpt->title[i].vts_ttn < 100); /* ?? */ ++ /* CHECK_VALUE(tt_srpt->title[i].title_set_sector != 0); */ } - // Make this a function @@ -410,74 +492,71 @@ #if 0 if(memcmp((uint8_t *)tt_srpt->title + tt_srpt->nr_of_srpts * sizeof(title_info_t), -@@ -910,7 +910,7 @@ +@@ -925,7 +925,7 @@ CHECK_ZERO(vts_ptt_srpt->zero_1); - assert(vts_ptt_srpt->nr_of_srpts != 0); -- assert(vts_ptt_srpt->nr_of_srpts < 100); // ?? -+ assert(vts_ptt_srpt->nr_of_srpts < 100); /* ?? */ + CHECK_VALUE(vts_ptt_srpt->nr_of_srpts != 0); +- CHECK_VALUE(vts_ptt_srpt->nr_of_srpts < 100); // ?? ++ CHECK_VALUE(vts_ptt_srpt->nr_of_srpts < 100); /* ?? */ info_length = vts_ptt_srpt->last_byte + 1 - VTS_PTT_SRPT_SIZE; -@@ -985,12 +985,12 @@ +@@ -1001,12 +1001,12 @@ } for(i = 0; i < vts_ptt_srpt->nr_of_srpts; i++) { -- assert(vts_ptt_srpt->title[i].nr_of_ptts < 1000); // ?? -+ assert(vts_ptt_srpt->title[i].nr_of_ptts < 1000); /* ?? */ +- CHECK_VALUE(vts_ptt_srpt->title[i].nr_of_ptts < 1000); // ?? ++ CHECK_VALUE(vts_ptt_srpt->title[i].nr_of_ptts < 1000); /* ?? */ for(j = 0; j < vts_ptt_srpt->title[i].nr_of_ptts; j++) { - assert(vts_ptt_srpt->title[i].ptt[j].pgcn != 0 ); -- assert(vts_ptt_srpt->title[i].ptt[j].pgcn < 1000); // ?? -+ assert(vts_ptt_srpt->title[i].ptt[j].pgcn < 1000); /* ?? */ - assert(vts_ptt_srpt->title[i].ptt[j].pgn != 0); -- assert(vts_ptt_srpt->title[i].ptt[j].pgn < 100); // ?? -+ assert(vts_ptt_srpt->title[i].ptt[j].pgn < 100); /* ?? */ + CHECK_VALUE(vts_ptt_srpt->title[i].ptt[j].pgcn != 0 ); +- CHECK_VALUE(vts_ptt_srpt->title[i].ptt[j].pgcn < 1000); // ?? ++ CHECK_VALUE(vts_ptt_srpt->title[i].ptt[j].pgcn < 1000); /* ?? */ + CHECK_VALUE(vts_ptt_srpt->title[i].ptt[j].pgn != 0); +- CHECK_VALUE(vts_ptt_srpt->title[i].ptt[j].pgn < 100); // ?? ++ CHECK_VALUE(vts_ptt_srpt->title[i].ptt[j].pgn < 100); /* ?? */ } } -@@ -1049,9 +1049,9 @@ - info_length = ptl_mait->last_byte + 1 - PTL_MAIT_SIZE; +@@ -1064,9 +1064,9 @@ + B2N_32(ptl_mait->last_byte); - assert(ptl_mait->nr_of_countries != 0); -- assert(ptl_mait->nr_of_countries < 100); // ?? -+ assert(ptl_mait->nr_of_countries < 100); /* ?? */ - assert(ptl_mait->nr_of_vtss != 0); -- assert(ptl_mait->nr_of_vtss < 100); // ?? -+ assert(ptl_mait->nr_of_vtss < 100); /* ?? */ - assert(ptl_mait->nr_of_countries * PTL_MAIT_COUNTRY_SIZE <= info_length); + CHECK_VALUE(ptl_mait->nr_of_countries != 0); +- CHECK_VALUE(ptl_mait->nr_of_countries < 100); // ?? ++ CHECK_VALUE(ptl_mait->nr_of_countries < 100); /* ?? */ + CHECK_VALUE(ptl_mait->nr_of_vtss != 0); +- CHECK_VALUE(ptl_mait->nr_of_vtss < 100); // ?? ++ CHECK_VALUE(ptl_mait->nr_of_vtss < 100); /* ?? */ + CHECK_VALUE(ptl_mait->nr_of_countries * PTL_MAIT_COUNTRY_SIZE + <= ptl_mait->last_byte + 1 - PTL_MAIT_SIZE); - /* Change this to read and 'translate' the tables too. -@@ -1519,7 +1519,7 @@ +@@ -1605,7 +1605,7 @@ /* assert(pgcit->nr_of_pgci_srp != 0); Magic Knight Rayearth Daybreak is mastered very strange and has Titles with 0 PTTs. */ -- assert(pgcit->nr_of_pgci_srp < 10000); // ?? seen max of 1338 -+ assert(pgcit->nr_of_pgci_srp < 10000); /* ?? seen max of 1338 */ +- CHECK_VALUE(pgcit->nr_of_pgci_srp < 10000); // ?? seen max of 1338 ++ CHECK_VALUE(pgcit->nr_of_pgci_srp < 10000); /* ?? seen max of 1338 */ info_length = pgcit->nr_of_pgci_srp * PGCI_SRP_SIZE; data = malloc(info_length); -@@ -1640,7 +1640,7 @@ +@@ -1726,7 +1726,7 @@ CHECK_ZERO(pgci_ut->zero_1); - assert(pgci_ut->nr_of_lus != 0); -- assert(pgci_ut->nr_of_lus < 100); // ?? 3-4 ? -+ assert(pgci_ut->nr_of_lus < 100); /* ?? 3-4 ? */ - assert((uint32_t)pgci_ut->nr_of_lus * PGCI_LU_SIZE < pgci_ut->last_byte); + CHECK_VALUE(pgci_ut->nr_of_lus != 0); +- CHECK_VALUE(pgci_ut->nr_of_lus < 100); // ?? 3-4 ? ++ CHECK_VALUE(pgci_ut->nr_of_lus < 100); /* ?? 3-4 ? */ + CHECK_VALUE((uint32_t)pgci_ut->nr_of_lus * PGCI_LU_SIZE < pgci_ut->last_byte); info_length = pgci_ut->nr_of_lus * PGCI_LU_SIZE; -@@ -1675,8 +1675,9 @@ +@@ -1760,7 +1760,7 @@ + free(data); for(i = 0; i < pgci_ut->nr_of_lus; i++) { - CHECK_ZERO(pgci_ut->lu[i].zero_1); - // Maybe this is only defined for v1.1 and later titles? -- /* If the bits in 'lu[i].exists' are enumerated abcd efgh then: -+ /* -+ Maybe this is only defined for v1.1 and later titles? -+ If the bits in 'lu[i].exists' are enumerated abcd efgh then: ++ /* Maybe this is only defined for v1.1 and later titles? */ + /* If the bits in 'lu[i].exists' are enumerated abcd efgh then: VTS_x_yy.IFO VIDEO_TS.IFO a == 0x83 "Root" 0x82 "Title" - b == 0x84 "Subpicture" -@@ -1714,8 +1715,10 @@ +@@ -1799,8 +1799,10 @@ ifofile->pgci_ut = 0; return 0; } @@ -490,9 +569,9 @@ } return 1; -@@ -1776,8 +1779,8 @@ +@@ -1861,8 +1863,8 @@ unsigned int nr_coded; - assert(vts_attributes->last_byte + 1 >= VTS_ATTRIBUTES_MIN_SIZE); + CHECK_VALUE(vts_attributes->last_byte + 1 >= VTS_ATTRIBUTES_MIN_SIZE); nr_coded = (vts_attributes->last_byte + 1 - VTS_ATTRIBUTES_MIN_SIZE)/6; - // This is often nr_coded = 70, how do you know how many there really are? - if(nr_coded > 32) { // We haven't read more from disk/file anyway @@ -500,29 +579,29 @@ + if(nr_coded > 32) { /* We haven't read more from disk/file anyway */ nr_coded = 32; } - assert(vts_attributes->nr_of_vtstt_subp_streams <= nr_coded); -@@ -1825,7 +1828,7 @@ + CHECK_VALUE(vts_attributes->nr_of_vtstt_subp_streams <= nr_coded); +@@ -1910,7 +1912,7 @@ CHECK_ZERO(vts_atrt->zero_1); - assert(vts_atrt->nr_of_vtss != 0); -- assert(vts_atrt->nr_of_vtss < 100); //?? -+ assert(vts_atrt->nr_of_vtss < 100); /* ?? */ - assert((uint32_t)vts_atrt->nr_of_vtss * (4 + VTS_ATTRIBUTES_MIN_SIZE) + + CHECK_VALUE(vts_atrt->nr_of_vtss != 0); +- CHECK_VALUE(vts_atrt->nr_of_vtss < 100); //?? ++ CHECK_VALUE(vts_atrt->nr_of_vtss < 100); /* ?? */ + CHECK_VALUE((uint32_t)vts_atrt->nr_of_vtss * (4 + VTS_ATTRIBUTES_MIN_SIZE) + VTS_ATRT_SIZE < vts_atrt->last_byte + 1); -@@ -1866,9 +1869,9 @@ +@@ -1954,9 +1956,9 @@ return 0; } - // This assert cant be in ifoRead_VTS_ATTRIBUTES + /* This assert cant be in ifoRead_VTS_ATTRIBUTES */ - assert(offset + vts_atrt->vts[i].last_byte <= vts_atrt->last_byte + 1); + CHECK_VALUE(offset + vts_atrt->vts[i].last_byte <= vts_atrt->last_byte + 1); - // Is this check correct? + /* Is this check correct? */ } - free(data); -@@ -1918,7 +1921,7 @@ + return 1; +@@ -2006,7 +2008,7 @@ return 0; } @@ -531,8 +610,8 @@ return 1; } ---- src/input/libdvdread/ifo_read.h 2002-11-27 21:56:47.000000000 +0100 -+++ src/input/libdvdread/ifo_read.h 2002-11-27 21:50:03.000000000 +0100 +--- src/input/libdvdread/ifo_read.h 2002-12-15 01:09:12.000000000 +0100 ++++ src/input/libdvdread/ifo_read.h 2003-02-28 14:12:36.000000000 +0100 @@ -20,8 +20,8 @@ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA */ @@ -544,9 +623,8 @@ #ifdef __cplusplus extern "C" { -diff -urN libdvdread.cvs/ifo_types.h libdvdread.new/ifo_types.h ---- src/input/libdvdread/ifo_types.h 2002-11-27 21:56:47.000000000 +0100 -+++ src/input/libdvdread/ifo_types.h 2002-11-27 21:50:03.000000000 +0100 +--- src/input/libdvdread/ifo_types.h 2003-02-22 22:42:11.000000000 +0100 ++++ src/input/libdvdread/ifo_types.h 2003-02-28 14:12:36.000000000 +0100 @@ -21,7 +21,7 @@ */ @@ -556,263 +634,19 @@ diff -urN libdvdread.cvs/ifo_types.h libdvdread.new/ifo_types.h #undef ATTRIBUTE_PACKED -@@ -59,7 +59,7 @@ - uint8_t hour; - uint8_t minute; - uint8_t second; -- uint8_t frame_u; // The two high bits are the frame rate. -+ uint8_t frame_u; /* The two high bits are the frame rate. */ - } ATTRIBUTE_PACKED dvd_time_t; - - /** -@@ -130,7 +130,7 @@ - unsigned int quantization : 2; - #endif - uint16_t lang_code; -- uint8_t lang_code2; // ?? -+ uint8_t lang_code2; /* ?? */ - uint8_t lang_extension; - uint16_t unknown2; - } ATTRIBUTE_PACKED audio_attr_t; -@@ -235,65 +235,65 @@ - */ - typedef struct { - #ifdef WORDS_BIGENDIAN -- unsigned int zero : 7; // 25-31 -- unsigned int video_pres_mode_change : 1; // 24 -- -- unsigned int karaoke_audio_pres_mode_change : 1; // 23 -- unsigned int angle_change : 1; // 22 -- unsigned int subpic_stream_change : 1; // 21 -- unsigned int audio_stream_change : 1; // 20 -- unsigned int pause_on : 1; // 19 -- unsigned int still_off : 1; // 18 -- unsigned int button_select_or_activate : 1; // 17 -- unsigned int resume : 1; // 16 -- -- unsigned int chapter_menu_call : 1; // 15 -- unsigned int angle_menu_call : 1; // 14 -- unsigned int audio_menu_call : 1; // 13 -- unsigned int subpic_menu_call : 1; // 12 -- unsigned int root_menu_call : 1; // 11 -- unsigned int title_menu_call : 1; // 10 -- unsigned int backward_scan : 1; // 9 -- unsigned int forward_scan : 1; // 8 -- -- unsigned int next_pg_search : 1; // 7 -- unsigned int prev_or_top_pg_search : 1; // 6 -- unsigned int time_or_chapter_search : 1; // 5 -- unsigned int go_up : 1; // 4 -- unsigned int stop : 1; // 3 -- unsigned int title_play : 1; // 2 -- unsigned int chapter_search_or_play : 1; // 1 -- unsigned int title_or_time_play : 1; // 0 -+ unsigned int zero : 7; /* 25-31 */ -+ unsigned int video_pres_mode_change : 1; /* 24 */ -+ -+ unsigned int karaoke_audio_pres_mode_change : 1; /* 23 */ -+ unsigned int angle_change : 1; /* 22 */ -+ unsigned int subpic_stream_change : 1; /* 21 */ -+ unsigned int audio_stream_change : 1; /* 20 */ -+ unsigned int pause_on : 1; /* 19 */ -+ unsigned int still_off : 1; /* 18 */ -+ unsigned int button_select_or_activate : 1; /* 17 */ -+ unsigned int resume : 1; /* 16 */ -+ -+ unsigned int chapter_menu_call : 1; /* 15 */ -+ unsigned int angle_menu_call : 1; /* 14 */ -+ unsigned int audio_menu_call : 1; /* 13 */ -+ unsigned int subpic_menu_call : 1; /* 12 */ -+ unsigned int root_menu_call : 1; /* 11 */ -+ unsigned int title_menu_call : 1; /* 10 */ -+ unsigned int backward_scan : 1; /* 9 */ -+ unsigned int forward_scan : 1; /* 8 */ -+ -+ unsigned int next_pg_search : 1; /* 7 */ -+ unsigned int prev_or_top_pg_search : 1; /* 6 */ -+ unsigned int time_or_chapter_search : 1; /* 5 */ -+ unsigned int go_up : 1; /* 4 */ -+ unsigned int stop : 1; /* 3 */ -+ unsigned int title_play : 1; /* 2 */ -+ unsigned int chapter_search_or_play : 1; /* 1 */ -+ unsigned int title_or_time_play : 1; /* 0 */ - #else -- unsigned int video_pres_mode_change : 1; // 24 -- unsigned int zero : 7; // 25-31 -- -- unsigned int resume : 1; // 16 -- unsigned int button_select_or_activate : 1; // 17 -- unsigned int still_off : 1; // 18 -- unsigned int pause_on : 1; // 19 -- unsigned int audio_stream_change : 1; // 20 -- unsigned int subpic_stream_change : 1; // 21 -- unsigned int angle_change : 1; // 22 -- unsigned int karaoke_audio_pres_mode_change : 1; // 23 -- -- unsigned int forward_scan : 1; // 8 -- unsigned int backward_scan : 1; // 9 -- unsigned int title_menu_call : 1; // 10 -- unsigned int root_menu_call : 1; // 11 -- unsigned int subpic_menu_call : 1; // 12 -- unsigned int audio_menu_call : 1; // 13 -- unsigned int angle_menu_call : 1; // 14 -- unsigned int chapter_menu_call : 1; // 15 -- -- unsigned int title_or_time_play : 1; // 0 -- unsigned int chapter_search_or_play : 1; // 1 -- unsigned int title_play : 1; // 2 -- unsigned int stop : 1; // 3 -- unsigned int go_up : 1; // 4 -- unsigned int time_or_chapter_search : 1; // 5 -- unsigned int prev_or_top_pg_search : 1; // 6 -- unsigned int next_pg_search : 1; // 7 -+ unsigned int video_pres_mode_change : 1; /* 24 */ -+ unsigned int zero : 7; /* 25-31 */ -+ -+ unsigned int resume : 1; /* 16 */ -+ unsigned int button_select_or_activate : 1; /* 17 */ -+ unsigned int still_off : 1; /* 18 */ -+ unsigned int pause_on : 1; /* 19 */ -+ unsigned int audio_stream_change : 1; /* 20 */ -+ unsigned int subpic_stream_change : 1; /* 21 */ -+ unsigned int angle_change : 1; /* 22 */ -+ unsigned int karaoke_audio_pres_mode_change : 1; /* 23 */ -+ -+ unsigned int forward_scan : 1; /* 8 */ -+ unsigned int backward_scan : 1; /* 9 */ -+ unsigned int title_menu_call : 1; /* 10 */ -+ unsigned int root_menu_call : 1; /* 11 */ -+ unsigned int subpic_menu_call : 1; /* 12 */ -+ unsigned int audio_menu_call : 1; /* 13 */ -+ unsigned int angle_menu_call : 1; /* 14 */ -+ unsigned int chapter_menu_call : 1; /* 15 */ -+ -+ unsigned int title_or_time_play : 1; /* 0 */ -+ unsigned int chapter_search_or_play : 1; /* 1 */ -+ unsigned int title_play : 1; /* 2 */ -+ unsigned int stop : 1; /* 3 */ -+ unsigned int go_up : 1; /* 4 */ -+ unsigned int time_or_chapter_search : 1; /* 5 */ -+ unsigned int prev_or_top_pg_search : 1; /* 6 */ -+ unsigned int next_pg_search : 1; /* 7 */ - #endif - } ATTRIBUTE_PACKED user_ops_t; - -@@ -453,11 +453,11 @@ - - video_attr_t vmgm_video_attr; - uint8_t zero_7; -- uint8_t nr_of_vmgm_audio_streams; // should be 0 or 1 -+ uint8_t nr_of_vmgm_audio_streams; /* should be 0 or 1 */ - audio_attr_t vmgm_audio_attr; - audio_attr_t zero_8[7]; - uint8_t zero_9[17]; -- uint8_t nr_of_vmgm_subp_streams; // should be 0 or 1 -+ uint8_t nr_of_vmgm_subp_streams; /* should be 0 or 1 */ - subp_attr_t vmgm_subp_attr; - subp_attr_t zero_10[27]; /* XXX: how much 'padding' here? */ - } ATTRIBUTE_PACKED vmgi_mat_t; -@@ -465,21 +465,21 @@ - typedef struct { - #ifdef WORDS_BIGENDIAN - unsigned int zero_1 : 1; -- unsigned int multi_or_random_pgc_title : 1; // 0 == one sequential pgc title -+ unsigned int multi_or_random_pgc_title : 1; /* 0 == one sequential pgc title */ - unsigned int jlc_exists_in_cell_cmd : 1; - unsigned int jlc_exists_in_prepost_cmd : 1; - unsigned int jlc_exists_in_button_cmd : 1; - unsigned int jlc_exists_in_tt_dom : 1; -- unsigned int chapter_search_or_play : 1; // UOP 1 -- unsigned int title_or_time_play : 1; // UOP 0 -+ unsigned int chapter_search_or_play : 1; /* UOP 1 */ -+ unsigned int title_or_time_play : 1; /* UOP 0 */ - #else -- unsigned int title_or_time_play : 1; // UOP 0 -- unsigned int chapter_search_or_play : 1; // UOP 1 -+ unsigned int title_or_time_play : 1; /* UOP 0 */ -+ unsigned int chapter_search_or_play : 1; /* UOP 1 */ - unsigned int jlc_exists_in_tt_dom : 1; - unsigned int jlc_exists_in_button_cmd : 1; - unsigned int jlc_exists_in_prepost_cmd : 1; - unsigned int jlc_exists_in_cell_cmd : 1; -- unsigned int multi_or_random_pgc_title : 1; // 0 == one sequential pgc title -+ unsigned int multi_or_random_pgc_title : 1; /* 0 == one sequential pgc title */ - unsigned int zero_1 : 1; - #endif - } ATTRIBUTE_PACKED playback_type_t; -@@ -540,12 +540,12 @@ - - video_attr_t vtsm_vobs_attr; - uint8_t zero_1; -- uint8_t nr_of_vtsm_audio_streams; // should be 0 or 1 -+ uint8_t nr_of_vtsm_audio_streams; /* should be 0 or 1 */ - audio_attr_t vtsm_audio_attr; - audio_attr_t zero_2[7]; - uint8_t zero_3[16]; - uint8_t zero_4; -- uint8_t nr_of_vtsm_subp_streams; // should be 0 or 1 -+ uint8_t nr_of_vtsm_subp_streams; /* should be 0 or 1 */ - subp_attr_t vtsm_subp_attr; - subp_attr_t zero_5[27]; - -@@ -581,18 +581,18 @@ - uint32_t last_byte; /* offsets are relative here */ - uint16_t offsets[100]; /* == nr_of_srpts + 1 (first is disc title) */ - #if 0 -- uint16_t unknown; // 0x48 ?? 0x48 words (16bit) info following -+ uint16_t unknown; /* 0x48 ?? 0x48 words (16bit) info following */ - uint16_t zero_1; - -- uint8_t type_of_info;//?? 01 == disc, 02 == Title, 04 == Title part -+ uint8_t type_of_info; /* ?? 01 == disc, 02 == Title, 04 == Title part */ - uint8_t unknown1; - uint8_t unknown2; - uint8_t unknown3; -- uint8_t unknown4;//?? allways 0x30 language?, text format? -+ uint8_t unknown4; /*?? allways 0x30 language?, text format? */ - uint8_t unknown5; -- uint16_t offset; // from first -+ uint16_t offset; /* from first */ - -- char text[12]; // ended by 0x09 -+ char text[12]; /* ended by 0x09 */ +--- src/input/libdvdread/md5.c 2003-01-12 01:46:16.000000000 +0100 ++++ src/input/libdvdread/md5.c 2003-02-28 14:53:15.000000000 +0100 +@@ -36,7 +36,7 @@ #endif - } ATTRIBUTE_PACKED txtdt_t; - -@@ -652,7 +652,7 @@ - uint32_t vts_ptt_srpt; /* sector */ - uint32_t vts_pgcit; /* sector */ - uint32_t vtsm_pgci_ut; /* sector */ -- uint32_t vts_tmapt; /* sector */ // XXX: FIXME TODO Implement -+ uint32_t vts_tmapt; /* sector */ /* XXX: FIXME TODO Implement */ - uint32_t vtsm_c_adt; /* sector */ - uint32_t vtsm_vobu_admap; /* sector */ - uint32_t vts_c_adt; /* sector */ -@@ -661,11 +661,11 @@ - - video_attr_t vtsm_video_attr; - uint8_t zero_14; -- uint8_t nr_of_vtsm_audio_streams; // should be 0 or 1 -+ uint8_t nr_of_vtsm_audio_streams; /* should be 0 or 1 */ - audio_attr_t vtsm_audio_attr; - audio_attr_t zero_15[7]; - uint8_t zero_16[17]; -- uint8_t nr_of_vtsm_subp_streams; // should be 0 or 1 -+ uint8_t nr_of_vtsm_subp_streams; /* should be 0 or 1 */ - subp_attr_t vtsm_subp_attr; - subp_attr_t zero_17[27]; - uint8_t zero_18[2]; ---- src/input/libdvdread/nav_print.c 2002-11-27 21:56:47.000000000 +0100 -+++ src/input/libdvdread/nav_print.c 2002-11-27 21:50:03.000000000 +0100 -@@ -27,7 +27,7 @@ - #include <inttypes.h> - #include <assert.h> --#include "config.h" // Needed for WORDS_BIGENDIAN -+#include "config.h" /* Needed for WORDS_BIGENDIAN */ - #include "nav_types.h" - #include "nav_print.h" + #include "md5.h" +-//#include "unlocked-io.h" ++/* #include "unlocked-io.h" */ + #ifdef _LIBC + # include <endian.h> +--- src/input/libdvdread/nav_print.c 2003-01-07 21:58:15.000000000 +0100 ++++ src/input/libdvdread/nav_print.c 2003-02-28 14:12:36.000000000 +0100 @@ -167,7 +167,7 @@ printf("left %d, ", btni->left); printf("right %d\n", btni->right); @@ -822,8 +656,8 @@ diff -urN libdvdread.cvs/ifo_types.h libdvdread.new/ifo_types.h printf("\n"); } } ---- src/input/libdvdread/nav_print.h 2002-11-27 21:56:47.000000000 +0100 -+++ src/input/libdvdread/nav_print.h 2002-11-27 21:50:03.000000000 +0100 +--- src/input/libdvdread/nav_print.h 2002-07-26 23:20:28.000000000 +0200 ++++ src/input/libdvdread/nav_print.h 2003-02-28 14:12:36.000000000 +0100 @@ -20,7 +20,7 @@ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA */ @@ -833,90 +667,46 @@ diff -urN libdvdread.cvs/ifo_types.h libdvdread.new/ifo_types.h /** * Pretty printing of the NAV packets, PCI and DSI structs. ---- src/input/libdvdread/nav_read.c 2002-11-27 21:56:47.000000000 +0100 -+++ src/input/libdvdread/nav_read.c 2002-11-27 21:50:03.000000000 +0100 -@@ -21,15 +21,19 @@ - #include <inttypes.h> - #include <assert.h> - --#include "config.h" // Needed for WORDS_BIGENDIAN -+#include "config.h" /* Needed for WORDS_BIGENDIAN */ - #include "bswap.h" - #include "nav_types.h" - #include "nav_read.h" - -+/* -+#define STRICT -+*/ -+ +--- src/input/libdvdread/nav_read.c 2003-01-07 21:58:15.000000000 +0100 ++++ src/input/libdvdread/nav_read.c 2003-02-28 14:49:04.000000000 +0100 +@@ -30,7 +30,7 @@ void navRead_PCI(pci_t *pci, unsigned char *buffer) { -- int i, j, k; -+ int i, j; + int i, j; -- assert(sizeof(pci_t) == PCI_BYTES - 1); // -1 for substream id -+ assert(sizeof(pci_t) == PCI_BYTES - 1); /* -1 for substream id */ +- CHECK_VALUE(sizeof(pci_t) == PCI_BYTES - 1); // -1 for substream id ++ CHECK_VALUE(sizeof(pci_t) == PCI_BYTES - 1); /* -1 for substream id */ memcpy(pci, buffer, sizeof(pci_t)); -@@ -71,6 +75,7 @@ - #endif - - -+#ifdef STRICT - /* Asserts */ - - /* pci pci gi */ -@@ -95,6 +100,7 @@ - /* pci hli btnit */ - for(i = 0; i < pci->hli.hl_gi.btngr_ns; i++) { - for(j = 0; j < (36 / pci->hli.hl_gi.btngr_ns); j++) { -+ int k; - int n = (36 / pci->hli.hl_gi.btngr_ns) * i + j; - assert(pci->hli.btnit[n].zero1 == 0); - assert(pci->hli.btnit[n].zero2 == 0); -@@ -110,7 +116,7 @@ - assert(pci->hli.btnit[n].down <= pci->hli.hl_gi.btn_ns); - assert(pci->hli.btnit[n].left <= pci->hli.hl_gi.btn_ns); - assert(pci->hli.btnit[n].right <= pci->hli.hl_gi.btn_ns); +@@ -126,7 +126,7 @@ + CHECK_VALUE(pci->hli.btnit[n].down <= pci->hli.hl_gi.btn_ns); + CHECK_VALUE(pci->hli.btnit[n].left <= pci->hli.hl_gi.btn_ns); + CHECK_VALUE(pci->hli.btnit[n].right <= pci->hli.hl_gi.btn_ns); - //vmcmd_verify(pci->hli.btnit[n].cmd); -+ /* vmcmd_verify(pci->hli.btnit[n].cmd); */ ++ /*vmcmd_verify(pci->hli.btnit[n].cmd);*/ } else { - assert(pci->hli.btnit[n].btn_coln == 0); - assert(pci->hli.btnit[n].auto_action_mode == 0); -@@ -123,16 +129,17 @@ - assert(pci->hli.btnit[n].left == 0); - assert(pci->hli.btnit[n].right == 0); + int k; + CHECK_VALUE(pci->hli.btnit[n].btn_coln == 0); +@@ -140,7 +140,7 @@ + CHECK_VALUE(pci->hli.btnit[n].left == 0); + CHECK_VALUE(pci->hli.btnit[n].right == 0); for (k = 0; k < 8; k++) -- assert(pci->hli.btnit[n].cmd.bytes[k] == 0); //CHECK_ZERO? -+ assert(pci->hli.btnit[n].cmd.bytes[k] == 0); /* CHECK_ZERO? */ +- CHECK_VALUE(pci->hli.btnit[n].cmd.bytes[k] == 0); //CHECK_ZERO? ++ CHECK_VALUE(pci->hli.btnit[n].cmd.bytes[k] == 0); /* CHECK_ZERO? */ } } } -+#endif - } - +@@ -150,7 +150,7 @@ void navRead_DSI(dsi_t *dsi, unsigned char *buffer) { int i; -- assert(sizeof(dsi_t) == DSI_BYTES - 1); // -1 for substream id -+ assert(sizeof(dsi_t) == DSI_BYTES - 1); /* -1 for substream id */ +- CHECK_VALUE(sizeof(dsi_t) == DSI_BYTES - 1); // -1 for substream id ++ CHECK_VALUE(sizeof(dsi_t) == DSI_BYTES - 1); /* -1 for substream id */ memcpy(dsi, buffer, sizeof(dsi_t)); -@@ -178,9 +185,11 @@ - B2N_32(dsi->synci.sp_synca[i]); - - -+#ifdef STRICT - /* Asserts */ - - /* dsi dsi gi */ - assert(dsi->dsi_gi.zero1 == 0); -+#endif - } - ---- src/input/libdvdread/nav_read.h 2002-11-27 21:56:47.000000000 +0100 -+++ src/input/libdvdread/nav_read.h 2002-11-27 21:50:03.000000000 +0100 +--- src/input/libdvdread/nav_read.h 2002-07-26 23:04:05.000000000 +0200 ++++ src/input/libdvdread/nav_read.h 2003-02-28 14:12:36.000000000 +0100 @@ -19,7 +19,7 @@ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA */ @@ -926,8 +716,8 @@ diff -urN libdvdread.cvs/ifo_types.h libdvdread.new/ifo_types.h /** * Parsing of NAV data, PCI and DSI parts. ---- src/input/libdvdread/nav_types.h 2002-11-27 21:56:47.000000000 +0100 -+++ src/input/libdvdread/nav_types.h 2002-11-27 21:55:06.000000000 +0100 +--- src/input/libdvdread/nav_types.h 2003-01-02 21:11:06.000000000 +0100 ++++ src/input/libdvdread/nav_types.h 2003-02-28 14:12:36.000000000 +0100 @@ -30,7 +30,7 @@ */ diff --git a/src/input/libdvdread/dvd_input.c b/src/input/libdvdread/dvd_input.c index d1782500f..ba1cb4c02 100644 --- a/src/input/libdvdread/dvd_input.c +++ b/src/input/libdvdread/dvd_input.c @@ -17,33 +17,44 @@ * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111, USA. */ +#include "config.h" + #include <stdio.h> #include <stdlib.h> #include <fcntl.h> #include <unistd.h> -#include <dlfcn.h> #include "dvd_reader.h" #include "dvd_input.h" /* The function pointers that is the exported interface of this file. */ -dvd_input_t (*DVDinput_open) (const char *); -int (*DVDinput_close) (dvd_input_t); -int (*DVDinput_seek) (dvd_input_t, int); -int (*DVDinput_title) (dvd_input_t, int); -int (*DVDinput_read) (dvd_input_t, void *, int, int); -char * (*DVDinput_error) (dvd_input_t); - -/* For libdvdcss */ +dvd_input_t (*dvdinput_open) (const char *); +int (*dvdinput_close) (dvd_input_t); +int (*dvdinput_seek) (dvd_input_t, int); +int (*dvdinput_title) (dvd_input_t, int); +int (*dvdinput_read) (dvd_input_t, void *, int, int); +char * (*dvdinput_error) (dvd_input_t); + +#ifdef HAVE_DVDCSS_DVDCSS_H +/* linking to libdvdcss */ +#include <dvdcss/dvdcss.h> +#define DVDcss_open(a) dvdcss_open((char*)(a)) +#define DVDcss_close dvdcss_close +#define DVDcss_seek dvdcss_seek +#define DVDcss_title dvdcss_title +#define DVDcss_read dvdcss_read +#define DVDcss_error dvdcss_error +#else +/* dlopening libdvdcss */ +#include <dlfcn.h> typedef struct dvdcss_s *dvdcss_handle; - -dvdcss_handle (*DVDcss_open) (const char *); -int (*DVDcss_close) (dvdcss_handle); -int (*DVDcss_seek) (dvdcss_handle, int, int); -int (*DVDcss_title) (dvdcss_handle, int); -int (*DVDcss_read) (dvdcss_handle, void *, int, int); -char * (*DVDcss_error) (dvdcss_handle); - +static dvdcss_handle (*DVDcss_open) (const char *); +static int (*DVDcss_close) (dvdcss_handle); +static int (*DVDcss_seek) (dvdcss_handle, int, int); +static int (*DVDcss_title) (dvdcss_handle, int); +static int (*DVDcss_read) (dvdcss_handle, void *, int, int); +static char * (*DVDcss_error) (dvdcss_handle); +#endif /* The DVDinput handle, add stuff here for new input methods. */ struct dvd_input_s { @@ -72,7 +83,7 @@ static dvd_input_t css_open(const char *target) /* Really open it with libdvdcss */ dev->dvdcss = DVDcss_open(target); if(dev->dvdcss == 0) { - fprintf(stderr, "libdvdread: Could not open device with libdvdcss.\n"); + fprintf(stderr, "libdvdread: Could not open %s with libdvdcss.\n", target); free(dev); return NULL; } @@ -250,11 +261,19 @@ static int file_close(dvd_input_t dev) /** * Setup read functions with either libdvdcss or minimal DVD access. */ -int DVDInputSetup(void) +int dvdinput_setup(void) { void *dvdcss_library = NULL; char **dvdcss_version = NULL; - + +#ifdef HAVE_DVDCSS_DVDCSS_H + /* linking to libdvdcss */ + dvdcss_library = &dvdcss_library; /* Give it some value != NULL */ + /* the DVDcss_* functions have been #defined at the top */ + dvdcss_version = &dvdcss_interface_2; + +#else + /* dlopening libdvdcss */ dvdcss_library = dlopen("libdvdcss.so.2", RTLD_LAZY); if(dvdcss_library != NULL) { @@ -292,6 +311,7 @@ int DVDInputSetup(void) dlclose(dvdcss_library); } } +#endif /* HAVE_DVDCSS_DVDCSS_H */ if(dvdcss_library != NULL) { /* @@ -303,25 +323,25 @@ int DVDInputSetup(void) fprintf(stderr, "libdvdread: Using libdvdcss version %s for DVD access\n", *dvdcss_version); - /* libdvdcss wraper functions */ - DVDinput_open = css_open; - DVDinput_close = css_close; - DVDinput_seek = css_seek; - DVDinput_title = css_title; - DVDinput_read = css_read; - DVDinput_error = css_error; + /* libdvdcss wrapper functions */ + dvdinput_open = css_open; + dvdinput_close = css_close; + dvdinput_seek = css_seek; + dvdinput_title = css_title; + dvdinput_read = css_read; + dvdinput_error = css_error; return 1; } else { fprintf(stderr, "libdvdread: Encrypted DVD support unavailable.\n"); /* libdvdcss replacement functions */ - DVDinput_open = file_open; - DVDinput_close = file_close; - DVDinput_seek = file_seek; - DVDinput_title = file_title; - DVDinput_read = file_read; - DVDinput_error = file_error; + dvdinput_open = file_open; + dvdinput_close = file_close; + dvdinput_seek = file_seek; + dvdinput_title = file_title; + dvdinput_read = file_read; + dvdinput_error = file_error; return 0; } } diff --git a/src/input/libdvdread/dvd_input.h b/src/input/libdvdread/dvd_input.h index 0f13385bf..e9e84917e 100644 --- a/src/input/libdvdread/dvd_input.h +++ b/src/input/libdvdread/dvd_input.h @@ -30,18 +30,18 @@ typedef struct dvd_input_s *dvd_input_t; /** - * Pointers which will be filled either the input meathods functions. + * Pointers which will be filled either the input methods functions. */ -extern dvd_input_t (*DVDinput_open) (const char *); -extern int (*DVDinput_close) (dvd_input_t); -extern int (*DVDinput_seek) (dvd_input_t, int); -extern int (*DVDinput_title) (dvd_input_t, int); -extern int (*DVDinput_read) (dvd_input_t, void *, int, int); -extern char * (*DVDinput_error) (dvd_input_t); +extern dvd_input_t (*dvdinput_open) (const char *); +extern int (*dvdinput_close) (dvd_input_t); +extern int (*dvdinput_seek) (dvd_input_t, int); +extern int (*dvdinput_title) (dvd_input_t, int); +extern int (*dvdinput_read) (dvd_input_t, void *, int, int); +extern char * (*dvdinput_error) (dvd_input_t); /** * Setup function accessed by dvd_reader.c. Returns 1 if there is CSS support. */ -int DVDInputSetup(void); +int dvdinput_setup(void); #endif /* DVD_INPUT_H_INCLUDED */ diff --git a/src/input/libdvdread/dvd_reader.c b/src/input/libdvdread/dvd_reader.c index 242bd2ba7..a46b47f02 100644 --- a/src/input/libdvdread/dvd_reader.c +++ b/src/input/libdvdread/dvd_reader.c @@ -1,6 +1,7 @@ /* - * Copyright (C) 2001, 2002 Billy Biggs <vektor@dumbterm.net>, - * Håkan Hjort <d95hjort@dtek.chalmers.se> + * Copyright (C) 2001, 2002, 2003 Billy Biggs <vektor@dumbterm.net>, + * Håkan Hjort <d95hjort@dtek.chalmers.se>, + * Björn Englund <d4bjorn@dtek.chalmers.se> * * 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 @@ -17,6 +18,8 @@ * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111, USA. */ +#include "config.h" + #include <sys/types.h> #include <sys/stat.h> #include <sys/time.h> /* For the timing of dvdcss_title crack. */ @@ -28,6 +31,7 @@ #include <unistd.h> #include <limits.h> #include <dirent.h> + #if defined(__FreeBSD__) || defined(__OpenBSD__) || defined(__NetBSD__) || defined(__bsdi__)|| defined(__DARWIN__) #define SYS_BSD 1 #endif @@ -44,6 +48,9 @@ #include "dvd_udf.h" #include "dvd_input.h" #include "dvd_reader.h" +#include "md5.h" + +#define DEFAULT_UDF_CACHE_LEVEL 1 struct dvd_reader_s { /* Basic information. */ @@ -52,13 +59,17 @@ struct dvd_reader_s { /* Hack for keeping track of the css status. * 0: no css, 1: perhaps (need init of keys), 2: have done init */ int css_state; - int css_title; /* Last title that we have called DVDinpute_title for. */ + int css_title; /* Last title that we have called dvdinpute_title for. */ /* Information required for an image file. */ dvd_input_t dev; /* Information required for a directory path drive. */ char *path_root; + + /* Filesystem cache */ + int udfcache_level; /* 0 - turned off, 1 - on */ + void *udfcache; }; struct dvd_file_s { @@ -80,6 +91,42 @@ struct dvd_file_s { ssize_t filesize; }; +/** + * Set the level of caching on udf + * level = 0 (no caching) + * level = 1 (caching filesystem info) + */ +int DVDUDFCacheLevel(dvd_reader_t *device, int level) +{ + struct dvd_reader_s *dev = (struct dvd_reader_s *)device; + + if(level > 0) { + level = 1; + } else if(level < 0) { + return dev->udfcache_level; + } + + dev->udfcache_level = level; + + return level; +} + +void *GetUDFCacheHandle(dvd_reader_t *device) +{ + struct dvd_reader_s *dev = (struct dvd_reader_s *)device; + + return dev->udfcache; +} + +void SetUDFCacheHandle(dvd_reader_t *device, void *cache) +{ + struct dvd_reader_s *dev = (struct dvd_reader_s *)device; + + dev->udfcache = cache; +} + + + /* Loop over all titles and call dvdcss_title to crack the keys. */ static int initAllCSSKeys( dvd_reader_t *dvd ) { @@ -89,6 +136,10 @@ static int initAllCSSKeys( dvd_reader_t *dvd ) uint32_t start, len; int title; + char *nokeys_str = getenv("DVDREAD_NOKEYS"); + if(nokeys_str != NULL) + return 0; + fprintf( stderr, "\n" ); fprintf( stderr, "libdvdread: Attempting to retrieve all CSS keys\n" ); fprintf( stderr, "libdvdread: This can take a _long_ time, " @@ -108,7 +159,7 @@ static int initAllCSSKeys( dvd_reader_t *dvd ) /* Perform CSS key cracking for this title. */ fprintf( stderr, "libdvdread: Get key for %s at 0x%08x\n", filename, start ); - if( DVDinput_title( dvd->dev, (int)start ) < 0 ) { + if( dvdinput_title( dvd->dev, (int)start ) < 0 ) { fprintf( stderr, "libdvdread: Error cracking CSS key for %s (0x%08x)\n", filename, start); } gettimeofday( &t_e, NULL ); @@ -126,7 +177,7 @@ static int initAllCSSKeys( dvd_reader_t *dvd ) /* Perform CSS key cracking for this title. */ fprintf( stderr, "libdvdread: Get key for %s at 0x%08x\n", filename, start ); - if( DVDinput_title( dvd->dev, (int)start ) < 0 ) { + if( dvdinput_title( dvd->dev, (int)start ) < 0 ) { fprintf( stderr, "libdvdread: Error cracking CSS key for %s (0x%08x)!!\n", filename, start); } gettimeofday( &t_e, NULL ); @@ -153,7 +204,7 @@ static dvd_reader_t *DVDOpenImageFile( const char *location, int have_css ) dvd_reader_t *dvd; dvd_input_t dev; - dev = DVDinput_open( location ); + dev = dvdinput_open( location ); if( !dev ) { fprintf( stderr, "libdvdread: Can't open %s for reading\n", location ); return 0; @@ -165,6 +216,9 @@ static dvd_reader_t *DVDOpenImageFile( const char *location, int have_css ) dvd->dev = dev; dvd->path_root = 0; + dvd->udfcache_level = DEFAULT_UDF_CACHE_LEVEL; + dvd->udfcache = NULL; + if( have_css ) { /* Only if DVDCSS_METHOD = title, a bit if it's disc or if * DVDCSS_METHOD = key but region missmatch. Unfortunaly we @@ -172,6 +226,7 @@ static dvd_reader_t *DVDOpenImageFile( const char *location, int have_css ) dvd->css_state = 1; /* Need key init. */ } + dvd->css_title = 0; return dvd; } @@ -186,6 +241,12 @@ static dvd_reader_t *DVDOpenPath( const char *path_root ) dvd->dev = 0; dvd->path_root = strdup( path_root ); + dvd->udfcache_level = DEFAULT_UDF_CACHE_LEVEL; + dvd->udfcache = NULL; + + dvd->css_state = 0; /* Only used in the UDF path */ + dvd->css_title = 0; /* Only matters in the UDF path */ + return dvd; } @@ -252,7 +313,7 @@ dvd_reader_t *DVDOpen( const char *path ) } /* Try to open libdvdcss or fall back to standard functions */ - have_css = DVDInputSetup(); + have_css = dvdinput_setup(); /* First check if this is a block/char device or a file*/ if( S_ISBLK( fileinfo.st_mode ) || @@ -395,8 +456,9 @@ dvd_reader_t *DVDOpen( const char *path ) void DVDClose( dvd_reader_t *dvd ) { if( dvd ) { - if( dvd->dev ) DVDinput_close( dvd->dev ); + if( dvd->dev ) dvdinput_close( dvd->dev ); if( dvd->path_root ) free( dvd->path_root ); + if( dvd->udfcache ) FreeUDFCache( dvd->udfcache ); free( dvd ); } } @@ -494,7 +556,7 @@ static dvd_file_t *DVDOpenFilePath( dvd_reader_t *dvd, char *filename ) /* Get the full path of the file. */ if( !findDVDFile( dvd, filename, full_path ) ) return 0; - dev = DVDinput_open( full_path ); + dev = dvdinput_open( full_path ); if( !dev ) return 0; dvd_file = (dvd_file_t *) malloc( sizeof( dvd_file_t ) ); @@ -558,7 +620,7 @@ static dvd_file_t *DVDOpenVOBUDF( dvd_reader_t *dvd, int title, int menu ) dvd->css_state = 2; } /* - if( DVDinput_title( dvd_file->dvd->dev, (int)start ) < 0 ) { + if( dvdinput_title( dvd_file->dvd->dev, (int)start ) < 0 ) { fprintf( stderr, "libdvdread: Error cracking CSS key for %s\n", filename ); } @@ -598,7 +660,7 @@ static dvd_file_t *DVDOpenVOBPath( dvd_reader_t *dvd, int title, int menu ) return 0; } - dev = DVDinput_open( full_path ); + dev = dvdinput_open( full_path ); if( dev == NULL ) { free( dvd_file ); return 0; @@ -611,7 +673,7 @@ static dvd_file_t *DVDOpenVOBPath( dvd_reader_t *dvd, int title, int menu ) } dvd_file->title_sizes[ 0 ] = fileinfo.st_size / DVD_VIDEO_LB_LEN; dvd_file->title_devs[ 0 ] = dev; - DVDinput_title( dvd_file->title_devs[0], 0); + dvdinput_title( dvd_file->title_devs[0], 0); dvd_file->filesize = dvd_file->title_sizes[ 0 ]; } else { @@ -628,8 +690,8 @@ static dvd_file_t *DVDOpenVOBPath( dvd_reader_t *dvd, int title, int menu ) } dvd_file->title_sizes[ i ] = fileinfo.st_size / DVD_VIDEO_LB_LEN; - dvd_file->title_devs[ i ] = DVDinput_open( full_path ); - DVDinput_title( dvd_file->title_devs[ i ], 0); + dvd_file->title_devs[ i ] = dvdinput_open( full_path ); + dvdinput_title( dvd_file->title_devs[ i ], 0 ); dvd_file->filesize += dvd_file->title_sizes[ i ]; } if( !dvd_file->title_devs[ 0 ] ) { @@ -702,7 +764,7 @@ void DVDCloseFile( dvd_file_t *dvd_file ) } else { for( i = 0; i < 9; ++i ) { if( dvd_file->title_devs[ i ] ) { - DVDinput_close( dvd_file->title_devs[i] ); + dvdinput_close( dvd_file->title_devs[i] ); } } } @@ -713,7 +775,7 @@ void DVDCloseFile( dvd_file_t *dvd_file ) } /* Internal, but used from dvd_udf.c */ -int DVDReadBlocksUDFRaw( dvd_reader_t *device, uint32_t lb_number, +int UDFReadBlocksRaw( dvd_reader_t *device, uint32_t lb_number, size_t block_count, unsigned char *data, int encrypted ) { @@ -724,13 +786,13 @@ int DVDReadBlocksUDFRaw( dvd_reader_t *device, uint32_t lb_number, return 0; } - ret = DVDinput_seek( device->dev, (int) lb_number ); + ret = dvdinput_seek( device->dev, (int) lb_number ); if( ret != (int) lb_number ) { fprintf( stderr, "libdvdread: Can't seek to block %u\n", lb_number ); return 0; } - return DVDinput_read( device->dev, (char *) data, + return dvdinput_read( device->dev, (char *) data, (int) block_count, encrypted ); } @@ -744,8 +806,8 @@ static int DVDReadBlocksUDF( dvd_file_t *dvd_file, uint32_t offset, size_t block_count, unsigned char *data, int encrypted ) { - return DVDReadBlocksUDFRaw( dvd_file->dvd, dvd_file->lb_start + offset, - block_count, data, encrypted ); + return UDFReadBlocksRaw( dvd_file->dvd, dvd_file->lb_start + offset, + block_count, data, encrypted ); } /* This is using possibly several inputs and starting from an offset of '0'. @@ -768,13 +830,13 @@ static int DVDReadBlocksPath( dvd_file_t *dvd_file, unsigned int offset, if( offset < dvd_file->title_sizes[ i ] ) { if( ( offset + block_count ) <= dvd_file->title_sizes[ i ] ) { - off = DVDinput_seek( dvd_file->title_devs[ i ], (int)offset ); + off = dvdinput_seek( dvd_file->title_devs[ i ], (int)offset ); if( off < 0 || off != (int)offset ) { fprintf( stderr, "libdvdread: Can't seek to block %d\n", offset ); return off < 0 ? off : 0; } - ret = DVDinput_read( dvd_file->title_devs[ i ], data, + ret = dvdinput_read( dvd_file->title_devs[ i ], data, (int)block_count, encrypted ); break; } else { @@ -783,13 +845,13 @@ static int DVDReadBlocksPath( dvd_file_t *dvd_file, unsigned int offset, * (This is only true if you try and read >1GB at a time) */ /* Read part 1 */ - off = DVDinput_seek( dvd_file->title_devs[ i ], (int)offset ); + off = dvdinput_seek( dvd_file->title_devs[ i ], (int)offset ); if( off < 0 || off != (int)offset ) { fprintf( stderr, "libdvdread: Can't seek to block %d\n", offset ); return off < 0 ? off : 0; } - ret = DVDinput_read( dvd_file->title_devs[ i ], data, + ret = dvdinput_read( dvd_file->title_devs[ i ], data, (int)part1_size, encrypted ); if( ret < 0 ) return ret; /* FIXME: This is wrong if i is the last file in the set. @@ -799,13 +861,13 @@ static int DVDReadBlocksPath( dvd_file_t *dvd_file, unsigned int offset, if( !dvd_file->title_devs[ i + 1 ] ) return ret; /* Read part 2 */ - off = DVDinput_seek( dvd_file->title_devs[ i + 1 ], 0 ); + off = dvdinput_seek( dvd_file->title_devs[ i + 1 ], 0 ); if( off < 0 || off != 0 ) { fprintf( stderr, "libdvdread: Can't seek to block %d\n", 0 ); return off < 0 ? off : 0; } - ret2 = DVDinput_read( dvd_file->title_devs[ i + 1 ], + ret2 = dvdinput_read( dvd_file->title_devs[ i + 1 ], data + ( part1_size * (int64_t)DVD_VIDEO_LB_LEN ), (int)(block_count - part1_size), @@ -835,10 +897,12 @@ ssize_t DVDReadBlocks( dvd_file_t *dvd_file, int offset, if( dvd_file->dvd->css_title != dvd_file->css_title ) { dvd_file->dvd->css_title = dvd_file->css_title; if( dvd_file->dvd->isImageFile ) { - DVDinput_title( dvd_file->dvd->dev, (int)dvd_file->lb_start ); - } else { - DVDinput_title( dvd_file->title_devs[ 0 ], (int)dvd_file->lb_start ); - } + dvdinput_title( dvd_file->dvd->dev, (int)dvd_file->lb_start ); + } + /* Here each vobu has it's own dvdcss handle, so no need to update + else { + dvdinput_title( dvd_file->title_devs[ 0 ], (int)dvd_file->lb_start ); + }*/ } if( dvd_file->dvd->isImageFile ) { @@ -883,7 +947,7 @@ ssize_t DVDReadBytes( dvd_file_t *dvd_file, void *data, size_t byte_size ) secbuf_base = (unsigned char *) malloc( numsec * DVD_VIDEO_LB_LEN + 2048 ); secbuf = (unsigned char *)(((int)secbuf_base & ~2047) + 2048); - if( !secbuf ) { + if( !secbuf_base ) { fprintf( stderr, "libdvdread: Can't allocate memory " "for file read!\n" ); return 0; @@ -917,3 +981,139 @@ ssize_t DVDFileSize( dvd_file_t *dvd_file ) return dvd_file->filesize; } + +int DVDDiscID( dvd_reader_t *dvd, unsigned char *discid ) +{ + struct md5_ctx ctx; + int title; + + /* Check arguments. */ + if( dvd == NULL || discid == NULL ) + return 0; + + /* Go through the first 10 IFO:s, in order, + * and md5sum them, i.e VIDEO_TS.IFO and VTS_0?_0.IFO */ + md5_init_ctx( &ctx ); + for( title = 0; title < 10; title++ ) { + dvd_file_t *dvd_file = DVDOpenFile( dvd, title, DVD_READ_INFO_FILE ); + if( dvd_file != NULL ) { + ssize_t bytes_read; + size_t file_size = dvd_file->filesize * DVD_VIDEO_LB_LEN; + char *buffer_base = malloc( file_size + 2048 ); + char *buffer = (unsigned char *)(((int)buffer_base & ~2047) + 2048); + + if( buffer_base == NULL ) { + fprintf( stderr, "libdvdread: DVDDiscId, failed to " + "allocate memory for file read!\n" ); + return -1; + } + bytes_read = DVDReadBytes( dvd_file, buffer, file_size ); + if( bytes_read != file_size ) { + fprintf( stderr, "libdvdread: DVDDiscId read returned %d bytes" + ", wanted %d\n", bytes_read, file_size ); + DVDCloseFile( dvd_file ); + free( buffer_base ); + return -1; + } + + md5_process_bytes( buffer, file_size, &ctx ); + + DVDCloseFile( dvd_file ); + free( buffer_base ); + } + } + md5_finish_ctx( &ctx, discid ); + + return 0; +} + + +int DVDISOVolumeInfo( dvd_reader_t *dvd, + char *volid, unsigned int volid_size, + unsigned char *volsetid, unsigned int volsetid_size ) +{ + unsigned char *buffer, *buffer_base; + int ret; + + /* Check arguments. */ + if( dvd == NULL ) + return 0; + + if( dvd->dev == NULL ) { + /* No block access, so no ISO... */ + return -1; + } + + buffer_base = malloc( DVD_VIDEO_LB_LEN + 2048 ); + buffer = (unsigned char *)(((int)buffer_base & ~2047) + 2048); + + if( buffer_base == NULL ) { + fprintf( stderr, "libdvdread: DVDISOVolumeInfo, failed to " + "allocate memory for file read!\n" ); + return -1; + } + + ret = UDFReadBlocksRaw( dvd, 16, 1, buffer, 0 ); + if( ret != 1 ) { + fprintf( stderr, "libdvdread: DVDISOVolumeInfo, failed to " + "read ISO9660 Primary Volume Descriptor!\n" ); + free( buffer_base ); + return -1; + } + + if( (volid != NULL) && (volid_size > 0) ) { + unsigned int n; + for(n = 0; n < 32; n++) { + if(buffer[40+n] == 0x20) { + break; + } + } + + if(volid_size > n+1) { + volid_size = n+1; + } + + memcpy(volid, &buffer[40], volid_size-1); + volid[volid_size-1] = '\0'; + } + + if( (volsetid != NULL) && (volsetid_size > 0) ) { + if(volsetid_size > 128) { + volsetid_size = 128; + } + memcpy(volsetid, &buffer[190], volsetid_size); + } + free( buffer_base ); + return 0; +} + + +int DVDUDFVolumeInfo( dvd_reader_t *dvd, + char *volid, unsigned int volid_size, + unsigned char *volsetid, unsigned int volsetid_size ) +{ + int ret; + /* Check arguments. */ + if( dvd == NULL ) + return -1; + + if( dvd->dev == NULL ) { + /* No block access, so no UDF VolumeSet Identifier */ + return -1; + } + + if( (volid != NULL) && (volid_size > 0) ) { + ret = UDFGetVolumeIdentifier(dvd, volid, volid_size); + if(!ret) { + return -1; + } + } + if( (volsetid != NULL) && (volsetid_size > 0) ) { + ret = UDFGetVolumeSetIdentifier(dvd, volsetid, volsetid_size); + if(!ret) { + return -1; + } + } + + return 0; +} diff --git a/src/input/libdvdread/dvd_reader.h b/src/input/libdvdread/dvd_reader.h index 631475976..cc4ba5489 100644 --- a/src/input/libdvdread/dvd_reader.h +++ b/src/input/libdvdread/dvd_reader.h @@ -3,7 +3,8 @@ /* * Copyright (C) 2001, 2002 Billy Biggs <vektor@dumbterm.net>, - * Håkan Hjort <d95hjort@dtek.chalmers.se> + * Håkan Hjort <d95hjort@dtek.chalmers.se>, + * Björn Englund <d4bjorn@dtek.chalmers.se> * * 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 @@ -30,6 +31,11 @@ */ /** + * The current version. + */ +#define DVDREAD_VERSION 904 + +/** * The length of one Logical Block of a DVD. */ #define DVD_VIDEO_LB_LEN 2048 @@ -179,6 +185,80 @@ ssize_t DVDReadBytes( dvd_file_t *, void *, size_t ); */ ssize_t DVDFileSize( dvd_file_t * ); +/** + * Get a unique 128 bit disc ID. + * This is the MD5 sum of VIDEO_TS.IFO and the VTS_0?_0.IFO files + * in title order (those that exist). + * If you need a 'text' representation of the id, print it as a + * hexadecimal number, using lowercase letters, discid[0] first. + * I.e. the same format as the command-line 'md5sum' program uses. + * + * @param dvd A read handle to get the disc ID from + * @param discid The buffer to put the disc ID into. The buffer must + * have room for 128 bits (16 chars). + * @return 0 on success, -1 on error. + */ +int DVDDiscID( dvd_reader_t *, unsigned char * ); + +/** + * Get the UDF VolumeIdentifier and VolumeSetIdentifier + * from the PrimaryVolumeDescriptor. + * + * @param dvd A read handle to get the disc ID from + * @param volid The buffer to put the VolumeIdentifier into. + * The VolumeIdentifier is latin-1 encoded (8bit unicode) + * null terminated and max 32 bytes (including '\0') + * @param volid_size No more than volid_size bytes will be copied to volid. + * If the VolumeIdentifier is truncated because of this + * it will still be null terminated. + * @param volsetid The buffer to put the VolumeSetIdentifier into. + * The VolumeIdentifier is 128 bytes as + * stored in the UDF PrimaryVolumeDescriptor. + * Note that this is not a null terminated string. + * @param volsetid_size At most volsetid_size bytes will be copied to volsetid. + * @return 0 on success, -1 on error. + */ +int DVDUDFVolumeInfo( dvd_reader_t *, char *, unsigned int, + unsigned char *, unsigned int ); + +/** + * Get the ISO9660 VolumeIdentifier and VolumeSetIdentifier + * + * * Only use this function as fallback if DVDUDFVolumeInfo returns 0 * + * * this will happen on a disc mastered only with a iso9660 filesystem * + * * All video DVD discs have UDF filesystem * + * + * @param dvd A read handle to get the disc ID from + * @param volid The buffer to put the VolumeIdentifier into. + * The VolumeIdentifier is coded with '0-9','A-Z','_' + * null terminated and max 33 bytes (including '\0') + * @param volid_size No more than volid_size bytes will be copied to volid. + * If the VolumeIdentifier is truncated because of this + * it will still be null terminated. + * @param volsetid The buffer to put the VolumeSetIdentifier into. + * The VolumeIdentifier is 128 bytes as + * stored in the ISO9660 PrimaryVolumeDescriptor. + * Note that this is not a null terminated string. + * @param volsetid_size At most volsetid_size bytes will be copied to volsetid. + * @return 0 on success, -1 on error. + */ +int DVDISOVolumeInfo( dvd_reader_t *, char *, unsigned int, + unsigned char *, unsigned int ); + +/** + * Sets the level of caching that is done when reading from a device + * + * @param dvd A read handle to get the disc ID from + * @param level The level of caching wanted. + * -1 - returns the current setting. + * 0 - UDF Cache turned off. + * 1 - (default level) Pointers to IFO files and some data from + * PrimaryVolumeDescriptor are cached. + * + * @return The level of caching. + */ +int DVDUDFCacheLevel( dvd_reader_t *, int ); + #ifdef __cplusplus }; #endif diff --git a/src/input/libdvdread/dvd_udf.c b/src/input/libdvdread/dvd_udf.c index eb5e159f8..7183f280e 100644 --- a/src/input/libdvdread/dvd_udf.c +++ b/src/input/libdvdread/dvd_udf.c @@ -4,6 +4,7 @@ * * Modifications by: * Billy Biggs <vektor@dumbterm.net>. + * Björn Englund <d4bjorn@dtek.chalmers.se>. * * dvdudf: parse and read the UDF volume information of a DVD Video * Copyright (C) 1999 Christian Wolff for convergence integrated media @@ -27,10 +28,11 @@ * http://www.gnu.org/copyleft/gpl.html */ +#include "config.h" + #include <stdio.h> #include <stdlib.h> #include <string.h> -#include <assert.h> #include <sys/ioctl.h> #include <sys/types.h> #include <sys/stat.h> @@ -41,7 +43,7 @@ #include "dvd_udf.h" /* Private but located in/shared with dvd_reader.c */ -extern int DVDReadBlocksUDFRaw( dvd_reader_t *device, uint32_t lb_number, +extern int UDFReadBlocksRaw( dvd_reader_t *device, uint32_t lb_number, size_t block_count, unsigned char *data, int encrypted ); @@ -55,7 +57,7 @@ static int DVDReadLBUDF( dvd_reader_t *device, uint32_t lb_number, while(count > 0) { - ret = DVDReadBlocksUDFRaw(device, lb_number, count, data, encrypted); + ret = UDFReadBlocksRaw(device, lb_number, count, data, encrypted); if(ret <= 0) { /* One of the reads failed or nothing more to read, too bad. @@ -93,6 +95,227 @@ struct AD { uint16_t Partition; }; +struct extent_ad { + uint32_t location; + uint32_t length; +}; + +struct avdp_t { + struct extent_ad mvds; + struct extent_ad rvds; +}; + +struct pvd_t { + uint8_t VolumeIdentifier[32]; + uint8_t VolumeSetIdentifier[128]; +}; + +struct lbudf { + uint32_t lb; + uint8_t *data; +}; + +struct icbmap { + uint32_t lbn; + struct AD file; + uint8_t filetype; +}; + +struct udf_cache { + int avdp_valid; + struct avdp_t avdp; + int pvd_valid; + struct pvd_t pvd; + int partition_valid; + struct Partition partition; + int rooticb_valid; + struct AD rooticb; + int lb_num; + struct lbudf *lbs; + int map_num; + struct icbmap *maps; +}; + +typedef enum { + PartitionCache, RootICBCache, LBUDFCache, MapCache, AVDPCache, PVDCache +} UDFCacheType; + +extern void *GetUDFCacheHandle(dvd_reader_t *device); +extern void SetUDFCacheHandle(dvd_reader_t *device, void *cache); + +void FreeUDFCache(void *cache) +{ + struct udf_cache *c = (struct udf_cache *)cache; + if(c == NULL) { + return; + } + if(c->lbs) { + free(c->lbs); + } + if(c->maps) { + free(c->maps); + } + free(c); +} + + +static int GetUDFCache(dvd_reader_t *device, UDFCacheType type, + uint32_t nr, void *data) +{ + int n; + struct udf_cache *c; + + if(DVDUDFCacheLevel(device, -1) <= 0) { + return 0; + } + + c = (struct udf_cache *)GetUDFCacheHandle(device); + + if(c == NULL) { + return 0; + } + + switch(type) { + case AVDPCache: + if(c->avdp_valid) { + *(struct avdp_t *)data = c->avdp; + return 1; + } + break; + case PVDCache: + if(c->pvd_valid) { + *(struct pvd_t *)data = c->pvd; + return 1; + } + break; + case PartitionCache: + if(c->partition_valid) { + *(struct Partition *)data = c->partition; + return 1; + } + break; + case RootICBCache: + if(c->rooticb_valid) { + *(struct AD *)data = c->rooticb; + return 1; + } + break; + case LBUDFCache: + for(n = 0; n < c->lb_num; n++) { + if(c->lbs[n].lb == nr) { + *(uint8_t **)data = c->lbs[n].data; + return 1; + } + } + break; + case MapCache: + for(n = 0; n < c->map_num; n++) { + if(c->maps[n].lbn == nr) { + *(struct icbmap *)data = c->maps[n]; + return 1; + } + } + break; + default: + break; + } + + return 0; +} + +static int SetUDFCache(dvd_reader_t *device, UDFCacheType type, + uint32_t nr, void *data) +{ + int n; + struct udf_cache *c; + + if(DVDUDFCacheLevel(device, -1) <= 0) { + return 0; + } + + c = (struct udf_cache *)GetUDFCacheHandle(device); + + if(c == NULL) { + c = calloc(1, sizeof(struct udf_cache)); + /* fprintf(stderr, "calloc: %d\n", sizeof(struct udf_cache)); */ + if(c == NULL) { + return 0; + } + SetUDFCacheHandle(device, c); + } + + + switch(type) { + case AVDPCache: + c->avdp = *(struct avdp_t *)data; + c->avdp_valid = 1; + break; + case PVDCache: + c->pvd = *(struct pvd_t *)data; + c->pvd_valid = 1; + break; + case PartitionCache: + c->partition = *(struct Partition *)data; + c->partition_valid = 1; + break; + case RootICBCache: + c->rooticb = *(struct AD *)data; + c->rooticb_valid = 1; + break; + case LBUDFCache: + for(n = 0; n < c->lb_num; n++) { + if(c->lbs[n].lb == nr) { + /* replace with new data */ + c->lbs[n].data = *(uint8_t **)data; + c->lbs[n].lb = nr; + return 1; + } + } + c->lb_num++; + c->lbs = realloc(c->lbs, c->lb_num * sizeof(struct lbudf)); + /* + fprintf(stderr, "realloc lb: %d * %d = %d\n", + c->lb_num, sizeof(struct lbudf), + c->lb_num * sizeof(struct lbudf)); + */ + if(c->lbs == NULL) { + c->lb_num = 0; + return 0; + } + c->lbs[n].data = *(uint8_t **)data; + c->lbs[n].lb = nr; + break; + case MapCache: + for(n = 0; n < c->map_num; n++) { + if(c->maps[n].lbn == nr) { + /* replace with new data */ + c->maps[n] = *(struct icbmap *)data; + c->maps[n].lbn = nr; + return 1; + } + } + c->map_num++; + c->maps = realloc(c->maps, c->map_num * sizeof(struct icbmap)); + /* + fprintf(stderr, "realloc maps: %d * %d = %d\n", + c->map_num, sizeof(struct icbmap), + c->map_num * sizeof(struct icbmap)); + */ + if(c->maps == NULL) { + c->map_num = 0; + return 0; + } + c->maps[n] = *(struct icbmap *)data; + c->maps[n].lbn = nr; + break; + default: + return 0; + } + + return 1; +} + + /* For direct data access, LSB first */ #define GETN1(p) ((uint8_t)data[p]) #define GETN2(p) ((uint16_t)data[p] | ((uint16_t)data[(p) + 1] << 8)) @@ -268,8 +491,16 @@ static int UDFMapICB( dvd_reader_t *device, struct AD ICB, uint8_t *FileType, uint8_t *LogBlock = (uint8_t *)(((int)LogBlock_base & ~2047) + 2048); uint32_t lbnum; uint16_t TagID; + struct icbmap tmpmap; lbnum = partition->Start + ICB.Location; + tmpmap.lbn = lbnum; + if(GetUDFCache(device, MapCache, lbnum, &tmpmap)) { + *FileType = tmpmap.filetype; + *File = tmpmap.file; + return 1; + } + do { if( DVDReadLBUDF( device, lbnum++, 1, LogBlock, 0 ) <= 0 ) { TagID = 0; @@ -279,6 +510,9 @@ static int UDFMapICB( dvd_reader_t *device, struct AD ICB, uint8_t *FileType, if( TagID == 261 ) { UDFFileEntry( LogBlock, FileType, partition, File ); + tmpmap.file = *File; + tmpmap.filetype = *FileType; + SetUDFCache(device, MapCache, tmpmap.lbn, &tmpmap); return 1; }; } while( ( lbnum <= partition->Start + ICB.Location + ( ICB.Length - 1 ) @@ -294,7 +528,8 @@ static int UDFMapICB( dvd_reader_t *device, struct AD ICB, uint8_t *FileType, * return 1 on success, 0 on error; */ static int UDFScanDir( dvd_reader_t *device, struct AD Dir, char *FileName, - struct Partition *partition, struct AD *FileICB ) + struct Partition *partition, struct AD *FileICB, + int cache_file_info) { char filename[ MAX_UDF_FILE_NAME_LEN ]; uint8_t directory_base[ 2 * DVD_VIDEO_LB_LEN + 2048]; @@ -303,9 +538,79 @@ static int UDFScanDir( dvd_reader_t *device, struct AD Dir, char *FileName, uint16_t TagID; uint8_t filechar; unsigned int p; + uint8_t *cached_dir_base = NULL, *cached_dir; + uint32_t dir_lba; + struct AD tmpICB; + int found = 0; + int in_cache = 0; /* Scan dir for ICB of file */ lbnum = partition->Start + Dir.Location; + + if(DVDUDFCacheLevel(device, -1) > 0) { + /* caching */ + + if(!GetUDFCache(device, LBUDFCache, lbnum, &cached_dir)) { + dir_lba = (Dir.Length + DVD_VIDEO_LB_LEN) / DVD_VIDEO_LB_LEN; + if((cached_dir_base = malloc(dir_lba * DVD_VIDEO_LB_LEN + 2048)) == NULL) { + return 0; + } + cached_dir = (uint8_t *)(((int)cached_dir_base & ~2047) + 2048); + if( DVDReadLBUDF( device, lbnum, dir_lba, cached_dir, 0) <= 0 ) { + free(cached_dir_base); + cached_dir = NULL; + } + /* + if(cached_dir) { + fprintf(stderr, "malloc dir: %d\n", + dir_lba * DVD_VIDEO_LB_LEN); + } + */ + SetUDFCache(device, LBUDFCache, lbnum, &cached_dir); + } else { + in_cache = 1; + } + + if(cached_dir == NULL) { + return 0; + } + + p = 0; + + while( p < Dir.Length ) { + UDFDescriptor( &cached_dir[ p ], &TagID ); + if( TagID == 257 ) { + p += UDFFileIdentifier( &cached_dir[ p ], &filechar, + filename, &tmpICB ); + if(cache_file_info && !in_cache) { + uint8_t tmpFiletype; + struct AD tmpFile; + + if( !strcasecmp( FileName, filename ) ) { + *FileICB = tmpICB; + found = 1; + + } + UDFMapICB(device, tmpICB, &tmpFiletype, + partition, &tmpFile); + } else { + if( !strcasecmp( FileName, filename ) ) { + *FileICB = tmpICB; + return 1; + } + } + } else { + if(cache_file_info && (!in_cache) && found) { + return 1; + } + return 0; + } + } + if(cache_file_info && (!in_cache) && found) { + return 1; + } + return 0; + } if( DVDReadLBUDF( device, lbnum, 2, directory, 0 ) <= 0 ) { return 0; @@ -336,6 +641,74 @@ static int UDFScanDir( dvd_reader_t *device, struct AD Dir, char *FileName, return 0; } + +static int UDFGetAVDP( dvd_reader_t *device, + struct avdp_t *avdp) +{ + uint8_t Anchor_base[ DVD_VIDEO_LB_LEN + 2048 ]; + uint8_t *Anchor = (uint8_t *)(((int)Anchor_base & ~2047) + 2048); + uint32_t lbnum, MVDS_location, MVDS_length; + uint16_t TagID; + uint32_t lastsector; + int terminate; + struct avdp_t; + + if(GetUDFCache(device, AVDPCache, 0, avdp)) { + return 1; + } + + /* Find Anchor */ + lastsector = 0; + lbnum = 256; /* Try #1, prime anchor */ + terminate = 0; + + for(;;) { + if( DVDReadLBUDF( device, lbnum, 1, Anchor, 0 ) > 0 ) { + UDFDescriptor( Anchor, &TagID ); + } else { + TagID = 0; + } + if (TagID != 2) { + /* Not an anchor */ + if( terminate ) return 0; /* Final try failed */ + + if( lastsector ) { + + /* We already found the last sector. Try #3, alternative + * backup anchor. If that fails, don't try again. + */ + lbnum = lastsector; + terminate = 1; + } else { + /* TODO: Find last sector of the disc (this is optional). */ + if( lastsector ) { + /* Try #2, backup anchor */ + lbnum = lastsector - 256; + } else { + /* Unable to find last sector */ + return 0; + } + } + } else { + /* It's an anchor! We can leave */ + break; + } + } + /* Main volume descriptor */ + UDFExtentAD( &Anchor[ 16 ], &MVDS_length, &MVDS_location ); + avdp->mvds.location = MVDS_location; + avdp->mvds.length = MVDS_length; + + /* Backup volume descriptor */ + UDFExtentAD( &Anchor[ 24 ], &MVDS_length, &MVDS_location ); + avdp->rvds.location = MVDS_location; + avdp->rvds.length = MVDS_length; + + SetUDFCache(device, AVDPCache, 0, avdp); + + return 1; +} + /** * Looks for partition on the disc. Returns 1 if partition found, 0 on error. * partnum: Number of the partition, starting at 0. @@ -346,53 +719,20 @@ static int UDFFindPartition( dvd_reader_t *device, int partnum, { uint8_t LogBlock_base[ DVD_VIDEO_LB_LEN + 2048 ]; uint8_t *LogBlock = (uint8_t *)(((int)LogBlock_base & ~2047) + 2048); - uint8_t Anchor_base[ DVD_VIDEO_LB_LEN + 2048 ]; - uint8_t *Anchor = (uint8_t *)(((int)Anchor_base & ~2047) + 2048); uint32_t lbnum, MVDS_location, MVDS_length; uint16_t TagID; - uint32_t lastsector; - int i, terminate, volvalid; - - /* Find Anchor */ - lastsector = 0; - lbnum = 256; /* Try #1, prime anchor */ - terminate = 0; - - for(;;) { - if( DVDReadLBUDF( device, lbnum, 1, Anchor, 0 ) > 0 ) { - UDFDescriptor( Anchor, &TagID ); - } else { - TagID = 0; - } - if (TagID != 2) { - /* Not an anchor */ - if( terminate ) return 0; /* Final try failed */ + int i, volvalid; + struct avdp_t avdp; - if( lastsector ) { - - /* We already found the last sector. Try #3, alternative - * backup anchor. If that fails, don't try again. - */ - lbnum = lastsector; - terminate = 1; - } else { - /* TODO: Find last sector of the disc (this is optional). */ - if( lastsector ) { - /* Try #2, backup anchor */ - lbnum = lastsector - 256; - } else { - /* Unable to find last sector */ - return 0; - } - } - } else { - /* It's an anchor! We can leave */ - break; - } + + if(!UDFGetAVDP(device, &avdp)) { + return 0; } + /* Main volume descriptor */ - UDFExtentAD( &Anchor[ 16 ], &MVDS_length, &MVDS_location ); - + MVDS_location = avdp.mvds.location; + MVDS_length = avdp.mvds.length; + part->valid = 0; volvalid = 0; part->VolumeDesc[ 0 ] = '\0'; @@ -427,8 +767,9 @@ static int UDFFindPartition( dvd_reader_t *device, int partnum, && ( ( !part->valid ) || ( !volvalid ) ) ); if( ( !part->valid) || ( !volvalid ) ) { - /* Backup volume descriptor */ - UDFExtentAD( &Anchor[ 24 ], &MVDS_length, &MVDS_location ); + /* Backup volume descriptor */ + MVDS_location = avdp.mvds.location; + MVDS_length = avdp.mvds.length; } } while( i-- && ( ( !part->valid ) || ( !volvalid ) ) ); @@ -448,17 +789,21 @@ uint32_t UDFFindFile( dvd_reader_t *device, char *filename, char tokenline[ MAX_UDF_FILE_NAME_LEN ]; char *token; uint8_t filetype; - + *filesize = 0; tokenline[0] = '\0'; strcat( tokenline, filename ); - /* Find partition, 0 is the standard location for DVD Video.*/ - if( !UDFFindPartition( device, 0, &partition ) ) return 0; - - /* Find root dir ICB */ - lbnum = partition.Start; - do { + + if(!(GetUDFCache(device, PartitionCache, 0, &partition) && + GetUDFCache(device, RootICBCache, 0, &RootICB))) { + /* Find partition, 0 is the standard location for DVD Video.*/ + if( !UDFFindPartition( device, 0, &partition ) ) return 0; + SetUDFCache(device, PartitionCache, 0, &partition); + + /* Find root dir ICB */ + lbnum = partition.Start; + do { if( DVDReadLBUDF( device, lbnum++, 1, LogBlock, 0 ) <= 0 ) { TagID = 0; } else { @@ -475,19 +820,34 @@ uint32_t UDFFindFile( dvd_reader_t *device, char *filename, /* Sanity checks. */ if( TagID != 256 ) return 0; if( RootICB.Partition != 0 ) return 0; - + SetUDFCache(device, RootICBCache, 0, &RootICB); + } + /* Find root dir */ if( !UDFMapICB( device, RootICB, &filetype, &partition, &File ) ) return 0; if( filetype != 4 ) return 0; /* Root dir should be dir */ - /* Tokenize filepath */ - token = strtok(tokenline, "/"); - while( token != NULL ) { - if( !UDFScanDir( device, File, token, &partition, &ICB ) ) return 0; - if( !UDFMapICB( device, ICB, &filetype, &partition, &File ) ) return 0; + { + int cache_file_info = 0; + /* Tokenize filepath */ + token = strtok(tokenline, "/"); + + while( token != NULL ) { + + if( !UDFScanDir( device, File, token, &partition, &ICB, + cache_file_info)) { + return 0; + } + if( !UDFMapICB( device, ICB, &filetype, &partition, &File ) ) { + return 0; + } + if(!strcmp(token, "VIDEO_TS")) { + cache_file_info = 1; + } token = strtok( NULL, "/" ); - } - + } + } + /* Sanity check. */ if( File.Partition != 0 ) return 0; @@ -498,3 +858,146 @@ uint32_t UDFFindFile( dvd_reader_t *device, char *filename, else return partition.Start + File.Location; } + + + +/** + * Gets a Descriptor . + * Returns 1 if descriptor found, 0 on error. + * id, tagid of descriptor + * bufsize, size of BlockBuf (must be >= DVD_VIDEO_LB_LEN). + */ +static int UDFGetDescriptor( dvd_reader_t *device, int id, + uint8_t *descriptor, int bufsize) +{ + uint32_t lbnum, MVDS_location, MVDS_length; + struct avdp_t avdp; + uint16_t TagID; + uint32_t lastsector; + int i, terminate; + int desc_found = 0; + /* Find Anchor */ + lastsector = 0; + lbnum = 256; /* Try #1, prime anchor */ + terminate = 0; + if(bufsize < DVD_VIDEO_LB_LEN) { + return 0; + } + + if(!UDFGetAVDP(device, &avdp)) { + return 0; + } + + /* Main volume descriptor */ + MVDS_location = avdp.mvds.location; + MVDS_length = avdp.mvds.length; + + i = 1; + do { + /* Find Descriptor */ + lbnum = MVDS_location; + do { + + if( DVDReadLBUDF( device, lbnum++, 1, descriptor, 0 ) <= 0 ) { + TagID = 0; + } else { + UDFDescriptor( descriptor, &TagID ); + } + + if( (TagID == id) && ( !desc_found ) ) { + /* Descriptor */ + desc_found = 1; + } + } while( ( lbnum <= MVDS_location + ( MVDS_length - 1 ) + / DVD_VIDEO_LB_LEN ) && ( TagID != 8 ) + && ( !desc_found) ); + + if( !desc_found ) { + /* Backup volume descriptor */ + MVDS_location = avdp.rvds.location; + MVDS_length = avdp.rvds.length; + } + } while( i-- && ( !desc_found ) ); + + return desc_found; +} + + +static int UDFGetPVD(dvd_reader_t *device, struct pvd_t *pvd) +{ + uint8_t pvd_buf_base[DVD_VIDEO_LB_LEN + 2048]; + uint8_t *pvd_buf = (uint8_t *)(((int)pvd_buf_base & ~2047) + 2048); + + if(GetUDFCache(device, PVDCache, 0, pvd)) { + return 1; + } + + if(!UDFGetDescriptor( device, 1, pvd_buf, sizeof(pvd_buf))) { + return 0; + } + + memcpy(pvd->VolumeIdentifier, &pvd_buf[24], 32); + memcpy(pvd->VolumeSetIdentifier, &pvd_buf[72], 128); + SetUDFCache(device, PVDCache, 0, pvd); + + return 1; +} + +/** + * Gets the Volume Identifier string, in 8bit unicode (latin-1) + * volid, place to put the string + * volid_size, size of the buffer volid points to + * returns the size of buffer needed for all data + */ +int UDFGetVolumeIdentifier(dvd_reader_t *device, char *volid, + unsigned int volid_size) +{ + struct pvd_t pvd; + unsigned int volid_len; + + /* get primary volume descriptor */ + if(!UDFGetPVD(device, &pvd)) { + return 0; + } + + volid_len = pvd.VolumeIdentifier[31]; + if(volid_len > 31) { + /* this field is only 32 bytes something is wrong */ + volid_len = 31; + } + if(volid_size > volid_len) { + volid_size = volid_len; + } + Unicodedecode(pvd.VolumeIdentifier, volid_size, volid); + + return volid_len; +} + +/** + * Gets the Volume Set Identifier, as a 128-byte dstring (not decoded) + * WARNING This is not a null terminated string + * volsetid, place to put the data + * volsetid_size, size of the buffer volsetid points to + * the buffer should be >=128 bytes to store the whole volumesetidentifier + * returns the size of the available volsetid information (128) + * or 0 on error + */ +int UDFGetVolumeSetIdentifier(dvd_reader_t *device, uint8_t *volsetid, + unsigned int volsetid_size) +{ + struct pvd_t pvd; + + /* get primary volume descriptor */ + if(!UDFGetPVD(device, &pvd)) { + return 0; + } + + + if(volsetid_size > 128) { + volsetid_size = 128; + } + + memcpy(volsetid, pvd.VolumeSetIdentifier, volsetid_size); + + return 128; +} diff --git a/src/input/libdvdread/dvd_udf.h b/src/input/libdvdread/dvd_udf.h index 960ccf405..b600983d9 100644 --- a/src/input/libdvdread/dvd_udf.h +++ b/src/input/libdvdread/dvd_udf.h @@ -7,7 +7,8 @@ * * Modifications by: * Billy Biggs <vektor@dumbterm.net>. - * + * Björn Englund <d4bjorn@dtek.chalmers.se>. + * * dvdudf: parse and read the UDF volume information of a DVD Video * Copyright (C) 1999 Christian Wolff for convergence integrated media * GmbH The author can be reached at scarabaeus@convergence.de, the @@ -47,6 +48,11 @@ extern "C" { */ uint32_t UDFFindFile( dvd_reader_t *device, char *filename, uint32_t *size ); +void FreeUDFCache(void *cache); +int UDFGetVolumeIdentifier(dvd_reader_t *device, + char *volid, unsigned int volid_size); +int UDFGetVolumeSetIdentifier(dvd_reader_t *device, + uint8_t *volsetid, unsigned int volsetid_size); #ifdef __cplusplus }; #endif diff --git a/src/input/libdvdread/dvdread_internal.h b/src/input/libdvdread/dvdread_internal.h new file mode 100644 index 000000000..a7c802d98 --- /dev/null +++ b/src/input/libdvdread/dvdread_internal.h @@ -0,0 +1,12 @@ +#ifndef DVDREAD_INTERNAL_H +#define DVDREAD_INTERNAL_H + + +#define CHECK_VALUE(arg) \ + if(!(arg)) { \ + fprintf(stderr, "\n*** libdvdread: CHECK_VALUE failed in %s:%i ***" \ + "\n*** for %s ***\n\n", \ + __FILE__, __LINE__, # arg ); \ + } + +#endif /* DVDREAD_INTERNAL_H */ diff --git a/src/input/libdvdread/ifo_print.c b/src/input/libdvdread/ifo_print.c index 21f28aa2b..50aeacd17 100644 --- a/src/input/libdvdread/ifo_print.c +++ b/src/input/libdvdread/ifo_print.c @@ -1,6 +1,7 @@ /* - * Copyright (C) 2000, 2001, 2002 Björn Englund <d4bjorn@dtek.chalmers.se>, - * Håkan Hjort <d95hjort@dtek.chalmers.se> + * Copyright (C) 2000, 2001, 2002, 2003 + * Björn Englund <d4bjorn@dtek.chalmers.se>, + * Håkan Hjort <d95hjort@dtek.chalmers.se> * * 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 @@ -17,26 +18,27 @@ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA */ +#include "config.h" + #include <stdio.h> #include <stdlib.h> #include <unistd.h> #include <inttypes.h> #include <string.h> #include <ctype.h> -#include <assert.h> -#include "config.h" /* Needed for WORDS_BIGENDIAN */ #include "ifo_types.h" #include "ifo_read.h" #include "ifo_print.h" +#include "dvdread_internal.h" /* Put this in some other file / package? It's used in nav_print too. */ -static void ifoPrint_time(int level, dvd_time_t *dtime) { +static void ifoPrint_time(dvd_time_t *dtime) { const char *rate; - assert((dtime->hour>>4) < 0xa && (dtime->hour&0xf) < 0xa); - assert((dtime->minute>>4) < 0x7 && (dtime->minute&0xf) < 0xa); - assert((dtime->second>>4) < 0x7 && (dtime->second&0xf) < 0xa); - assert((dtime->frame_u&0xf) < 0xa); + CHECK_VALUE((dtime->hour>>4) < 0xa && (dtime->hour&0xf) < 0xa); + CHECK_VALUE((dtime->minute>>4) < 0x7 && (dtime->minute&0xf) < 0xa); + CHECK_VALUE((dtime->second>>4) < 0x7 && (dtime->second&0xf) < 0xa); + CHECK_VALUE((dtime->frame_u&0xf) < 0xa); printf("%02x:%02x:%02x.%02x", dtime->hour, @@ -75,7 +77,7 @@ static void ifoPrint_CMD(int row, vm_cmd_t *command) { printf("\n"); } -static void ifoPrint_video_attributes(int level, video_attr_t *attr) { +static void ifoPrint_video_attributes(video_attr_t *attr) { /* The following test is shorter but not correct ISO C, memcmp(attr,my_friendly_zeros, sizeof(video_attr_t)) */ @@ -86,6 +88,7 @@ static void ifoPrint_video_attributes(int level, video_attr_t *attr) { && attr->unknown1 == 0 && attr->line21_cc_1 == 0 && attr->line21_cc_2 == 0 + && attr->bit_rate == 0 && attr->video_format == 0 && attr->letterboxed == 0 && attr->film_mode == 0) { @@ -145,7 +148,7 @@ static void ifoPrint_video_attributes(int level, video_attr_t *attr) { } printf("U%x ", attr->unknown1); - assert(!attr->unknown1); + CHECK_VALUE(!attr->unknown1); if(attr->line21_cc_1 || attr->line21_cc_2) { printf("NTSC CC "); @@ -154,6 +157,17 @@ static void ifoPrint_video_attributes(int level, video_attr_t *attr) { if(attr->line21_cc_2) printf("2 "); } + + switch(attr->bit_rate) { + case 0: + printf("Variable Bit Rate "); + break; + case 1: + printf("Constant Bit Rate "); + break; + default: + printf("(please send a bug report)"); + } { int height = 480; @@ -188,7 +202,7 @@ static void ifoPrint_video_attributes(int level, video_attr_t *attr) { } } -static void ifoPrint_audio_attributes(int level, audio_attr_t *attr) { +static void ifoPrint_audio_attributes(audio_attr_t *attr) { if(attr->audio_format == 0 && attr->multichannel_extension == 0 @@ -197,8 +211,10 @@ static void ifoPrint_audio_attributes(int level, audio_attr_t *attr) { && attr->quantization == 0 && attr->sample_frequency == 0 && attr->channels == 0 + && attr->lang_code == 0 && attr->lang_extension == 0 - && attr->unknown1 == 0 + && attr->code_extension == 0 + && attr->unknown3 == 0 && attr->unknown1 == 0) { printf("-- Unspecified --"); return; @@ -236,10 +252,11 @@ static void ifoPrint_audio_attributes(int level, audio_attr_t *attr) { switch(attr->lang_type) { case 0: /* not specified */ - assert(attr->lang_code == 0 || attr->lang_code == 0xffff); + CHECK_VALUE(attr->lang_code == 0 || attr->lang_code == 0xffff); break; case 1: - printf("%c%c ", attr->lang_code>>8, attr->lang_code & 0xff); + printf("%c%c (%c) ", attr->lang_code>>8, attr->lang_code & 0xff, + attr->lang_extension ? attr->lang_extension : ' '); break; default: printf("(please send a bug report) "); @@ -290,7 +307,7 @@ static void ifoPrint_audio_attributes(int level, audio_attr_t *attr) { printf("%dCh ", attr->channels + 1); - switch(attr->lang_extension) { + switch(attr->code_extension) { case 0: printf("Not specified "); break; @@ -311,34 +328,64 @@ static void ifoPrint_audio_attributes(int level, audio_attr_t *attr) { printf("(please send a bug report) "); } - printf("%d ", attr->unknown1); - printf("%d ", attr->unknown2); + printf("%d ", attr->unknown3); + if(attr->application_mode == 1) { + printf("ca=%d ", attr->app_info.karaoke.channel_assignment); + printf("%d ", attr->app_info.karaoke.version); + if(attr->app_info.karaoke.mc_intro) + printf("mc intro "); + printf("%s ", attr->app_info.karaoke.mode ? "duet" : "solo"); + printf("%d ", attr->app_info.karaoke.unknown4); + } + if(attr->application_mode == 2) { + if(attr->app_info.surround.dolby_encoded) { + printf("dolby surround "); + } + printf("%d ", attr->app_info.surround.unknown5); + printf("%d ", attr->app_info.surround.unknown6); + } } -static void ifoPrint_subp_attributes(int level, subp_attr_t *attr) { +static void ifoPrint_subp_attributes(subp_attr_t *attr) { if(attr->type == 0 + && attr->code_mode == 0 && attr->lang_code == 0 + && attr->lang_extension == 0 && attr->zero1 == 0 && attr->zero2 == 0 - && attr->lang_extension== 0) { + && attr->code_extension == 0) { printf("-- Unspecified --"); return; } - printf("type %02x ", attr->type); - - if(isalpha((int)(attr->lang_code >> 8)) - && isalpha((int)(attr->lang_code & 0xff))) { - printf("%c%c ", attr->lang_code >> 8, attr->lang_code & 0xff); + switch(attr->code_mode) { + case 0: + printf("Coding Mode RLE "); + break; + case 1: + printf("Coding Mode Extended "); + break; + default: + printf("(please send a bug report) "); + } + + if(attr->type == 1) { + if(isalpha((int)(attr->lang_code >> 8)) + && isalpha((int)(attr->lang_code & 0xff))) { + printf("%c%c ", attr->lang_code >> 8, attr->lang_code & 0xff); + } else { + printf("%02x%02x ", attr->lang_code >> 8, attr->lang_code & 0xff); + } } else { - printf("%02x%02x ", 0xff & (unsigned)(attr->lang_code >> 8), - 0xff & (unsigned)(attr->lang_code & 0xff)); + printf("lang not specified "); } printf("%d ", attr->zero1); printf("%d ", attr->zero2); - + printf("%d ", attr->code_extension); + + /* Is this correct? should it not be subp_code_ext here instead? */ switch(attr->lang_extension) { case 0: printf("Not specified "); @@ -494,20 +541,20 @@ void ifoPrint_VMGI_MAT(vmgi_mat_t *vmgi_mat) { printf("Start sector of VMGM_VOBU_ADMAP: %08x\n", vmgi_mat->vmgm_vobu_admap); printf("Video attributes of VMGM_VOBS: "); - ifoPrint_video_attributes(5, &vmgi_mat->vmgm_video_attr); + ifoPrint_video_attributes(&vmgi_mat->vmgm_video_attr); printf("\n"); printf("VMGM Number of Audio attributes: %i\n", vmgi_mat->nr_of_vmgm_audio_streams); if(vmgi_mat->nr_of_vmgm_audio_streams > 0) { printf("\tstream %i status: ", 1); - ifoPrint_audio_attributes(5, &vmgi_mat->vmgm_audio_attr); + ifoPrint_audio_attributes(&vmgi_mat->vmgm_audio_attr); printf("\n"); } printf("VMGM Number of Sub-picture attributes: %i\n", vmgi_mat->nr_of_vmgm_subp_streams); if(vmgi_mat->nr_of_vmgm_subp_streams > 0) { printf("\tstream %2i status: ", 1); - ifoPrint_subp_attributes(5, &vmgi_mat->vmgm_subp_attr); + ifoPrint_subp_attributes(&vmgi_mat->vmgm_subp_attr); printf("\n"); } } @@ -536,14 +583,14 @@ void ifoPrint_VTSI_MAT(vtsi_mat_t *vtsi_mat) { printf("Start sector of VTS_VOBU_ADMAP: %08x\n", vtsi_mat->vts_vobu_admap); printf("Video attributes of VTSM_VOBS: "); - ifoPrint_video_attributes(5, &vtsi_mat->vtsm_video_attr); + ifoPrint_video_attributes(&vtsi_mat->vtsm_video_attr); printf("\n"); printf("VTSM Number of Audio attributes: %i\n", vtsi_mat->nr_of_vtsm_audio_streams); if(vtsi_mat->nr_of_vtsm_audio_streams > 0) { printf("\tstream %i status: ", 1); - ifoPrint_audio_attributes(5, &vtsi_mat->vtsm_audio_attr); + ifoPrint_audio_attributes(&vtsi_mat->vtsm_audio_attr); printf("\n"); } @@ -551,19 +598,19 @@ void ifoPrint_VTSI_MAT(vtsi_mat_t *vtsi_mat) { vtsi_mat->nr_of_vtsm_subp_streams); if(vtsi_mat->nr_of_vtsm_subp_streams > 0) { printf("\tstream %2i status: ", 1); - ifoPrint_subp_attributes(5, &vtsi_mat->vtsm_subp_attr); + ifoPrint_subp_attributes(&vtsi_mat->vtsm_subp_attr); printf("\n"); } printf("Video attributes of VTS_VOBS: "); - ifoPrint_video_attributes(5, &vtsi_mat->vts_video_attr); + ifoPrint_video_attributes(&vtsi_mat->vts_video_attr); printf("\n"); printf("VTS Number of Audio attributes: %i\n", vtsi_mat->nr_of_vts_audio_streams); for(i = 0; i < vtsi_mat->nr_of_vts_audio_streams; i++) { printf("\tstream %i status: ", i); - ifoPrint_audio_attributes(5, &vtsi_mat->vts_audio_attr[i]); + ifoPrint_audio_attributes(&vtsi_mat->vts_audio_attr[i]); printf("\n"); } @@ -571,9 +618,11 @@ void ifoPrint_VTSI_MAT(vtsi_mat_t *vtsi_mat) { vtsi_mat->nr_of_vts_subp_streams); for(i = 0; i < vtsi_mat->nr_of_vts_subp_streams; i++) { printf("\tstream %2i status: ", i); - ifoPrint_subp_attributes(5, &vtsi_mat->vts_subp_attr[i]); + ifoPrint_subp_attributes(&vtsi_mat->vts_subp_attr[i]); printf("\n"); } + + /* FIXME: Add printing of MultiChannel Extension */ } @@ -627,7 +676,7 @@ static void ifoPrint_CELL_PLAYBACK(cell_playback_t *cell_playback, int nr) { for(i=0;i<nr;i++) { printf("Cell: %3i ", i + 1); - ifoPrint_time(5, &cell_playback[i].playback_time); + ifoPrint_time(&cell_playback[i].playback_time); printf("\t"); if(cell_playback[i].block_mode || cell_playback[i].block_type) { @@ -705,7 +754,7 @@ void ifoPrint_PGC(pgc_t *pgc) { printf("Number of Cells: %i\n", pgc->nr_of_cells); /* Check that time is 0:0:0:0 also if nr_of_programs==0 */ printf("Playback time: "); - ifoPrint_time(5, &pgc->playback_time); printf("\n"); + ifoPrint_time(&pgc->playback_time); printf("\n"); /* If no programs/no time then does this mean anything? */ printf("Prohibited user operations: "); @@ -730,7 +779,12 @@ void ifoPrint_PGC(pgc_t *pgc) { printf("GoUp PGC number: %i\n", pgc->goup_pgc_nr); if(pgc->nr_of_programs != 0) { printf("Still time: %i seconds (255=inf)\n", pgc->still_time); - printf("PG Playback mode %02x\n", pgc->pg_playback_mode); + if(pgc->pg_playback_mode == 0) + printf("PG Playback mode: Sequential\n"); + else if(!(pgc->pg_playback_mode & 0x80)) + printf("PG Playback mode: Random %i\n", pgc->pg_playback_mode); + else + printf("PG Playback mode: Shuffle %i\n", pgc->pg_playback_mode & 0x7f ); } if(pgc->nr_of_programs != 0) { @@ -760,8 +814,23 @@ void ifoPrint_TT_SRPT(tt_srpt_t *tt_srpt) { printf("\tNumber of PTTs: %i\n", tt_srpt->title[i].nr_of_ptts); printf("\tNumber of angles: %i\n", tt_srpt->title[i].nr_of_angles); - printf("\tTitle playback type: %02x\n", /* XXX: TODO FIXME */ - *(uint8_t *)&(tt_srpt->title[i].pb_ty)); + printf("\tTitle playback type: %s%s%s%s%s%s%s\n", + tt_srpt->title[i].pb_ty.multi_or_random_pgc_title ? + " One Random PGC Title or Multi PGC Title" : + " One Sequential PGC Title", + tt_srpt->title[i].pb_ty.jlc_exists_in_cell_cmd ? + "" : ", No Link/Jump/Call exists in Cell command", + tt_srpt->title[i].pb_ty.jlc_exists_in_prepost_cmd ? + "" : ", No Link/Jump/Call exists in Pre- and/or Post-command", + tt_srpt->title[i].pb_ty.jlc_exists_in_button_cmd ? + "" : ", No Link/Jump/Call exists in Button command", + tt_srpt->title[i].pb_ty.jlc_exists_in_tt_dom ? + "" : ", No Link/Jump/Call exists in TT_DOM", + tt_srpt->title[i].pb_ty.chapter_search_or_play ? + ", UOP1 (TT_Play and PTT_Search) prohibited" : "", + tt_srpt->title[i].pb_ty.title_or_time_play ? + ", UOP0 (Time_Play and Time_Search) prohibited" : "" + ); printf("\tParental ID field: %04x\n", tt_srpt->title[i].parental_id); printf("\tTitle set starting sector %08x\n", @@ -776,6 +845,8 @@ void ifoPrint_VTS_PTT_SRPT(vts_ptt_srpt_t *vts_ptt_srpt) { vts_ptt_srpt->nr_of_srpts, vts_ptt_srpt->last_byte); for(i=0;i<vts_ptt_srpt->nr_of_srpts;i++) { + printf("\nVTS_PTT number %d has a offset %d relative to VTS_PTT_SRPT\n", + i + 1, vts_ptt_srpt->ttu_offset[i]); for(j=0;j<vts_ptt_srpt->title[i].nr_of_ptts;j++) { printf("VTS_PTT_SRPT - Title %3i part %3i: PGC: %3i PG: %3i\n", i + 1, j + 1, @@ -786,35 +857,30 @@ void ifoPrint_VTS_PTT_SRPT(vts_ptt_srpt_t *vts_ptt_srpt) { } -static void hexdump(uint8_t *ptr, int len) { - while(len--) - printf("%02x ", *ptr++); -} - void ifoPrint_PTL_MAIT(ptl_mait_t *ptl_mait) { - int i, j; + int i, level, vts; printf("Number of Countries: %i\n", ptl_mait->nr_of_countries); printf("Number of VTSs: %i\n", ptl_mait->nr_of_vtss); - /* printf("Last byte: %i\n", ptl_mait->last_byte); */ + printf("Last byte: %i\n", ptl_mait->last_byte); for(i = 0; i < ptl_mait->nr_of_countries; i++) { - printf("Country code: %c%c\n", + + printf("Start byte: %i\n", ptl_mait->countries[i].pf_ptl_mai_start_byte); + printf("Parental Masks for country: %c%c\n", ptl_mait->countries[i].country_code >> 8, ptl_mait->countries[i].country_code & 0xff); - /* - printf("Start byte: %04x %i\n", - ptl_mait->countries[i].pf_ptl_mai_start_byte, - ptl_mait->countries[i].pf_ptl_mai_start_byte); - */ - /* This seems to be pointing at a array with 8 2byte fields per VTS - ? and one extra for the menu? always an odd number of VTSs on - all the dics I tested so it might be padding to even also. - If it is for the menu it probably the first entry. */ - for(j=0;j<8;j++) { - hexdump( (uint8_t *)ptl_mait->countries - PTL_MAIT_COUNTRY_SIZE - + ptl_mait->countries[i].pf_ptl_mai_start_byte - + j*(ptl_mait->nr_of_vtss+1)*2, (ptl_mait->nr_of_vtss+1)*2); + + for(vts = 0; vts <= ptl_mait->nr_of_vtss; vts++) { + if( vts == 0 ) { + printf("VMG "); + } else { + printf("VTS %2d ", vts); + } + for(level = 0; level < 8; level++) { + printf("%d: %04x ", level, + ptl_mait->countries[i].pf_ptl_mai[vts][level] ); + } printf("\n"); } } @@ -825,10 +891,11 @@ void ifoPrint_VTS_TMAPT(vts_tmapt_t *vts_tmapt) { int i, j; printf("Number of VTS_TMAPS: %i\n", vts_tmapt->nr_of_tmaps); - /*printf("Last byte: %i\n", vts_tmapt->last_byte);*/ - + printf("Last byte: %i\n", vts_tmapt->last_byte); + for(i = 0; i < vts_tmapt->nr_of_tmaps; i++) { - printf("TMAP %i\n", i); + printf("TMAP %i\n", i + 1); + printf(" offset %d relative to VTS_TMAPTI\n", vts_tmapt->tmap_offset[i]); printf(" Time unit (seconds): %i\n", vts_tmapt->tmap[i].tmu); printf(" Number of entries: %i\n", vts_tmapt->tmap[i].nr_of_entries); timeunit = vts_tmapt->tmap[i].tmu; @@ -887,9 +954,10 @@ void ifoPrint_PGCI_UT(pgci_ut_t *pgci_ut) { printf("Number of Menu Language Units (PGCI_LU): %3i\n", pgci_ut->nr_of_lus); for(i = 0; i < pgci_ut->nr_of_lus; i++) { - printf("\nMenu Language Code: %c%c\n", + printf("\nMenu Language Code: %c%c (%c)\n", pgci_ut->lu[i].lang_code >> 8, - pgci_ut->lu[i].lang_code & 0xff); + pgci_ut->lu[i].lang_code & 0xff, + pgci_ut->lu[i].lang_extension ? pgci_ut->lu[i].lang_extension :' '); printf("Menu Existence: %02x\n", pgci_ut->lu[i].exists); ifoPrint_PGCIT(pgci_ut->lu[i].pgcit); } @@ -902,31 +970,31 @@ static void ifoPrint_VTS_ATTRIBUTES(vts_attributes_t *vts_attributes) { printf("VTS_CAT Application type: %08x\n", vts_attributes->vts_cat); printf("Video attributes of VTSM_VOBS: "); - ifoPrint_video_attributes(5, &vts_attributes->vtsm_vobs_attr); + ifoPrint_video_attributes(&vts_attributes->vtsm_vobs_attr); printf("\n"); printf("Number of Audio streams: %i\n", vts_attributes->nr_of_vtsm_audio_streams); if(vts_attributes->nr_of_vtsm_audio_streams > 0) { printf("\tstream %i attributes: ", 1); - ifoPrint_audio_attributes(5, &vts_attributes->vtsm_audio_attr); + ifoPrint_audio_attributes(&vts_attributes->vtsm_audio_attr); printf("\n"); } printf("Number of Subpicture streams: %i\n", vts_attributes->nr_of_vtsm_subp_streams); if(vts_attributes->nr_of_vtsm_subp_streams > 0) { printf("\tstream %2i attributes: ", 1); - ifoPrint_subp_attributes(5, &vts_attributes->vtsm_subp_attr); + ifoPrint_subp_attributes(&vts_attributes->vtsm_subp_attr); printf("\n"); } printf("Video attributes of VTSTT_VOBS: "); - ifoPrint_video_attributes(5, &vts_attributes->vtstt_vobs_video_attr); + ifoPrint_video_attributes(&vts_attributes->vtstt_vobs_video_attr); printf("\n"); printf("Number of Audio streams: %i\n", vts_attributes->nr_of_vtstt_audio_streams); for(i = 0; i < vts_attributes->nr_of_vtstt_audio_streams; i++) { printf("\tstream %i attributes: ", i); - ifoPrint_audio_attributes(5, &vts_attributes->vtstt_audio_attr[i]); + ifoPrint_audio_attributes(&vts_attributes->vtstt_audio_attr[i]); printf("\n"); } @@ -934,7 +1002,7 @@ static void ifoPrint_VTS_ATTRIBUTES(vts_attributes_t *vts_attributes) { vts_attributes->nr_of_vtstt_subp_streams); for(i = 0; i < vts_attributes->nr_of_vtstt_subp_streams; i++) { printf("\tstream %2i attributes: ", i); - ifoPrint_subp_attributes(5, &vts_attributes->vtstt_subp_attr[i]); + ifoPrint_subp_attributes(&vts_attributes->vtstt_subp_attr[i]); printf("\n"); } } @@ -946,6 +1014,8 @@ void ifoPrint_VTS_ATRT(vts_atrt_t *vts_atrt) { printf("Number of Video Title Sets: %3i\n", vts_atrt->nr_of_vtss); for(i = 0; i < vts_atrt->nr_of_vtss; i++) { printf("\nVideo Title Set %i\n", i + 1); + printf(" offset %d relative to VMG_VTS_ATRT\n", + vts_atrt->vts_atrt_offsets[i]); ifoPrint_VTS_ATTRIBUTES(&vts_atrt->vts[i]); } } diff --git a/src/input/libdvdread/ifo_read.c b/src/input/libdvdread/ifo_read.c index 6dd5d3d5d..7bc9a2769 100644 --- a/src/input/libdvdread/ifo_read.c +++ b/src/input/libdvdread/ifo_read.c @@ -1,6 +1,7 @@ /* - * Copyright (C) 2000, 2001, 2002 Björn Englund <d4bjorn@dtek.chalmers.se>, - * Håkan Hjort <d95hjort@dtek.chalmers.se> + * Copyright (C) 2000, 2001, 2002, 2003 + * Björn Englund <d4bjorn@dtek.chalmers.se>, + * Håkan Hjort <d95hjort@dtek.chalmers.se> * * 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 @@ -17,25 +18,29 @@ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA */ +#include "config.h" + #include <stdio.h> #include <stdlib.h> - #include <inttypes.h> #include <string.h> -#include <assert.h> - -#include "dvd_reader.h" -#include "config.h" /* Needed for WORDS_BIGENDIAN */ #include "bswap.h" #include "ifo_types.h" #include "ifo_read.h" +#include "dvd_reader.h" +#include "dvdread_internal.h" #ifndef DVD_BLOCK_LEN #define DVD_BLOCK_LEN 2048 #endif #ifndef NDEBUG +#define CHECK_ZERO0(arg) \ + if(arg != 0) { \ + fprintf(stderr, "*** Zero check failed in %s:%i\n for %s = 0x%x\n", \ + __FILE__, __LINE__, # arg, arg); \ + } #define CHECK_ZERO(arg) \ if(memcmp(my_friendly_zeros, &arg, sizeof(arg))) { \ unsigned int i_CZ; \ @@ -47,6 +52,7 @@ } static const uint8_t my_friendly_zeros[2048]; #else +#define CHECK_ZERO0(arg) (void)(arg) #define CHECK_ZERO(arg) (void)(arg) #endif @@ -323,33 +329,33 @@ static int ifoRead_VMG(ifo_handle_t *ifofile) { CHECK_ZERO(vmgi_mat->zero_8); CHECK_ZERO(vmgi_mat->zero_9); CHECK_ZERO(vmgi_mat->zero_10); - assert(vmgi_mat->vmg_last_sector != 0); - assert(vmgi_mat->vmgi_last_sector != 0); - assert(vmgi_mat->vmgi_last_sector * 2 <= vmgi_mat->vmg_last_sector); - assert(vmgi_mat->vmg_nr_of_volumes != 0); - assert(vmgi_mat->vmg_this_volume_nr != 0); - assert(vmgi_mat->vmg_this_volume_nr <= vmgi_mat->vmg_nr_of_volumes); - assert(vmgi_mat->disc_side == 1 || vmgi_mat->disc_side == 2); - assert(vmgi_mat->vmg_nr_of_title_sets != 0); - assert(vmgi_mat->vmgi_last_byte >= 341); - assert(vmgi_mat->vmgi_last_byte / DVD_BLOCK_LEN <= + CHECK_VALUE(vmgi_mat->vmg_last_sector != 0); + CHECK_VALUE(vmgi_mat->vmgi_last_sector != 0); + CHECK_VALUE(vmgi_mat->vmgi_last_sector * 2 <= vmgi_mat->vmg_last_sector); + CHECK_VALUE(vmgi_mat->vmgi_last_sector * 2 <= vmgi_mat->vmg_last_sector); + CHECK_VALUE(vmgi_mat->vmg_nr_of_volumes != 0); + CHECK_VALUE(vmgi_mat->vmg_this_volume_nr != 0); + CHECK_VALUE(vmgi_mat->vmg_this_volume_nr <= vmgi_mat->vmg_nr_of_volumes); + CHECK_VALUE(vmgi_mat->disc_side == 1 || vmgi_mat->disc_side == 2); + CHECK_VALUE(vmgi_mat->vmg_nr_of_title_sets != 0); + CHECK_VALUE(vmgi_mat->vmgi_last_byte >= 341); + CHECK_VALUE(vmgi_mat->vmgi_last_byte / DVD_BLOCK_LEN <= vmgi_mat->vmgi_last_sector); - /* It seems that first_play_pgc might be optional. */ - assert(vmgi_mat->first_play_pgc != 0 && - vmgi_mat->first_play_pgc < vmgi_mat->vmgi_last_byte); - assert(vmgi_mat->vmgm_vobs == 0 || + /* It seems that first_play_pgc is optional. */ + CHECK_VALUE(vmgi_mat->first_play_pgc < vmgi_mat->vmgi_last_byte); + CHECK_VALUE(vmgi_mat->vmgm_vobs == 0 || (vmgi_mat->vmgm_vobs > vmgi_mat->vmgi_last_sector && vmgi_mat->vmgm_vobs < vmgi_mat->vmg_last_sector)); - assert(vmgi_mat->tt_srpt <= vmgi_mat->vmgi_last_sector); - assert(vmgi_mat->vmgm_pgci_ut <= vmgi_mat->vmgi_last_sector); - assert(vmgi_mat->ptl_mait <= vmgi_mat->vmgi_last_sector); - assert(vmgi_mat->vts_atrt <= vmgi_mat->vmgi_last_sector); - assert(vmgi_mat->txtdt_mgi <= vmgi_mat->vmgi_last_sector); - assert(vmgi_mat->vmgm_c_adt <= vmgi_mat->vmgi_last_sector); - assert(vmgi_mat->vmgm_vobu_admap <= vmgi_mat->vmgi_last_sector); + CHECK_VALUE(vmgi_mat->tt_srpt <= vmgi_mat->vmgi_last_sector); + CHECK_VALUE(vmgi_mat->vmgm_pgci_ut <= vmgi_mat->vmgi_last_sector); + CHECK_VALUE(vmgi_mat->ptl_mait <= vmgi_mat->vmgi_last_sector); + CHECK_VALUE(vmgi_mat->vts_atrt <= vmgi_mat->vmgi_last_sector); + CHECK_VALUE(vmgi_mat->txtdt_mgi <= vmgi_mat->vmgi_last_sector); + CHECK_VALUE(vmgi_mat->vmgm_c_adt <= vmgi_mat->vmgi_last_sector); + CHECK_VALUE(vmgi_mat->vmgm_vobu_admap <= vmgi_mat->vmgi_last_sector); - assert(vmgi_mat->nr_of_vmgm_audio_streams <= 1); - assert(vmgi_mat->nr_of_vmgm_subp_streams <= 1); + CHECK_VALUE(vmgi_mat->nr_of_vmgm_audio_streams <= 1); + CHECK_VALUE(vmgi_mat->nr_of_vmgm_subp_streams <= 1); return 1; } @@ -425,34 +431,44 @@ static int ifoRead_VTS(ifo_handle_t *ifofile) { CHECK_ZERO(vtsi_mat->zero_18); CHECK_ZERO(vtsi_mat->zero_19); CHECK_ZERO(vtsi_mat->zero_20); - assert(vtsi_mat->vtsi_last_sector*2 <= vtsi_mat->vts_last_sector); - assert(vtsi_mat->vtsi_last_byte/DVD_BLOCK_LEN <= vtsi_mat->vtsi_last_sector); - assert(vtsi_mat->vtsm_vobs == 0 || - (vtsi_mat->vtsm_vobs > vtsi_mat->vtsi_last_sector && + CHECK_ZERO(vtsi_mat->zero_21); + CHECK_VALUE(vtsi_mat->vtsi_last_sector*2 <= vtsi_mat->vts_last_sector); + CHECK_VALUE(vtsi_mat->vtsi_last_byte/DVD_BLOCK_LEN <= vtsi_mat->vtsi_last_sector); + CHECK_VALUE(vtsi_mat->vtsm_vobs == 0 || + (vtsi_mat->vtsm_vobs > vtsi_mat->vtsi_last_sector && vtsi_mat->vtsm_vobs < vtsi_mat->vts_last_sector)); - assert(vtsi_mat->vtstt_vobs == 0 || + CHECK_VALUE(vtsi_mat->vtstt_vobs == 0 || (vtsi_mat->vtstt_vobs > vtsi_mat->vtsi_last_sector && vtsi_mat->vtstt_vobs < vtsi_mat->vts_last_sector)); - assert(vtsi_mat->vts_ptt_srpt <= vtsi_mat->vtsi_last_sector); - assert(vtsi_mat->vts_pgcit <= vtsi_mat->vtsi_last_sector); - assert(vtsi_mat->vtsm_pgci_ut <= vtsi_mat->vtsi_last_sector); - assert(vtsi_mat->vts_tmapt <= vtsi_mat->vtsi_last_sector); - assert(vtsi_mat->vtsm_c_adt <= vtsi_mat->vtsi_last_sector); - assert(vtsi_mat->vtsm_vobu_admap <= vtsi_mat->vtsi_last_sector); - assert(vtsi_mat->vts_c_adt <= vtsi_mat->vtsi_last_sector); - assert(vtsi_mat->vts_vobu_admap <= vtsi_mat->vtsi_last_sector); - - assert(vtsi_mat->nr_of_vtsm_audio_streams <= 1); - assert(vtsi_mat->nr_of_vtsm_subp_streams <= 1); - - assert(vtsi_mat->nr_of_vts_audio_streams <= 8); + CHECK_VALUE(vtsi_mat->vts_ptt_srpt <= vtsi_mat->vtsi_last_sector); + CHECK_VALUE(vtsi_mat->vts_pgcit <= vtsi_mat->vtsi_last_sector); + CHECK_VALUE(vtsi_mat->vtsm_pgci_ut <= vtsi_mat->vtsi_last_sector); + CHECK_VALUE(vtsi_mat->vts_tmapt <= vtsi_mat->vtsi_last_sector); + CHECK_VALUE(vtsi_mat->vtsm_c_adt <= vtsi_mat->vtsi_last_sector); + CHECK_VALUE(vtsi_mat->vtsm_vobu_admap <= vtsi_mat->vtsi_last_sector); + CHECK_VALUE(vtsi_mat->vts_c_adt <= vtsi_mat->vtsi_last_sector); + CHECK_VALUE(vtsi_mat->vts_vobu_admap <= vtsi_mat->vtsi_last_sector); + + CHECK_VALUE(vtsi_mat->nr_of_vtsm_audio_streams <= 1); + CHECK_VALUE(vtsi_mat->nr_of_vtsm_subp_streams <= 1); + + CHECK_VALUE(vtsi_mat->nr_of_vts_audio_streams <= 8); for(i = vtsi_mat->nr_of_vts_audio_streams; i < 8; i++) CHECK_ZERO(vtsi_mat->vts_audio_attr[i]); - assert(vtsi_mat->nr_of_vts_subp_streams <= 32); + CHECK_VALUE(vtsi_mat->nr_of_vts_subp_streams <= 32); for(i = vtsi_mat->nr_of_vts_subp_streams; i < 32; i++) CHECK_ZERO(vtsi_mat->vts_subp_attr[i]); - + + for(i = 0; i < 8; i++) { + CHECK_ZERO0(vtsi_mat->vts_mu_audio_attr[i].zero1); + CHECK_ZERO0(vtsi_mat->vts_mu_audio_attr[i].zero2); + CHECK_ZERO0(vtsi_mat->vts_mu_audio_attr[i].zero3); + CHECK_ZERO0(vtsi_mat->vts_mu_audio_attr[i].zero4); + CHECK_ZERO0(vtsi_mat->vts_mu_audio_attr[i].zero5); + CHECK_ZERO(vtsi_mat->vts_mu_audio_attr[i].zero6); + } + return 1; } @@ -473,7 +489,7 @@ static int ifoRead_PGC_COMMAND_TBL(ifo_handle_t *ifofile, B2N_16(cmd_tbl->nr_of_post); B2N_16(cmd_tbl->nr_of_cell); - assert(cmd_tbl->nr_of_pre + cmd_tbl->nr_of_post + cmd_tbl->nr_of_cell<= 255); + CHECK_VALUE(cmd_tbl->nr_of_pre + cmd_tbl->nr_of_post + cmd_tbl->nr_of_cell<= 255); if(cmd_tbl->nr_of_pre != 0) { unsigned int pre_cmds_size = cmd_tbl->nr_of_pre * COMMAND_DATA_SIZE; @@ -575,9 +591,9 @@ static int ifoRead_CELL_PLAYBACK_TBL(ifo_handle_t *ifofile, B2N_32(cell_playback[i].last_sector); /* Changed < to <= because this was false in the movie 'Pi'. */ - assert(cell_playback[i].last_vobu_start_sector <= + CHECK_VALUE(cell_playback[i].last_vobu_start_sector <= cell_playback[i].last_sector); - assert(cell_playback[i].first_sector <= + CHECK_VALUE(cell_playback[i].first_sector <= cell_playback[i].last_vobu_start_sector); } @@ -630,7 +646,7 @@ static int ifoRead_PGC(ifo_handle_t *ifofile, pgc_t *pgc, unsigned int offset) { B2N_32(pgc->palette[i]); CHECK_ZERO(pgc->zero_1); - assert(pgc->nr_of_programs <= pgc->nr_of_cells); + CHECK_VALUE(pgc->nr_of_programs <= pgc->nr_of_cells); /* verify time (look at print_time) */ for(i = 0; i < 8; i++) @@ -644,13 +660,13 @@ static int ifoRead_PGC(ifo_handle_t *ifofile, pgc_t *pgc, unsigned int offset) { if(pgc->nr_of_programs == 0) { CHECK_ZERO(pgc->still_time); CHECK_ZERO(pgc->pg_playback_mode); /* ?? */ - assert(pgc->program_map_offset == 0); - assert(pgc->cell_playback_offset == 0); - assert(pgc->cell_position_offset == 0); + CHECK_VALUE(pgc->program_map_offset == 0); + CHECK_VALUE(pgc->cell_playback_offset == 0); + CHECK_VALUE(pgc->cell_position_offset == 0); } else { - assert(pgc->program_map_offset != 0); - assert(pgc->cell_playback_offset != 0); - assert(pgc->cell_position_offset != 0); + CHECK_VALUE(pgc->program_map_offset != 0); + CHECK_VALUE(pgc->cell_playback_offset != 0); + CHECK_VALUE(pgc->cell_position_offset != 0); } if(pgc->command_tbl_offset != 0) { @@ -731,11 +747,10 @@ int ifoRead_FP_PGC(ifo_handle_t *ifofile) { if(!ifofile->vmgi_mat) return 0; - /* It seems that first_play_pgc might be optional after all. */ - if(ifofile->vmgi_mat->first_play_pgc == 0) { /* mandatory */ - ifofile->first_play_pgc = 0; - return 0; /* change this to a 1 if it's optional. */ - } + /* It seems that first_play_pgc is optional after all. */ + ifofile->first_play_pgc = 0; + if(ifofile->vmgi_mat->first_play_pgc == 0) + return 1; ifofile->first_play_pgc = (pgc_t *)malloc(sizeof(pgc_t)); if(!ifofile->first_play_pgc) @@ -828,22 +843,22 @@ int ifoRead_TT_SRPT(ifo_handle_t *ifofile) { CHECK_ZERO(tt_srpt->zero_1); - assert(tt_srpt->nr_of_srpts != 0); - assert(tt_srpt->nr_of_srpts < 100); /* ?? */ - assert((int)tt_srpt->nr_of_srpts * sizeof(title_info_t) <= info_length); + CHECK_VALUE(tt_srpt->nr_of_srpts != 0); + CHECK_VALUE(tt_srpt->nr_of_srpts < 100); /* ?? */ + CHECK_VALUE((int)tt_srpt->nr_of_srpts * sizeof(title_info_t) <= info_length); for(i = 0; i < tt_srpt->nr_of_srpts; i++) { - assert(tt_srpt->title[i].pb_ty.zero_1 == 0); - assert(tt_srpt->title[i].nr_of_angles != 0); - assert(tt_srpt->title[i].nr_of_angles < 10); - /* assert(tt_srpt->title[i].nr_of_ptts != 0); */ + CHECK_VALUE(tt_srpt->title[i].pb_ty.zero_1 == 0); + CHECK_VALUE(tt_srpt->title[i].nr_of_angles != 0); + CHECK_VALUE(tt_srpt->title[i].nr_of_angles < 10); + /* CHECK_VALUE(tt_srpt->title[i].nr_of_ptts != 0); */ /* XXX: this assertion breaks Ghostbusters: */ - assert(tt_srpt->title[i].nr_of_ptts < 1000); /* ?? */ - assert(tt_srpt->title[i].title_set_nr != 0); - assert(tt_srpt->title[i].title_set_nr < 100); /* ?? */ - assert(tt_srpt->title[i].vts_ttn != 0); - assert(tt_srpt->title[i].vts_ttn < 100); /* ?? */ - /* assert(tt_srpt->title[i].title_set_sector != 0); */ + CHECK_VALUE(tt_srpt->title[i].nr_of_ptts < 1000); /* ?? */ + CHECK_VALUE(tt_srpt->title[i].title_set_nr != 0); + CHECK_VALUE(tt_srpt->title[i].title_set_nr < 100); /* ?? */ + CHECK_VALUE(tt_srpt->title[i].vts_ttn != 0); + CHECK_VALUE(tt_srpt->title[i].vts_ttn < 100); /* ?? */ + /* CHECK_VALUE(tt_srpt->title[i].title_set_sector != 0); */ } /* Make this a function */ @@ -909,8 +924,8 @@ int ifoRead_VTS_PTT_SRPT(ifo_handle_t *ifofile) { B2N_32(vts_ptt_srpt->last_byte); CHECK_ZERO(vts_ptt_srpt->zero_1); - assert(vts_ptt_srpt->nr_of_srpts != 0); - assert(vts_ptt_srpt->nr_of_srpts < 100); /* ?? */ + CHECK_VALUE(vts_ptt_srpt->nr_of_srpts != 0); + CHECK_VALUE(vts_ptt_srpt->nr_of_srpts < 100); /* ?? */ info_length = vts_ptt_srpt->last_byte + 1 - VTS_PTT_SRPT_SIZE; @@ -934,8 +949,10 @@ int ifoRead_VTS_PTT_SRPT(ifo_handle_t *ifofile) { Magic Knight Rayearth Daybreak is mastered very strange and has Titles with 0 PTTs. They all have a data[i] offsets beyond the end of of the vts_ptt_srpt structure. */ - assert(data[i] + sizeof(ptt_info_t) <= vts_ptt_srpt->last_byte + 1 + 4); + CHECK_VALUE(data[i] + sizeof(ptt_info_t) <= vts_ptt_srpt->last_byte + 1 + 4); } + + vts_ptt_srpt->ttu_offset = data; vts_ptt_srpt->title = malloc(vts_ptt_srpt->nr_of_srpts * sizeof(ttu_t)); if(!vts_ptt_srpt->title) { @@ -954,7 +971,7 @@ int ifoRead_VTS_PTT_SRPT(ifo_handle_t *ifofile) { Magic Knight Rayearth Daybreak is mastered very strange and has Titles with 0 PTTs. */ if(n < 0) n = 0; - assert(n % 4 == 0); + CHECK_VALUE(n % 4 == 0); vts_ptt_srpt->title[i].nr_of_ptts = n / 4; vts_ptt_srpt->title[i].ptt = malloc(n * sizeof(ptt_info_t)); @@ -968,14 +985,13 @@ int ifoRead_VTS_PTT_SRPT(ifo_handle_t *ifofile) { } for(j = 0; j < vts_ptt_srpt->title[i].nr_of_ptts; j++) { /* The assert placed here because of Magic Knight Rayearth Daybreak */ - assert(data[i] + sizeof(ptt_info_t) <= vts_ptt_srpt->last_byte + 1); + CHECK_VALUE(data[i] + sizeof(ptt_info_t) <= vts_ptt_srpt->last_byte + 1); vts_ptt_srpt->title[i].ptt[j].pgcn = *(uint16_t*)(((char *)data) + data[i] + 4*j - VTS_PTT_SRPT_SIZE); vts_ptt_srpt->title[i].ptt[j].pgn = *(uint16_t*)(((char *)data) + data[i] + 4*j + 2 - VTS_PTT_SRPT_SIZE); } } - free(data); for(i = 0; i < vts_ptt_srpt->nr_of_srpts; i++) { for(j = 0; j < vts_ptt_srpt->title[i].nr_of_ptts; j++) { @@ -985,12 +1001,12 @@ int ifoRead_VTS_PTT_SRPT(ifo_handle_t *ifofile) { } for(i = 0; i < vts_ptt_srpt->nr_of_srpts; i++) { - assert(vts_ptt_srpt->title[i].nr_of_ptts < 1000); /* ?? */ + CHECK_VALUE(vts_ptt_srpt->title[i].nr_of_ptts < 1000); /* ?? */ for(j = 0; j < vts_ptt_srpt->title[i].nr_of_ptts; j++) { - assert(vts_ptt_srpt->title[i].ptt[j].pgcn != 0 ); - assert(vts_ptt_srpt->title[i].ptt[j].pgcn < 1000); /* ?? */ - assert(vts_ptt_srpt->title[i].ptt[j].pgn != 0); - assert(vts_ptt_srpt->title[i].ptt[j].pgn < 100); /* ?? */ + CHECK_VALUE(vts_ptt_srpt->title[i].ptt[j].pgcn != 0 ); + CHECK_VALUE(vts_ptt_srpt->title[i].ptt[j].pgcn < 1000); /* ?? */ + CHECK_VALUE(vts_ptt_srpt->title[i].ptt[j].pgn != 0); + CHECK_VALUE(vts_ptt_srpt->title[i].ptt[j].pgn < 100); /* ?? */ } } @@ -1006,6 +1022,7 @@ void ifoFree_VTS_PTT_SRPT(ifo_handle_t *ifofile) { int i; for(i = 0; i < ifofile->vts_ptt_srpt->nr_of_srpts; i++) free(ifofile->vts_ptt_srpt->title[i].ptt); + free(ifofile->vts_ptt_srpt->ttu_offset); free(ifofile->vts_ptt_srpt->title); free(ifofile->vts_ptt_srpt); ifofile->vts_ptt_srpt = 0; @@ -1016,7 +1033,7 @@ void ifoFree_VTS_PTT_SRPT(ifo_handle_t *ifofile) { int ifoRead_PTL_MAIT(ifo_handle_t *ifofile) { ptl_mait_t *ptl_mait; int info_length; - unsigned int i; + unsigned int i, j; if(!ifofile) return 0; @@ -1046,26 +1063,29 @@ int ifoRead_PTL_MAIT(ifo_handle_t *ifofile) { B2N_16(ptl_mait->nr_of_vtss); B2N_32(ptl_mait->last_byte); - info_length = ptl_mait->last_byte + 1 - PTL_MAIT_SIZE; + CHECK_VALUE(ptl_mait->nr_of_countries != 0); + CHECK_VALUE(ptl_mait->nr_of_countries < 100); /* ?? */ + CHECK_VALUE(ptl_mait->nr_of_vtss != 0); + CHECK_VALUE(ptl_mait->nr_of_vtss < 100); /* ?? */ + CHECK_VALUE(ptl_mait->nr_of_countries * PTL_MAIT_COUNTRY_SIZE + <= ptl_mait->last_byte + 1 - PTL_MAIT_SIZE); - assert(ptl_mait->nr_of_countries != 0); - assert(ptl_mait->nr_of_countries < 100); /* ?? */ - assert(ptl_mait->nr_of_vtss != 0); - assert(ptl_mait->nr_of_vtss < 100); /* ?? */ - assert(ptl_mait->nr_of_countries * PTL_MAIT_COUNTRY_SIZE <= info_length); - - /* Change this to read and 'translate' the tables too. - I.e don't read so much here */ + info_length = ptl_mait->nr_of_countries * sizeof(ptl_mait_country_t); ptl_mait->countries = (ptl_mait_country_t *)malloc(info_length); if(!ptl_mait->countries) { free(ptl_mait); ifofile->ptl_mait = 0; return 0; } - if(!(DVDReadBytes(ifofile->file, ptl_mait->countries, info_length))) { - fprintf(stderr, "libdvdread: Unable to read PTL_MAIT.\n"); - ifoFree_PTL_MAIT(ifofile); - return 0; + + for(i = 0; i < ptl_mait->nr_of_countries; i++) { + if(!(DVDReadBytes(ifofile->file, &ptl_mait->countries[i], PTL_MAIT_COUNTRY_SIZE))) { + fprintf(stderr, "libdvdread: Unable to read PTL_MAIT.\n"); + free(ptl_mait->countries); + free(ptl_mait); + ifofile->ptl_mait = 0; + return 0; + } } for(i = 0; i < ptl_mait->nr_of_countries; i++) { @@ -1076,18 +1096,78 @@ int ifoRead_PTL_MAIT(ifo_handle_t *ifofile) { for(i = 0; i < ptl_mait->nr_of_countries; i++) { CHECK_ZERO(ptl_mait->countries[i].zero_1); CHECK_ZERO(ptl_mait->countries[i].zero_2); - assert(ptl_mait->countries[i].pf_ptl_mai_start_byte + - 8 * (ptl_mait->nr_of_vtss + 1) * 2 <= ptl_mait->last_byte + 1); + CHECK_VALUE(ptl_mait->countries[i].pf_ptl_mai_start_byte + + 8*2 * (ptl_mait->nr_of_vtss + 1) <= ptl_mait->last_byte + 1); } + for(i = 0; i < ptl_mait->nr_of_countries; i++) { + uint16_t *pf_temp; + + if(!DVDFileSeek_(ifofile->file, + ifofile->vmgi_mat->ptl_mait * DVD_BLOCK_LEN + + ptl_mait->countries[i].pf_ptl_mai_start_byte)) { + fprintf(stderr, "libdvdread: Unable to seak PTL_MAIT table.\n"); + free(ptl_mait->countries); + free(ptl_mait); + return 0; + } + info_length = (ptl_mait->nr_of_vtss + 1) * sizeof(pf_level_t); + pf_temp = (uint16_t *)malloc(info_length); + if(!pf_temp) { + for(j = 0; j < i ; j++) { + free(ptl_mait->countries[j].pf_ptl_mai); + } + free(ptl_mait->countries); + free(ptl_mait); + return 0; + } + if(!(DVDReadBytes(ifofile->file, pf_temp, info_length))) { + fprintf(stderr, "libdvdread: Unable to read PTL_MAIT table.\n"); + free(pf_temp); + for(j = 0; j < i ; j++) { + free(ptl_mait->countries[j].pf_ptl_mai); + } + free(ptl_mait->countries); + free(ptl_mait); + return 0; + } + for (j = 0; j < ((ptl_mait->nr_of_vtss + 1) * 8); j++) { + B2N_16(pf_temp[j]); + } + ptl_mait->countries[i].pf_ptl_mai = (pf_level_t *)malloc(info_length); + if(!ptl_mait->countries[i].pf_ptl_mai) { + free(pf_temp); + for(j = 0; j < i ; j++) { + free(ptl_mait->countries[j].pf_ptl_mai); + } + free(ptl_mait->countries); + free(ptl_mait); + return 0; + } + { /* Transpose the array so we can use C indexing. */ + int level, vts; + for(level = 0; level < 8; level++) { + for(vts = 0; vts <= ptl_mait->nr_of_vtss; vts++) { + ptl_mait->countries[i].pf_ptl_mai[vts][level] = + pf_temp[(7-level)*(ptl_mait->nr_of_vtss+1) + vts]; + } + } + free(pf_temp); + } + } return 1; } void ifoFree_PTL_MAIT(ifo_handle_t *ifofile) { + unsigned int i; + if(!ifofile) return; if(ifofile->ptl_mait) { + for(i = 0; i < ifofile->ptl_mait->nr_of_countries; i++) { + free(ifofile->ptl_mait->countries[i].pf_ptl_mai); + } free(ifofile->ptl_mait->countries); free(ifofile->ptl_mait); ifofile->ptl_mait = 0; @@ -1109,12 +1189,13 @@ int ifoRead_VTS_TMAPT(ifo_handle_t *ifofile) { if(ifofile->vtsi_mat->vts_tmapt == 0) { /* optional(?) */ ifofile->vts_tmapt = NULL; + fprintf(stderr,"Please send bug report - no VTS_TMAPT ?? \n"); return 1; } offset = ifofile->vtsi_mat->vts_tmapt * DVD_BLOCK_LEN; - if(!DVDFileSeek_(ifofile->file, offset)) + if(!DVDFileSeek_(ifofile->file, offset)) return 0; vts_tmapt = (vts_tmapt_t *)malloc(sizeof(vts_tmapt_t)); @@ -1143,6 +1224,8 @@ int ifoRead_VTS_TMAPT(ifo_handle_t *ifofile) { ifofile->vts_tmapt = NULL; return 0; } + + vts_tmapt->tmap_offset = vts_tmap_srp; if(!(DVDReadBytes(ifofile->file, vts_tmap_srp, info_length))) { fprintf(stderr, "libdvdread: Unable to read VTS_TMAPT.\n"); @@ -1151,6 +1234,11 @@ int ifoRead_VTS_TMAPT(ifo_handle_t *ifofile) { ifofile->vts_tmapt = NULL; return 0; } + + for (i = 0; i < vts_tmapt->nr_of_tmaps; i++) { + B2N_32(vts_tmap_srp[i]); + } + info_length = vts_tmapt->nr_of_tmaps * sizeof(vts_tmap_t); @@ -1161,17 +1249,17 @@ int ifoRead_VTS_TMAPT(ifo_handle_t *ifofile) { ifofile->vts_tmapt = NULL; return 0; } + memset(vts_tmapt->tmap, 0, info_length); /* So ifoFree_VTS_TMAPT works. */ for(i = 0; i < vts_tmapt->nr_of_tmaps; i++) { if(!DVDFileSeek_(ifofile->file, offset + vts_tmap_srp[i])) { - free(vts_tmap_srp); ifoFree_VTS_TMAPT(ifofile); return 0; } + if(!(DVDReadBytes(ifofile->file, &vts_tmapt->tmap[i], VTS_TMAP_SIZE))) { fprintf(stderr, "libdvdread: Unable to read VTS_TMAP.\n"); - free(vts_tmap_srp); ifoFree_VTS_TMAPT(ifofile); return 0; } @@ -1188,14 +1276,12 @@ int ifoRead_VTS_TMAPT(ifo_handle_t *ifofile) { vts_tmapt->tmap[i].map_ent = (map_ent_t *)malloc(info_length); if(!vts_tmapt->tmap[i].map_ent) { - free(vts_tmap_srp); ifoFree_VTS_TMAPT(ifofile); return 0; } if(!(DVDReadBytes(ifofile->file, vts_tmapt->tmap[i].map_ent, info_length))) { fprintf(stderr, "libdvdread: Unable to read VTS_TMAP_ENT.\n"); - free(vts_tmap_srp); ifoFree_VTS_TMAPT(ifofile); return 0; } @@ -1203,7 +1289,6 @@ int ifoRead_VTS_TMAPT(ifo_handle_t *ifofile) { for(j = 0; j < vts_tmapt->tmap[i].nr_of_entries; j++) B2N_32(vts_tmapt->tmap[i].map_ent[j]); } - free(vts_tmap_srp); return 1; } @@ -1219,6 +1304,7 @@ void ifoFree_VTS_TMAPT(ifo_handle_t *ifofile) { if(ifofile->vts_tmapt->tmap[i].map_ent) free(ifofile->vts_tmapt->tmap[i].map_ent); free(ifofile->vts_tmapt->tmap); + free(ifofile->vts_tmapt->tmap_offset); free(ifofile->vts_tmapt); ifofile->vts_tmapt = NULL; } @@ -1300,7 +1386,7 @@ static int ifoRead_C_ADT_internal(ifo_handle_t *ifofile, /* assert(c_adt->nr_of_vobs > 0); Magic Knight Rayearth Daybreak is mastered very strange and has Titles with a VOBS that has no cells. */ - assert(info_length % sizeof(cell_adr_t) == 0); + CHECK_VALUE(info_length % sizeof(cell_adr_t) == 0); /* assert(info_length / sizeof(cell_adr_t) >= c_adt->nr_of_vobs); Enemy of the State region 2 (de) has Titles where nr_of_vobs field @@ -1326,10 +1412,10 @@ static int ifoRead_C_ADT_internal(ifo_handle_t *ifofile, B2N_32(c_adt->cell_adr_table[i].last_sector); CHECK_ZERO(c_adt->cell_adr_table[i].zero_1); - assert(c_adt->cell_adr_table[i].vob_id > 0); - assert(c_adt->cell_adr_table[i].vob_id <= c_adt->nr_of_vobs); - assert(c_adt->cell_adr_table[i].cell_id > 0); - assert(c_adt->cell_adr_table[i].start_sector < + CHECK_VALUE(c_adt->cell_adr_table[i].vob_id > 0); + CHECK_VALUE(c_adt->cell_adr_table[i].vob_id <= c_adt->nr_of_vobs); + CHECK_VALUE(c_adt->cell_adr_table[i].cell_id > 0); + CHECK_VALUE(c_adt->cell_adr_table[i].start_sector < c_adt->cell_adr_table[i].last_sector); } @@ -1433,7 +1519,7 @@ static int ifoRead_VOBU_ADMAP_internal(ifo_handle_t *ifofile, /* assert(info_length > 0); Magic Knight Rayearth Daybreak is mastered very strange and has Titles with a VOBS that has no VOBUs. */ - assert(info_length % sizeof(uint32_t) == 0); + CHECK_VALUE(info_length % sizeof(uint32_t) == 0); vobu_admap->vobu_start_sectors = (uint32_t *)malloc(info_length); if(!vobu_admap->vobu_start_sectors) { @@ -1519,7 +1605,7 @@ static int ifoRead_PGCIT_internal(ifo_handle_t *ifofile, pgcit_t *pgcit, /* assert(pgcit->nr_of_pgci_srp != 0); Magic Knight Rayearth Daybreak is mastered very strange and has Titles with 0 PTTs. */ - assert(pgcit->nr_of_pgci_srp < 10000); /* ?? seen max of 1338 */ + CHECK_VALUE(pgcit->nr_of_pgci_srp < 10000); /* ?? seen max of 1338 */ info_length = pgcit->nr_of_pgci_srp * PGCI_SRP_SIZE; data = malloc(info_length); @@ -1542,12 +1628,12 @@ static int ifoRead_PGCIT_internal(ifo_handle_t *ifofile, pgcit_t *pgcit, ptr += PGCI_LU_SIZE; B2N_16(pgcit->pgci_srp[i].ptl_id_mask); B2N_32(pgcit->pgci_srp[i].pgc_start_byte); - assert(pgcit->pgci_srp[i].unknown1 == 0); + CHECK_VALUE(pgcit->pgci_srp[i].unknown1 == 0); } free(data); for(i = 0; i < pgcit->nr_of_pgci_srp; i++) - assert(pgcit->pgci_srp[i].pgc_start_byte + PGC_SIZE <= pgcit->last_byte+1); + CHECK_VALUE(pgcit->pgci_srp[i].pgc_start_byte + PGC_SIZE <= pgcit->last_byte+1); for(i = 0; i < pgcit->nr_of_pgci_srp; i++) { pgcit->pgci_srp[i].pgc = malloc(sizeof(pgc_t)); @@ -1639,9 +1725,9 @@ int ifoRead_PGCI_UT(ifo_handle_t *ifofile) { B2N_32(pgci_ut->last_byte); CHECK_ZERO(pgci_ut->zero_1); - assert(pgci_ut->nr_of_lus != 0); - assert(pgci_ut->nr_of_lus < 100); /* ?? 3-4 ? */ - assert((uint32_t)pgci_ut->nr_of_lus * PGCI_LU_SIZE < pgci_ut->last_byte); + CHECK_VALUE(pgci_ut->nr_of_lus != 0); + CHECK_VALUE(pgci_ut->nr_of_lus < 100); /* ?? 3-4 ? */ + CHECK_VALUE((uint32_t)pgci_ut->nr_of_lus * PGCI_LU_SIZE < pgci_ut->last_byte); info_length = pgci_ut->nr_of_lus * PGCI_LU_SIZE; data = malloc(info_length); @@ -1674,10 +1760,8 @@ int ifoRead_PGCI_UT(ifo_handle_t *ifofile) { free(data); for(i = 0; i < pgci_ut->nr_of_lus; i++) { - CHECK_ZERO(pgci_ut->lu[i].zero_1); - /* - Maybe this is only defined for v1.1 and later titles? - If the bits in 'lu[i].exists' are enumerated abcd efgh then: + /* Maybe this is only defined for v1.1 and later titles? */ + /* If the bits in 'lu[i].exists' are enumerated abcd efgh then: VTS_x_yy.IFO VIDEO_TS.IFO a == 0x83 "Root" 0x82 "Title" b == 0x84 "Subpicture" @@ -1685,7 +1769,7 @@ int ifoRead_PGCI_UT(ifo_handle_t *ifofile) { d == 0x86 "Angle" e == 0x87 "PTT" */ - assert((pgci_ut->lu[i].exists & 0x07) == 0); + CHECK_VALUE((pgci_ut->lu[i].exists & 0x07) == 0); } for(i = 0; i < pgci_ut->nr_of_lus; i++) { @@ -1769,21 +1853,21 @@ static int ifoRead_VTS_ATTRIBUTES(ifo_handle_t *ifofile, CHECK_ZERO(vts_attributes->zero_5); CHECK_ZERO(vts_attributes->zero_6); CHECK_ZERO(vts_attributes->zero_7); - assert(vts_attributes->nr_of_vtsm_audio_streams <= 1); - assert(vts_attributes->nr_of_vtsm_subp_streams <= 1); - assert(vts_attributes->nr_of_vtstt_audio_streams <= 8); + CHECK_VALUE(vts_attributes->nr_of_vtsm_audio_streams <= 1); + CHECK_VALUE(vts_attributes->nr_of_vtsm_subp_streams <= 1); + CHECK_VALUE(vts_attributes->nr_of_vtstt_audio_streams <= 8); for(i = vts_attributes->nr_of_vtstt_audio_streams; i < 8; i++) CHECK_ZERO(vts_attributes->vtstt_audio_attr[i]); - assert(vts_attributes->nr_of_vtstt_subp_streams <= 32); + CHECK_VALUE(vts_attributes->nr_of_vtstt_subp_streams <= 32); { unsigned int nr_coded; - assert(vts_attributes->last_byte + 1 >= VTS_ATTRIBUTES_MIN_SIZE); + CHECK_VALUE(vts_attributes->last_byte + 1 >= VTS_ATTRIBUTES_MIN_SIZE); nr_coded = (vts_attributes->last_byte + 1 - VTS_ATTRIBUTES_MIN_SIZE)/6; /* This is often nr_coded = 70, how do you know how many there really are? */ if(nr_coded > 32) { /* We haven't read more from disk/file anyway */ nr_coded = 32; } - assert(vts_attributes->nr_of_vtstt_subp_streams <= nr_coded); + CHECK_VALUE(vts_attributes->nr_of_vtstt_subp_streams <= nr_coded); for(i = vts_attributes->nr_of_vtstt_subp_streams; i < nr_coded; i++) CHECK_ZERO(vts_attributes->vtstt_subp_attr[i]); } @@ -1827,9 +1911,9 @@ int ifoRead_VTS_ATRT(ifo_handle_t *ifofile) { B2N_32(vts_atrt->last_byte); CHECK_ZERO(vts_atrt->zero_1); - assert(vts_atrt->nr_of_vtss != 0); - assert(vts_atrt->nr_of_vtss < 100); /* ?? */ - assert((uint32_t)vts_atrt->nr_of_vtss * (4 + VTS_ATTRIBUTES_MIN_SIZE) + + CHECK_VALUE(vts_atrt->nr_of_vtss != 0); + CHECK_VALUE(vts_atrt->nr_of_vtss < 100); /* ?? */ + CHECK_VALUE((uint32_t)vts_atrt->nr_of_vtss * (4 + VTS_ATTRIBUTES_MIN_SIZE) + VTS_ATRT_SIZE < vts_atrt->last_byte + 1); info_length = vts_atrt->nr_of_vtss * sizeof(uint32_t); @@ -1839,6 +1923,9 @@ int ifoRead_VTS_ATRT(ifo_handle_t *ifofile) { ifofile->vts_atrt = 0; return 0; } + + vts_atrt->vts_atrt_offsets = data; + if(!(DVDReadBytes(ifofile->file, data, info_length))) { free(data); free(vts_atrt); @@ -1848,7 +1935,7 @@ int ifoRead_VTS_ATRT(ifo_handle_t *ifofile) { for(i = 0; i < vts_atrt->nr_of_vtss; i++) { B2N_32(data[i]); - assert(data[i] + VTS_ATTRIBUTES_MIN_SIZE < vts_atrt->last_byte + 1); + CHECK_VALUE(data[i] + VTS_ATTRIBUTES_MIN_SIZE < vts_atrt->last_byte + 1); } info_length = vts_atrt->nr_of_vtss * sizeof(vts_attributes_t); @@ -1870,10 +1957,9 @@ int ifoRead_VTS_ATRT(ifo_handle_t *ifofile) { } /* This assert cant be in ifoRead_VTS_ATTRIBUTES */ - assert(offset + vts_atrt->vts[i].last_byte <= vts_atrt->last_byte + 1); + CHECK_VALUE(offset + vts_atrt->vts[i].last_byte <= vts_atrt->last_byte + 1); /* Is this check correct? */ } - free(data); return 1; } @@ -1885,6 +1971,7 @@ void ifoFree_VTS_ATRT(ifo_handle_t *ifofile) { if(ifofile->vts_atrt) { free(ifofile->vts_atrt->vts); + free(ifofile->vts_atrt->vts_atrt_offsets); free(ifofile->vts_atrt); ifofile->vts_atrt = 0; } diff --git a/src/input/libdvdread/ifo_read.h b/src/input/libdvdread/ifo_read.h index 588d075b8..3b9b27f20 100644 --- a/src/input/libdvdread/ifo_read.h +++ b/src/input/libdvdread/ifo_read.h @@ -110,8 +110,7 @@ int ifoRead_VTS_PTT_SRPT(ifo_handle_t *); * * Reads in the first play program chain data, filling the * ifofile->first_play_pgc structure. This data is only located in the video - * manager information file. This structure is mandatory, and must be included - * in the VMGI file. **Possibly this is only optional.** + * manager information file (VMGI). This structure is optional. */ int ifoRead_FP_PGC(ifo_handle_t *); diff --git a/src/input/libdvdread/ifo_types.h b/src/input/libdvdread/ifo_types.h index c0b6f57ea..f707d9d83 100644 --- a/src/input/libdvdread/ifo_types.h +++ b/src/input/libdvdread/ifo_types.h @@ -83,7 +83,8 @@ typedef struct { unsigned int line21_cc_1 : 1; unsigned int line21_cc_2 : 1; - unsigned int unknown1 : 2; + unsigned int unknown1 : 1; + unsigned int bit_rate : 1; unsigned int picture_size : 2; unsigned int letterboxed : 1; @@ -98,14 +99,15 @@ typedef struct { unsigned int letterboxed : 1; unsigned int picture_size : 2; - unsigned int unknown1 : 2; + unsigned int bit_rate : 1; + unsigned int unknown1 : 1; unsigned int line21_cc_2 : 1; unsigned int line21_cc_1 : 1; #endif } ATTRIBUTE_PACKED video_attr_t; /** - * Audio Attributes. (Incomplete/Wrong?) + * Audio Attributes. */ typedef struct { #ifdef WORDS_BIGENDIAN @@ -130,13 +132,99 @@ typedef struct { unsigned int quantization : 2; #endif uint16_t lang_code; - uint8_t lang_code2; /* ?? */ uint8_t lang_extension; - uint16_t unknown2; + uint8_t code_extension; + uint8_t unknown3; + union { + struct ATTRIBUTE_PACKED { +#ifdef WORDS_BIGENDIAN + unsigned int unknown4 : 1; + unsigned int channel_assignment : 3; + unsigned int version : 2; + unsigned int mc_intro : 1; /* probably 0: true, 1:false */ + unsigned int mode : 1; /* Karaoke mode 0: solo 1: duet */ +#else + unsigned int mode : 1; + unsigned int mc_intro : 1; + unsigned int version : 2; + unsigned int channel_assignment : 3; + unsigned int unknown4 : 1; +#endif + } karaoke; + struct ATTRIBUTE_PACKED { +#ifdef WORDS_BIGENDIAN + unsigned int unknown5 : 4; + unsigned int dolby_encoded : 1; /* suitable for surround decoding */ + unsigned int unknown6 : 3; +#else + unsigned int unknown6 : 3; + unsigned int dolby_encoded : 1; + unsigned int unknown5 : 4; +#endif + } surround; + } app_info; } ATTRIBUTE_PACKED audio_attr_t; + /** - * Subpicture Attributes.(Incomplete/Wrong) + * MultiChannel Extension + */ +typedef struct { +#ifdef WORDS_BIGENDIAN + unsigned int zero1 : 7; + unsigned int ach0_gme : 1; + + unsigned int zero2 : 7; + unsigned int ach1_gme : 1; + + unsigned int zero3 : 4; + unsigned int ach2_gv1e : 1; + unsigned int ach2_gv2e : 1; + unsigned int ach2_gm1e : 1; + unsigned int ach2_gm2e : 1; + + unsigned int zero4 : 4; + unsigned int ach3_gv1e : 1; + unsigned int ach3_gv2e : 1; + unsigned int ach3_gmAe : 1; + unsigned int ach3_se2e : 1; + + unsigned int zero5 : 4; + unsigned int ach4_gv1e : 1; + unsigned int ach4_gv2e : 1; + unsigned int ach4_gmBe : 1; + unsigned int ach4_seBe : 1; +#else + unsigned int ach0_gme : 1; + unsigned int zero1 : 7; + + unsigned int ach1_gme : 1; + unsigned int zero2 : 7; + + unsigned int ach2_gm2e : 1; + unsigned int ach2_gm1e : 1; + unsigned int ach2_gv2e : 1; + unsigned int ach2_gv1e : 1; + unsigned int zero3 : 4; + + unsigned int ach3_se2e : 1; + unsigned int ach3_gmAe : 1; + unsigned int ach3_gv2e : 1; + unsigned int ach3_gv1e : 1; + unsigned int zero4 : 4; + + unsigned int ach4_seBe : 1; + unsigned int ach4_gmBe : 1; + unsigned int ach4_gv2e : 1; + unsigned int ach4_gv1e : 1; + unsigned int zero5 : 4; +#endif + uint8_t zero6[19]; +} ATTRIBUTE_PACKED multichannel_ext_t; + + +/** + * Subpicture Attributes. */ typedef struct { /* @@ -149,11 +237,19 @@ typedef struct { * language: indicates language if type == 1 * lang extension: if type == 1 contains the lang extension */ - uint8_t type; - uint8_t zero1; +#ifdef WORDS_BIGENDIAN + unsigned int code_mode : 3; + unsigned int zero1 : 3; + unsigned int type : 2; +#else + unsigned int type : 2; + unsigned int zero1 : 3; + unsigned int code_mode : 3; +#endif + uint8_t zero2; uint16_t lang_code; - uint8_t lang_extension; - uint8_t zero2; + uint8_t lang_extension; + uint8_t code_extension; } ATTRIBUTE_PACKED subp_attr_t; @@ -237,62 +333,62 @@ typedef struct { #ifdef WORDS_BIGENDIAN unsigned int zero : 7; /* 25-31 */ unsigned int video_pres_mode_change : 1; /* 24 */ - + unsigned int karaoke_audio_pres_mode_change : 1; /* 23 */ - unsigned int angle_change : 1; /* 22 */ - unsigned int subpic_stream_change : 1; /* 21 */ - unsigned int audio_stream_change : 1; /* 20 */ - unsigned int pause_on : 1; /* 19 */ - unsigned int still_off : 1; /* 18 */ - unsigned int button_select_or_activate : 1; /* 17 */ + unsigned int angle_change : 1; + unsigned int subpic_stream_change : 1; + unsigned int audio_stream_change : 1; + unsigned int pause_on : 1; + unsigned int still_off : 1; + unsigned int button_select_or_activate : 1; unsigned int resume : 1; /* 16 */ - + unsigned int chapter_menu_call : 1; /* 15 */ - unsigned int angle_menu_call : 1; /* 14 */ - unsigned int audio_menu_call : 1; /* 13 */ - unsigned int subpic_menu_call : 1; /* 12 */ - unsigned int root_menu_call : 1; /* 11 */ - unsigned int title_menu_call : 1; /* 10 */ - unsigned int backward_scan : 1; /* 9 */ + unsigned int angle_menu_call : 1; + unsigned int audio_menu_call : 1; + unsigned int subpic_menu_call : 1; + unsigned int root_menu_call : 1; + unsigned int title_menu_call : 1; + unsigned int backward_scan : 1; unsigned int forward_scan : 1; /* 8 */ - + unsigned int next_pg_search : 1; /* 7 */ - unsigned int prev_or_top_pg_search : 1; /* 6 */ - unsigned int time_or_chapter_search : 1; /* 5 */ - unsigned int go_up : 1; /* 4 */ - unsigned int stop : 1; /* 3 */ - unsigned int title_play : 1; /* 2 */ - unsigned int chapter_search_or_play : 1; /* 1 */ + unsigned int prev_or_top_pg_search : 1; + unsigned int time_or_chapter_search : 1; + unsigned int go_up : 1; + unsigned int stop : 1; + unsigned int title_play : 1; + unsigned int chapter_search_or_play : 1; unsigned int title_or_time_play : 1; /* 0 */ #else unsigned int video_pres_mode_change : 1; /* 24 */ unsigned int zero : 7; /* 25-31 */ - + unsigned int resume : 1; /* 16 */ - unsigned int button_select_or_activate : 1; /* 17 */ - unsigned int still_off : 1; /* 18 */ - unsigned int pause_on : 1; /* 19 */ - unsigned int audio_stream_change : 1; /* 20 */ - unsigned int subpic_stream_change : 1; /* 21 */ - unsigned int angle_change : 1; /* 22 */ + unsigned int button_select_or_activate : 1; + unsigned int still_off : 1; + unsigned int pause_on : 1; + unsigned int audio_stream_change : 1; + unsigned int subpic_stream_change : 1; + unsigned int angle_change : 1; unsigned int karaoke_audio_pres_mode_change : 1; /* 23 */ - + unsigned int forward_scan : 1; /* 8 */ - unsigned int backward_scan : 1; /* 9 */ - unsigned int title_menu_call : 1; /* 10 */ - unsigned int root_menu_call : 1; /* 11 */ - unsigned int subpic_menu_call : 1; /* 12 */ - unsigned int audio_menu_call : 1; /* 13 */ - unsigned int angle_menu_call : 1; /* 14 */ + unsigned int backward_scan : 1; + unsigned int title_menu_call : 1; + unsigned int root_menu_call : 1; + unsigned int subpic_menu_call : 1; + unsigned int audio_menu_call : 1; + unsigned int angle_menu_call : 1; unsigned int chapter_menu_call : 1; /* 15 */ - + unsigned int title_or_time_play : 1; /* 0 */ - unsigned int chapter_search_or_play : 1; /* 1 */ - unsigned int title_play : 1; /* 2 */ - unsigned int stop : 1; /* 3 */ - unsigned int go_up : 1; /* 4 */ - unsigned int time_or_chapter_search : 1; /* 5 */ - unsigned int prev_or_top_pg_search : 1; /* 6 */ + unsigned int chapter_search_or_play : 1; + unsigned int title_play : 1; + unsigned int stop : 1; + unsigned int go_up : 1; + unsigned int time_or_chapter_search : 1; + unsigned int prev_or_top_pg_search : 1; unsigned int next_pg_search : 1; /* 7 */ #endif } ATTRIBUTE_PACKED user_ops_t; @@ -361,7 +457,7 @@ typedef struct { */ typedef struct { uint16_t lang_code; - uint8_t zero_1; + uint8_t lang_extension; uint8_t exists; uint32_t lang_start_byte; pgcit_t *pgcit; @@ -465,7 +561,7 @@ typedef struct { typedef struct { #ifdef WORDS_BIGENDIAN unsigned int zero_1 : 1; - unsigned int multi_or_random_pgc_title : 1; /* 0 == one sequential pgc title */ + unsigned int multi_or_random_pgc_title : 1; /* 0: one sequential pgc title */ unsigned int jlc_exists_in_cell_cmd : 1; unsigned int jlc_exists_in_prepost_cmd : 1; unsigned int jlc_exists_in_button_cmd : 1; @@ -473,13 +569,13 @@ typedef struct { unsigned int chapter_search_or_play : 1; /* UOP 1 */ unsigned int title_or_time_play : 1; /* UOP 0 */ #else - unsigned int title_or_time_play : 1; /* UOP 0 */ - unsigned int chapter_search_or_play : 1; /* UOP 1 */ + unsigned int title_or_time_play : 1; + unsigned int chapter_search_or_play : 1; unsigned int jlc_exists_in_tt_dom : 1; unsigned int jlc_exists_in_button_cmd : 1; unsigned int jlc_exists_in_prepost_cmd : 1; unsigned int jlc_exists_in_cell_cmd : 1; - unsigned int multi_or_random_pgc_title : 1; /* 0 == one sequential pgc title */ + unsigned int multi_or_random_pgc_title : 1; unsigned int zero_1 : 1; #endif } ATTRIBUTE_PACKED playback_type_t; @@ -508,6 +604,13 @@ typedef struct { } ATTRIBUTE_PACKED tt_srpt_t; #define TT_SRPT_SIZE 8 + +/** + * Parental Management Information Unit Table. + * Level 1 (US: G), ..., 7 (US: NC-17), 8 + */ +typedef uint16_t pf_level_t[8]; + /** * Parental Management Information Unit Table. */ @@ -516,7 +619,7 @@ typedef struct { uint16_t zero_1; uint16_t pf_ptl_mai_start_byte; uint16_t zero_2; - /* uint16_t *pf_ptl_mai // table of nr_of_vtss+1 x 8 */ + pf_level_t *pf_ptl_mai; /* table of (nr_of_vtss + 1), video_ts is first */ } ATTRIBUTE_PACKED ptl_mait_country_t; #define PTL_MAIT_COUNTRY_SIZE 8 @@ -571,6 +674,7 @@ typedef struct { uint16_t zero_1; uint32_t last_byte; vts_attributes_t *vts; + uint32_t *vts_atrt_offsets; /* offsets table for each vts_attributes */ } ATTRIBUTE_PACKED vts_atrt_t; #define VTS_ATRT_SIZE 8 @@ -588,7 +692,7 @@ typedef struct { uint8_t unknown1; uint8_t unknown2; uint8_t unknown3; - uint8_t unknown4; /*?? allways 0x30 language?, text format? */ + uint8_t unknown4; /* ?? allways 0x30 language?, text format? */ uint8_t unknown5; uint16_t offset; /* from first */ @@ -652,7 +756,7 @@ typedef struct { uint32_t vts_ptt_srpt; /* sector */ uint32_t vts_pgcit; /* sector */ uint32_t vtsm_pgci_ut; /* sector */ - uint32_t vts_tmapt; /* sector */ /* XXX: FIXME TODO Implement */ + uint32_t vts_tmapt; /* sector */ uint32_t vtsm_c_adt; /* sector */ uint32_t vtsm_vobu_admap; /* sector */ uint32_t vts_c_adt; /* sector */ @@ -677,6 +781,8 @@ typedef struct { uint8_t zero_20[17]; uint8_t nr_of_vts_subp_streams; subp_attr_t vts_subp_attr[32]; + uint16_t zero_21; + multichannel_ext_t vts_mu_audio_attr[8]; /* XXX: how much 'padding' here, if any? */ } ATTRIBUTE_PACKED vtsi_mat_t; @@ -704,6 +810,7 @@ typedef struct { uint16_t zero_1; uint32_t last_byte; ttu_t *title; + uint32_t *ttu_offset; /* offset table for each ttu */ } ATTRIBUTE_PACKED vts_ptt_srpt_t; #define VTS_PTT_SRPT_SIZE 8 @@ -733,6 +840,7 @@ typedef struct { uint16_t zero_1; uint32_t last_byte; vts_tmap_t *tmap; + uint32_t *tmap_offset; /* offset table for each tmap */ } ATTRIBUTE_PACKED vts_tmapt_t; #define VTS_TMAPT_SIZE 8 diff --git a/src/input/libdvdread/md5.c b/src/input/libdvdread/md5.c new file mode 100644 index 000000000..3ee9abae5 --- /dev/null +++ b/src/input/libdvdread/md5.c @@ -0,0 +1,417 @@ +/* md5.c - Functions to compute MD5 message digest of files or memory blocks + according to the definition of MD5 in RFC 1321 from April 1992. + Copyright (C) 1995, 1996, 2001 Free Software Foundation, Inc. + NOTE: The canonical source of this file is maintained with the GNU C + Library. Bugs can be reported to bug-glibc@prep.ai.mit.edu. + + 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 this program; if not, write to the Free Software Foundation, + Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */ + +/* Written by Ulrich Drepper <drepper@gnu.ai.mit.edu>, 1995. */ + +#ifdef HAVE_CONFIG_H +# include <config.h> +#endif + +#include <sys/types.h> + +#if STDC_HEADERS || defined _LIBC +# include <stdlib.h> +# include <string.h> +#else +# ifndef HAVE_MEMCPY +# define memcpy(d, s, n) bcopy ((s), (d), (n)) +# endif +#endif + +#include "md5.h" +/* #include "unlocked-io.h" */ + +#ifdef _LIBC +# include <endian.h> +# if __BYTE_ORDER == __BIG_ENDIAN +# define WORDS_BIGENDIAN 1 +# endif +#endif + +#ifdef WORDS_BIGENDIAN +# define SWAP(n) \ + (((n) << 24) | (((n) & 0xff00) << 8) | (((n) >> 8) & 0xff00) | ((n) >> 24)) +#else +# define SWAP(n) (n) +#endif + + +/* This array contains the bytes used to pad the buffer to the next + 64-byte boundary. (RFC 1321, 3.1: Step 1) */ +static const unsigned char fillbuf[64] = { 0x80, 0 /* , 0, 0, ... */ }; + + +/* Initialize structure containing state of computation. + (RFC 1321, 3.3: Step 3) */ +void +md5_init_ctx (ctx) + struct md5_ctx *ctx; +{ + ctx->A = 0x67452301; + ctx->B = 0xefcdab89; + ctx->C = 0x98badcfe; + ctx->D = 0x10325476; + + ctx->total[0] = ctx->total[1] = 0; + ctx->buflen = 0; +} + +/* Put result from CTX in first 16 bytes following RESBUF. The result + must be in little endian byte order. + + IMPORTANT: On some systems it is required that RESBUF is correctly + aligned for a 32 bits value. */ +void * +md5_read_ctx (ctx, resbuf) + const struct md5_ctx *ctx; + void *resbuf; +{ + ((md5_uint32 *) resbuf)[0] = SWAP (ctx->A); + ((md5_uint32 *) resbuf)[1] = SWAP (ctx->B); + ((md5_uint32 *) resbuf)[2] = SWAP (ctx->C); + ((md5_uint32 *) resbuf)[3] = SWAP (ctx->D); + + return resbuf; +} + +/* Process the remaining bytes in the internal buffer and the usual + prolog according to the standard and write the result to RESBUF. + + IMPORTANT: On some systems it is required that RESBUF is correctly + aligned for a 32 bits value. */ +void * +md5_finish_ctx (ctx, resbuf) + struct md5_ctx *ctx; + void *resbuf; +{ + /* Take yet unprocessed bytes into account. */ + md5_uint32 bytes = ctx->buflen; + size_t pad; + + /* Now count remaining bytes. */ + ctx->total[0] += bytes; + if (ctx->total[0] < bytes) + ++ctx->total[1]; + + pad = bytes >= 56 ? 64 + 56 - bytes : 56 - bytes; + memcpy (&ctx->buffer[bytes], fillbuf, pad); + + /* Put the 64-bit file length in *bits* at the end of the buffer. */ + *(md5_uint32 *) &ctx->buffer[bytes + pad] = SWAP (ctx->total[0] << 3); + *(md5_uint32 *) &ctx->buffer[bytes + pad + 4] = SWAP ((ctx->total[1] << 3) | + (ctx->total[0] >> 29)); + + /* Process last bytes. */ + md5_process_block (ctx->buffer, bytes + pad + 8, ctx); + + return md5_read_ctx (ctx, resbuf); +} + +/* Compute MD5 message digest for bytes read from STREAM. The + resulting message digest number will be written into the 16 bytes + beginning at RESBLOCK. */ +int +md5_stream (stream, resblock) + FILE *stream; + void *resblock; +{ + /* Important: BLOCKSIZE must be a multiple of 64. */ +#define BLOCKSIZE 4096 + struct md5_ctx ctx; + char buffer[BLOCKSIZE + 72]; + size_t sum; + + /* Initialize the computation context. */ + md5_init_ctx (&ctx); + + /* Iterate over full file contents. */ + while (1) + { + /* We read the file in blocks of BLOCKSIZE bytes. One call of the + computation function processes the whole buffer so that with the + next round of the loop another block can be read. */ + size_t n; + sum = 0; + + /* Read block. Take care for partial reads. */ + do + { + n = fread (buffer + sum, 1, BLOCKSIZE - sum, stream); + + sum += n; + } + while (sum < BLOCKSIZE && n != 0); + if (n == 0 && ferror (stream)) + return 1; + + /* If end of file is reached, end the loop. */ + if (n == 0) + break; + + /* Process buffer with BLOCKSIZE bytes. Note that + BLOCKSIZE % 64 == 0 + */ + md5_process_block (buffer, BLOCKSIZE, &ctx); + } + + /* Add the last bytes if necessary. */ + if (sum > 0) + md5_process_bytes (buffer, sum, &ctx); + + /* Construct result in desired memory. */ + md5_finish_ctx (&ctx, resblock); + return 0; +} + +/* Compute MD5 message digest for LEN bytes beginning at BUFFER. The + result is always in little endian byte order, so that a byte-wise + output yields to the wanted ASCII representation of the message + digest. */ +void * +md5_buffer (buffer, len, resblock) + const char *buffer; + size_t len; + void *resblock; +{ + struct md5_ctx ctx; + + /* Initialize the computation context. */ + md5_init_ctx (&ctx); + + /* Process whole buffer but last len % 64 bytes. */ + md5_process_bytes (buffer, len, &ctx); + + /* Put result in desired memory area. */ + return md5_finish_ctx (&ctx, resblock); +} + + +void +md5_process_bytes (buffer, len, ctx) + const void *buffer; + size_t len; + struct md5_ctx *ctx; +{ + /* When we already have some bits in our internal buffer concatenate + both inputs first. */ + if (ctx->buflen != 0) + { + size_t left_over = ctx->buflen; + size_t add = 128 - left_over > len ? len : 128 - left_over; + + memcpy (&ctx->buffer[left_over], buffer, add); + ctx->buflen += add; + + if (left_over + add > 64) + { + md5_process_block (ctx->buffer, (left_over + add) & ~63, ctx); + /* The regions in the following copy operation cannot overlap. */ + memcpy (ctx->buffer, &ctx->buffer[(left_over + add) & ~63], + (left_over + add) & 63); + ctx->buflen = (left_over + add) & 63; + } + + buffer = (const char *) buffer + add; + len -= add; + } + + /* Process available complete blocks. */ + if (len > 64) + { + md5_process_block (buffer, len & ~63, ctx); + buffer = (const char *) buffer + (len & ~63); + len &= 63; + } + + /* Move remaining bytes in internal buffer. */ + if (len > 0) + { + memcpy (ctx->buffer, buffer, len); + ctx->buflen = len; + } +} + + +/* These are the four functions used in the four steps of the MD5 algorithm + and defined in the RFC 1321. The first function is a little bit optimized + (as found in Colin Plumbs public domain implementation). */ +/* #define FF(b, c, d) ((b & c) | (~b & d)) */ +#define FF(b, c, d) (d ^ (b & (c ^ d))) +#define FG(b, c, d) FF (d, b, c) +#define FH(b, c, d) (b ^ c ^ d) +#define FI(b, c, d) (c ^ (b | ~d)) + +/* Process LEN bytes of BUFFER, accumulating context into CTX. + It is assumed that LEN % 64 == 0. */ + +void +md5_process_block (buffer, len, ctx) + const void *buffer; + size_t len; + struct md5_ctx *ctx; +{ + md5_uint32 correct_words[16]; + const md5_uint32 *words = buffer; + size_t nwords = len / sizeof (md5_uint32); + const md5_uint32 *endp = words + nwords; + md5_uint32 A = ctx->A; + md5_uint32 B = ctx->B; + md5_uint32 C = ctx->C; + md5_uint32 D = ctx->D; + + /* First increment the byte count. RFC 1321 specifies the possible + length of the file up to 2^64 bits. Here we only compute the + number of bytes. Do a double word increment. */ + ctx->total[0] += len; + if (ctx->total[0] < len) + ++ctx->total[1]; + + /* Process all bytes in the buffer with 64 bytes in each round of + the loop. */ + while (words < endp) + { + md5_uint32 *cwp = correct_words; + md5_uint32 A_save = A; + md5_uint32 B_save = B; + md5_uint32 C_save = C; + md5_uint32 D_save = D; + + /* First round: using the given function, the context and a constant + the next context is computed. Because the algorithms processing + unit is a 32-bit word and it is determined to work on words in + little endian byte order we perhaps have to change the byte order + before the computation. To reduce the work for the next steps + we store the swapped words in the array CORRECT_WORDS. */ + +#define OP(a, b, c, d, s, T) \ + do \ + { \ + a += FF (b, c, d) + (*cwp++ = SWAP (*words)) + T; \ + ++words; \ + a = rol (a, s); \ + a += b; \ + } \ + while (0) + + /* Before we start, one word to the strange constants. + They are defined in RFC 1321 as + + T[i] = (int) (4294967296.0 * fabs (sin (i))), i=1..64, or + perl -e 'foreach(1..64){printf "0x%08x\n", int (4294967296 * abs (sin $_))}' + */ + + /* Round 1. */ + OP (A, B, C, D, 7, 0xd76aa478); + OP (D, A, B, C, 12, 0xe8c7b756); + OP (C, D, A, B, 17, 0x242070db); + OP (B, C, D, A, 22, 0xc1bdceee); + OP (A, B, C, D, 7, 0xf57c0faf); + OP (D, A, B, C, 12, 0x4787c62a); + OP (C, D, A, B, 17, 0xa8304613); + OP (B, C, D, A, 22, 0xfd469501); + OP (A, B, C, D, 7, 0x698098d8); + OP (D, A, B, C, 12, 0x8b44f7af); + OP (C, D, A, B, 17, 0xffff5bb1); + OP (B, C, D, A, 22, 0x895cd7be); + OP (A, B, C, D, 7, 0x6b901122); + OP (D, A, B, C, 12, 0xfd987193); + OP (C, D, A, B, 17, 0xa679438e); + OP (B, C, D, A, 22, 0x49b40821); + + /* For the second to fourth round we have the possibly swapped words + in CORRECT_WORDS. Redefine the macro to take an additional first + argument specifying the function to use. */ +#undef OP +#define OP(f, a, b, c, d, k, s, T) \ + do \ + { \ + a += f (b, c, d) + correct_words[k] + T; \ + a = rol (a, s); \ + a += b; \ + } \ + while (0) + + /* Round 2. */ + OP (FG, A, B, C, D, 1, 5, 0xf61e2562); + OP (FG, D, A, B, C, 6, 9, 0xc040b340); + OP (FG, C, D, A, B, 11, 14, 0x265e5a51); + OP (FG, B, C, D, A, 0, 20, 0xe9b6c7aa); + OP (FG, A, B, C, D, 5, 5, 0xd62f105d); + OP (FG, D, A, B, C, 10, 9, 0x02441453); + OP (FG, C, D, A, B, 15, 14, 0xd8a1e681); + OP (FG, B, C, D, A, 4, 20, 0xe7d3fbc8); + OP (FG, A, B, C, D, 9, 5, 0x21e1cde6); + OP (FG, D, A, B, C, 14, 9, 0xc33707d6); + OP (FG, C, D, A, B, 3, 14, 0xf4d50d87); + OP (FG, B, C, D, A, 8, 20, 0x455a14ed); + OP (FG, A, B, C, D, 13, 5, 0xa9e3e905); + OP (FG, D, A, B, C, 2, 9, 0xfcefa3f8); + OP (FG, C, D, A, B, 7, 14, 0x676f02d9); + OP (FG, B, C, D, A, 12, 20, 0x8d2a4c8a); + + /* Round 3. */ + OP (FH, A, B, C, D, 5, 4, 0xfffa3942); + OP (FH, D, A, B, C, 8, 11, 0x8771f681); + OP (FH, C, D, A, B, 11, 16, 0x6d9d6122); + OP (FH, B, C, D, A, 14, 23, 0xfde5380c); + OP (FH, A, B, C, D, 1, 4, 0xa4beea44); + OP (FH, D, A, B, C, 4, 11, 0x4bdecfa9); + OP (FH, C, D, A, B, 7, 16, 0xf6bb4b60); + OP (FH, B, C, D, A, 10, 23, 0xbebfbc70); + OP (FH, A, B, C, D, 13, 4, 0x289b7ec6); + OP (FH, D, A, B, C, 0, 11, 0xeaa127fa); + OP (FH, C, D, A, B, 3, 16, 0xd4ef3085); + OP (FH, B, C, D, A, 6, 23, 0x04881d05); + OP (FH, A, B, C, D, 9, 4, 0xd9d4d039); + OP (FH, D, A, B, C, 12, 11, 0xe6db99e5); + OP (FH, C, D, A, B, 15, 16, 0x1fa27cf8); + OP (FH, B, C, D, A, 2, 23, 0xc4ac5665); + + /* Round 4. */ + OP (FI, A, B, C, D, 0, 6, 0xf4292244); + OP (FI, D, A, B, C, 7, 10, 0x432aff97); + OP (FI, C, D, A, B, 14, 15, 0xab9423a7); + OP (FI, B, C, D, A, 5, 21, 0xfc93a039); + OP (FI, A, B, C, D, 12, 6, 0x655b59c3); + OP (FI, D, A, B, C, 3, 10, 0x8f0ccc92); + OP (FI, C, D, A, B, 10, 15, 0xffeff47d); + OP (FI, B, C, D, A, 1, 21, 0x85845dd1); + OP (FI, A, B, C, D, 8, 6, 0x6fa87e4f); + OP (FI, D, A, B, C, 15, 10, 0xfe2ce6e0); + OP (FI, C, D, A, B, 6, 15, 0xa3014314); + OP (FI, B, C, D, A, 13, 21, 0x4e0811a1); + OP (FI, A, B, C, D, 4, 6, 0xf7537e82); + OP (FI, D, A, B, C, 11, 10, 0xbd3af235); + OP (FI, C, D, A, B, 2, 15, 0x2ad7d2bb); + OP (FI, B, C, D, A, 9, 21, 0xeb86d391); + + /* Add the starting values of the context. */ + A += A_save; + B += B_save; + C += C_save; + D += D_save; + } + + /* Put checksum in context given as argument. */ + ctx->A = A; + ctx->B = B; + ctx->C = C; + ctx->D = D; +} diff --git a/src/input/libdvdread/md5.h b/src/input/libdvdread/md5.h new file mode 100644 index 000000000..3b7dea169 --- /dev/null +++ b/src/input/libdvdread/md5.h @@ -0,0 +1,161 @@ +/* md5.h - Declaration of functions and data types used for MD5 sum + computing library functions. + Copyright (C) 1995, 1996, 1999 Free Software Foundation, Inc. + NOTE: The canonical source of this file is maintained with the GNU C + Library. Bugs can be reported to bug-glibc@prep.ai.mit.edu. + + 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 this program; if not, write to the Free Software Foundation, + Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */ + +#ifndef _MD5_H +#define _MD5_H 1 + +#include <stdio.h> + +#if defined HAVE_LIMITS_H || _LIBC +# include <limits.h> +#endif + +/* The following contortions are an attempt to use the C preprocessor + to determine an unsigned integral type that is 32 bits wide. An + alternative approach is to use autoconf's AC_CHECK_SIZEOF macro, but + doing that would require that the configure script compile and *run* + the resulting executable. Locally running cross-compiled executables + is usually not possible. */ + +#ifdef _LIBC +# include <sys/types.h> +typedef u_int32_t md5_uint32; +#else +# if defined __STDC__ && __STDC__ +# define UINT_MAX_32_BITS 4294967295U +# else +# define UINT_MAX_32_BITS 0xFFFFFFFF +# endif + +/* If UINT_MAX isn't defined, assume it's a 32-bit type. + This should be valid for all systems GNU cares about because + that doesn't include 16-bit systems, and only modern systems + (that certainly have <limits.h>) have 64+-bit integral types. */ + +# ifndef UINT_MAX +# define UINT_MAX UINT_MAX_32_BITS +# endif + +# if UINT_MAX == UINT_MAX_32_BITS + typedef unsigned int md5_uint32; +# else +# if USHRT_MAX == UINT_MAX_32_BITS + typedef unsigned short md5_uint32; +# else +# if ULONG_MAX == UINT_MAX_32_BITS + typedef unsigned long md5_uint32; +# else + /* The following line is intended to evoke an error. + Using #error is not portable enough. */ + "Cannot determine unsigned 32-bit data type." +# endif +# endif +# endif +#endif + +#undef __P +#if defined (__STDC__) && __STDC__ +#define __P(x) x +#else +#define __P(x) () +#endif + +/* Structure to save state of computation between the single steps. */ +struct md5_ctx +{ + md5_uint32 A; + md5_uint32 B; + md5_uint32 C; + md5_uint32 D; + + md5_uint32 total[2]; + md5_uint32 buflen; + char buffer[128]; +}; + +/* + * The following three functions are build up the low level used in + * the functions `md5_stream' and `md5_buffer'. + */ + +/* Initialize structure containing state of computation. + (RFC 1321, 3.3: Step 3) */ +extern void md5_init_ctx __P ((struct md5_ctx *ctx)); + +/* Starting with the result of former calls of this function (or the + initialization function update the context for the next LEN bytes + starting at BUFFER. + It is necessary that LEN is a multiple of 64!!! */ +extern void md5_process_block __P ((const void *buffer, size_t len, + struct md5_ctx *ctx)); + +/* Starting with the result of former calls of this function (or the + initialization function update the context for the next LEN bytes + starting at BUFFER. + It is NOT required that LEN is a multiple of 64. */ +extern void md5_process_bytes __P ((const void *buffer, size_t len, + struct md5_ctx *ctx)); + +/* Process the remaining bytes in the buffer and put result from CTX + in first 16 bytes following RESBUF. The result is always in little + endian byte order, so that a byte-wise output yields to the wanted + ASCII representation of the message digest. + + IMPORTANT: On some systems it is required that RESBUF be correctly + aligned for a 32 bits value. */ +extern void *md5_finish_ctx __P ((struct md5_ctx *ctx, void *resbuf)); + + +/* Put result from CTX in first 16 bytes following RESBUF. The result is + always in little endian byte order, so that a byte-wise output yields + to the wanted ASCII representation of the message digest. + + IMPORTANT: On some systems it is required that RESBUF is correctly + aligned for a 32 bits value. */ +extern void *md5_read_ctx __P ((const struct md5_ctx *ctx, void *resbuf)); + + +/* Compute MD5 message digest for bytes read from STREAM. The + resulting message digest number will be written into the 16 bytes + beginning at RESBLOCK. */ +extern int md5_stream __P ((FILE *stream, void *resblock)); + +/* Compute MD5 message digest for LEN bytes beginning at BUFFER. The + result is always in little endian byte order, so that a byte-wise + output yields to the wanted ASCII representation of the message + digest. */ +extern void *md5_buffer __P ((const char *buffer, size_t len, void *resblock)); + +/* The following is from gnupg-1.0.2's cipher/bithelp.h. */ +/* Rotate a 32 bit integer by n bytes */ +#if defined __GNUC__ && defined __i386__ +static inline md5_uint32 +rol(md5_uint32 x, int n) +{ + __asm__("roll %%cl,%0" + :"=r" (x) + :"0" (x),"c" (n)); + return x; +} +#else +# define rol(x,n) ( ((x) << (n)) | ((x) >> (32-(n))) ) +#endif + +#endif diff --git a/src/input/libdvdread/nav_print.c b/src/input/libdvdread/nav_print.c index 210829a4c..842ebe44f 100644 --- a/src/input/libdvdread/nav_print.c +++ b/src/input/libdvdread/nav_print.c @@ -1,5 +1,5 @@ /* - * Copyright (C) 2000, 2001, 2002 Håkan Hjort <d95hjort@dtek.chalmers.se> + * Copyright (C) 2000, 2001, 2002, 2003 Håkan Hjort <d95hjort@dtek.chalmers.se> * * Much of the contents in this file is based on VOBDUMP. * @@ -23,21 +23,21 @@ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA */ +#include "config.h" + #include <stdio.h> #include <inttypes.h> -#include <assert.h> -#include "config.h" /* Needed for WORDS_BIGENDIAN */ #include "nav_types.h" #include "nav_print.h" - +#include "dvdread_internal.h" static void print_time(dvd_time_t *dtime) { const char *rate; - assert((dtime->hour>>4) < 0xa && (dtime->hour&0xf) < 0xa); - assert((dtime->minute>>4) < 0x7 && (dtime->minute&0xf) < 0xa); - assert((dtime->second>>4) < 0x7 && (dtime->second&0xf) < 0xa); - assert((dtime->frame_u&0xf) < 0xa); + CHECK_VALUE((dtime->hour>>4) < 0xa && (dtime->hour&0xf) < 0xa); + CHECK_VALUE((dtime->minute>>4) < 0x7 && (dtime->minute&0xf) < 0xa); + CHECK_VALUE((dtime->second>>4) < 0x7 && (dtime->second&0xf) < 0xa); + CHECK_VALUE((dtime->frame_u&0xf) < 0xa); printf("%02x:%02x:%02x.%02x", dtime->hour, diff --git a/src/input/libdvdread/nav_read.c b/src/input/libdvdread/nav_read.c index abaf94b13..67135173a 100644 --- a/src/input/libdvdread/nav_read.c +++ b/src/input/libdvdread/nav_read.c @@ -1,5 +1,5 @@ /* - * Copyright (C) 2000, 2001, 2002 Håkan Hjort <d95hjort@dtek.chalmers.se> + * Copyright (C) 2000, 2001, 2002, 2003 Håkan Hjort <d95hjort@dtek.chalmers.se> * * 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 @@ -16,24 +16,21 @@ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA */ +#include "config.h" + #include <stdio.h> #include <string.h> #include <inttypes.h> -#include <assert.h> -#include "config.h" /* Needed for WORDS_BIGENDIAN */ #include "bswap.h" #include "nav_types.h" #include "nav_read.h" - -/* -#define STRICT -*/ +#include "dvdread_internal.h" void navRead_PCI(pci_t *pci, unsigned char *buffer) { int i, j; - assert(sizeof(pci_t) == PCI_BYTES - 1); /* -1 for substream id */ + CHECK_VALUE(sizeof(pci_t) == PCI_BYTES - 1); /* -1 for substream id */ memcpy(pci, buffer, sizeof(pci_t)); @@ -61,85 +58,99 @@ void navRead_PCI(pci_t *pci, unsigned char *buffer) { for(j = 0; j < 2; j++) B2N_32(pci->hli.btn_colit.btn_coli[i][j]); -#if !defined(WORDS_BIGENDIAN) + /* NOTE: I've had to change the structure from the disk layout to get + * the packing to work with Sun's Forte C compiler. */ + /* pci hli btni */ for(i = 0; i < 36; i++) { - char tmp[6], swap; - memcpy(tmp, &(pci->hli.btnit[i]), 6); - /* This is a B2N_24() */ - swap = tmp[0]; tmp[0] = tmp[2]; tmp[2] = swap; - /* This is a B2N_24() */ - swap = tmp[3]; tmp[3] = tmp[5]; tmp[5] = swap; - memcpy(&(pci->hli.btnit[i]), tmp, 6); - } + char tmp[sizeof(pci->hli.btnit[i])], swap; + memcpy(tmp, &(pci->hli.btnit[i]), sizeof(pci->hli.btnit[i])); + /* Byte 4 to 7 are 'rotated' was: ABCD EFGH IJ is: ABCG DEFH IJ */ + swap = tmp[6]; + tmp[6] = tmp[5]; + tmp[5] = tmp[4]; + tmp[4] = tmp[3]; + tmp[3] = swap; + + /* Then there are the two B2N_24(..) calls */ +#ifndef WORDS_BIGENDIAN + swap = tmp[0]; + tmp[0] = tmp[2]; + tmp[2] = swap; + + swap = tmp[4]; + tmp[4] = tmp[6]; + tmp[6] = swap; #endif + memcpy(&(pci->hli.btnit[i]), tmp, sizeof(pci->hli.btnit[i])); + } -#ifdef STRICT +#ifndef NDEBUG /* Asserts */ /* pci pci gi */ - assert(pci->pci_gi.zero1 == 0); + CHECK_VALUE(pci->pci_gi.zero1 == 0); /* pci hli hli_gi */ - assert(pci->hli.hl_gi.zero1 == 0); - assert(pci->hli.hl_gi.zero2 == 0); - assert(pci->hli.hl_gi.zero3 == 0); - assert(pci->hli.hl_gi.zero4 == 0); - assert(pci->hli.hl_gi.zero5 == 0); + CHECK_VALUE(pci->hli.hl_gi.zero1 == 0); + CHECK_VALUE(pci->hli.hl_gi.zero2 == 0); + CHECK_VALUE(pci->hli.hl_gi.zero3 == 0); + CHECK_VALUE(pci->hli.hl_gi.zero4 == 0); + CHECK_VALUE(pci->hli.hl_gi.zero5 == 0); /* Are there buttons defined here? */ if((pci->hli.hl_gi.hli_ss & 0x03) != 0) { - assert(pci->hli.hl_gi.btn_ns != 0); - assert(pci->hli.hl_gi.btngr_ns != 0); + CHECK_VALUE(pci->hli.hl_gi.btn_ns != 0); + CHECK_VALUE(pci->hli.hl_gi.btngr_ns != 0); } else { - assert((pci->hli.hl_gi.btn_ns != 0 && pci->hli.hl_gi.btngr_ns != 0) + CHECK_VALUE((pci->hli.hl_gi.btn_ns != 0 && pci->hli.hl_gi.btngr_ns != 0) || (pci->hli.hl_gi.btn_ns == 0 && pci->hli.hl_gi.btngr_ns == 0)); } /* pci hli btnit */ for(i = 0; i < pci->hli.hl_gi.btngr_ns; i++) { for(j = 0; j < (36 / pci->hli.hl_gi.btngr_ns); j++) { - int k; int n = (36 / pci->hli.hl_gi.btngr_ns) * i + j; - assert(pci->hli.btnit[n].zero1 == 0); - assert(pci->hli.btnit[n].zero2 == 0); - assert(pci->hli.btnit[n].zero3 == 0); - assert(pci->hli.btnit[n].zero4 == 0); - assert(pci->hli.btnit[n].zero5 == 0); - assert(pci->hli.btnit[n].zero6 == 0); + CHECK_VALUE(pci->hli.btnit[n].zero1 == 0); + CHECK_VALUE(pci->hli.btnit[n].zero2 == 0); + CHECK_VALUE(pci->hli.btnit[n].zero3 == 0); + CHECK_VALUE(pci->hli.btnit[n].zero4 == 0); + CHECK_VALUE(pci->hli.btnit[n].zero5 == 0); + CHECK_VALUE(pci->hli.btnit[n].zero6 == 0); if (j < pci->hli.hl_gi.btn_ns) { - assert(pci->hli.btnit[n].x_start <= pci->hli.btnit[n].x_end); - assert(pci->hli.btnit[n].y_start <= pci->hli.btnit[n].y_end); - assert(pci->hli.btnit[n].up <= pci->hli.hl_gi.btn_ns); - assert(pci->hli.btnit[n].down <= pci->hli.hl_gi.btn_ns); - assert(pci->hli.btnit[n].left <= pci->hli.hl_gi.btn_ns); - assert(pci->hli.btnit[n].right <= pci->hli.hl_gi.btn_ns); - /* vmcmd_verify(pci->hli.btnit[n].cmd); */ + CHECK_VALUE(pci->hli.btnit[n].x_start <= pci->hli.btnit[n].x_end); + CHECK_VALUE(pci->hli.btnit[n].y_start <= pci->hli.btnit[n].y_end); + CHECK_VALUE(pci->hli.btnit[n].up <= pci->hli.hl_gi.btn_ns); + CHECK_VALUE(pci->hli.btnit[n].down <= pci->hli.hl_gi.btn_ns); + CHECK_VALUE(pci->hli.btnit[n].left <= pci->hli.hl_gi.btn_ns); + CHECK_VALUE(pci->hli.btnit[n].right <= pci->hli.hl_gi.btn_ns); + /*vmcmd_verify(pci->hli.btnit[n].cmd);*/ } else { - assert(pci->hli.btnit[n].btn_coln == 0); - assert(pci->hli.btnit[n].auto_action_mode == 0); - assert(pci->hli.btnit[n].x_start == 0); - assert(pci->hli.btnit[n].y_start == 0); - assert(pci->hli.btnit[n].x_end == 0); - assert(pci->hli.btnit[n].y_end == 0); - assert(pci->hli.btnit[n].up == 0); - assert(pci->hli.btnit[n].down == 0); - assert(pci->hli.btnit[n].left == 0); - assert(pci->hli.btnit[n].right == 0); + int k; + CHECK_VALUE(pci->hli.btnit[n].btn_coln == 0); + CHECK_VALUE(pci->hli.btnit[n].auto_action_mode == 0); + CHECK_VALUE(pci->hli.btnit[n].x_start == 0); + CHECK_VALUE(pci->hli.btnit[n].y_start == 0); + CHECK_VALUE(pci->hli.btnit[n].x_end == 0); + CHECK_VALUE(pci->hli.btnit[n].y_end == 0); + CHECK_VALUE(pci->hli.btnit[n].up == 0); + CHECK_VALUE(pci->hli.btnit[n].down == 0); + CHECK_VALUE(pci->hli.btnit[n].left == 0); + CHECK_VALUE(pci->hli.btnit[n].right == 0); for (k = 0; k < 8; k++) - assert(pci->hli.btnit[n].cmd.bytes[k] == 0); /* CHECK_ZERO? */ + CHECK_VALUE(pci->hli.btnit[n].cmd.bytes[k] == 0); /* CHECK_ZERO? */ } } } -#endif +#endif /* !NDEBUG */ } void navRead_DSI(dsi_t *dsi, unsigned char *buffer) { int i; - assert(sizeof(dsi_t) == DSI_BYTES - 1); /* -1 for substream id */ + CHECK_VALUE(sizeof(dsi_t) == DSI_BYTES - 1); /* -1 for substream id */ memcpy(dsi, buffer, sizeof(dsi_t)); @@ -185,11 +196,9 @@ void navRead_DSI(dsi_t *dsi, unsigned char *buffer) { B2N_32(dsi->synci.sp_synca[i]); -#ifdef STRICT /* Asserts */ /* dsi dsi gi */ - assert(dsi->dsi_gi.zero1 == 0); -#endif + CHECK_VALUE(dsi->dsi_gi.zero1 == 0); } diff --git a/src/input/libdvdread/nav_types.h b/src/input/libdvdread/nav_types.h index 33bb6d559..3ad98947d 100644 --- a/src/input/libdvdread/nav_types.h +++ b/src/input/libdvdread/nav_types.h @@ -90,15 +90,21 @@ typedef struct { /** * Highlight General Information + * + * For btngrX_dsp_ty the bits have the following meaning: + * 000b: normal 4/3 only buttons + * XX1b: wide (16/9) buttons + * X1Xb: letterbox buttons + * 1XXb: pan&scan buttons */ typedef struct { - uint16_t hli_ss; /**< status, only low 2 bits 0: no, 1: different 2: equal 3: eual except for button cmds */ + uint16_t hli_ss; /**< status, only low 2 bits 0: no buttons, 1: different 2: equal 3: eual except for button cmds */ uint32_t hli_s_ptm; /**< start ptm of hli */ uint32_t hli_e_ptm; /**< end ptm of hli */ uint32_t btn_se_e_ptm; /**< end ptm of button select */ #ifdef WORDS_BIGENDIAN unsigned int zero1 : 2; /**< reserved */ - unsigned int btngr_ns : 2; /**< number of button groups */ + unsigned int btngr_ns : 2; /**< number of button groups 1, 2 or 3 with 36/18/12 buttons */ unsigned int zero2 : 1; /**< reserved */ unsigned int btngr1_dsp_ty : 3; /**< display type of subpic stream for button group 1 */ unsigned int zero3 : 1; /**< reserved */ @@ -115,9 +121,9 @@ typedef struct { unsigned int btngr2_dsp_ty : 3; unsigned int zero3 : 1; #endif - uint8_t btn_ofn; /**< button offset number */ - uint8_t btn_ns; /**< number of valid buttons (low 6 bits) */ - uint8_t nsl_btn_ns; /**< number of buttons selectable by U_BTNNi (low 6 bits) nsl_btn_ns <= btn_ns */ + uint8_t btn_ofn; /**< button offset number range 0-255 */ + uint8_t btn_ns; /**< number of valid buttons <= 36/18/12 (low 6 bits) */ + uint8_t nsl_btn_ns; /**< number of buttons selectable by U_BTNNi (low 6 bits) nsl_btn_ns <= btn_ns */ uint8_t zero5; /**< reserved */ uint8_t fosl_btnn; /**< forcedly selected button (low 6 bits) */ uint8_t foac_btnn; /**< forcedly activated button (low 6 bits) */ @@ -138,6 +144,10 @@ typedef struct { /** * Button Information + * + * NOTE: I've had to change the structure from the disk layout to get + * the packing to work with Sun's Forte C compiler. + * The 4 and 7 bytes are 'rotated' was: ABC DEF GHIJ is: ABCG DEFH IJ */ typedef struct { #ifdef WORDS_BIGENDIAN @@ -145,13 +155,15 @@ typedef struct { unsigned int x_start : 10; /**< x start offset within the overlay */ unsigned int zero1 : 2; /**< reserved */ unsigned int x_end : 10; /**< x end offset within the overlay */ + + unsigned int zero3 : 2; /**< reserved */ + unsigned int up : 6; /**< button index when pressing up */ + unsigned int auto_action_mode : 2; /**< 0: no, 1: activated if selected */ unsigned int y_start : 10; /**< y start offset within the overlay */ unsigned int zero2 : 2; /**< reserved */ unsigned int y_end : 10; /**< y end offset within the overlay */ - unsigned int zero3 : 2; /**< reserved */ - unsigned int up : 6; /**< button index when pressing up */ unsigned int zero4 : 2; /**< reserved */ unsigned int down : 6; /**< button index when pressing down */ unsigned int zero5 : 2; /**< reserved */ @@ -163,13 +175,15 @@ typedef struct { unsigned int zero1 : 2; unsigned int x_start : 10; unsigned int btn_coln : 2; + + unsigned int up : 6; + unsigned int zero3 : 2; + unsigned int y_end : 10; unsigned int zero2 : 2; unsigned int y_start : 10; unsigned int auto_action_mode : 2; - unsigned int up : 6; - unsigned int zero3 : 2; unsigned int down : 6; unsigned int zero4 : 2; unsigned int left : 6; |