|
MythTV
0.26-pre
|
00001 /* 00002 * Copyright (C) 2000, 2001, 2002, 2003 00003 * Björn Englund <d4bjorn@dtek.chalmers.se>, 00004 * Håkan Hjort <d95hjort@dtek.chalmers.se> 00005 * 00006 * This file is part of libdvdread. 00007 * 00008 * libdvdread is free software; you can redistribute it and/or modify 00009 * it under the terms of the GNU General Public License as published by 00010 * the Free Software Foundation; either version 2 of the License, or 00011 * (at your option) any later version. 00012 * 00013 * libdvdread is distributed in the hope that it will be useful, 00014 * but WITHOUT ANY WARRANTY; without even the implied warranty of 00015 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 00016 * GNU General Public License for more details. 00017 * 00018 * You should have received a copy of the GNU General Public License along 00019 * with libdvdread; if not, write to the Free Software Foundation, Inc., 00020 * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. 00021 */ 00022 00023 #include "config.h" 00024 00025 #include <stdio.h> 00026 #include <stdlib.h> 00027 #include <inttypes.h> 00028 #include <string.h> 00029 00030 #include "bswap.h" 00031 #include "dvdread/ifo_types.h" 00032 #include "dvdread/ifo_read.h" 00033 #include "dvdread/dvd_reader.h" 00034 #include "dvdread_internal.h" 00035 #include "dvdread/bitreader.h" 00036 00037 #ifndef DVD_BLOCK_LEN 00038 #define DVD_BLOCK_LEN 2048 00039 #endif 00040 00041 #ifndef NDEBUG 00042 #define CHECK_ZERO0(arg) \ 00043 if(arg != 0) { \ 00044 fprintf(stderr, "*** Zero check failed in %s:%i\n for %s = 0x%x\n", \ 00045 __FILE__, __LINE__, # arg, arg); \ 00046 } 00047 #define CHECK_ZERO(arg) \ 00048 if(memcmp(my_friendly_zeros, &arg, sizeof(arg))) { \ 00049 unsigned int i_CZ; \ 00050 fprintf(stderr, "*** Zero check failed in %s:%i\n for %s = 0x", \ 00051 __FILE__, __LINE__, # arg ); \ 00052 for(i_CZ = 0; i_CZ < sizeof(arg); i_CZ++) \ 00053 fprintf(stderr, "%02x", *((uint8_t *)&arg + i_CZ)); \ 00054 fprintf(stderr, "\n"); \ 00055 } 00056 static const uint8_t my_friendly_zeros[2048]; 00057 #else 00058 #define CHECK_ZERO0(arg) (void)(arg) 00059 #define CHECK_ZERO(arg) (void)(arg) 00060 #endif 00061 00062 00063 /* Prototypes for internal functions */ 00064 static int ifoRead_VMG(ifo_handle_t *ifofile); 00065 static int ifoRead_VTS(ifo_handle_t *ifofile); 00066 static int ifoRead_PGC(ifo_handle_t *ifofile, pgc_t *pgc, unsigned int offset); 00067 static int ifoRead_PGC_COMMAND_TBL(ifo_handle_t *ifofile, 00068 pgc_command_tbl_t *cmd_tbl, 00069 unsigned int offset); 00070 static int ifoRead_PGC_PROGRAM_MAP(ifo_handle_t *ifofile, 00071 pgc_program_map_t *program_map, 00072 unsigned int nr, unsigned int offset); 00073 static int ifoRead_CELL_PLAYBACK_TBL(ifo_handle_t *ifofile, 00074 cell_playback_t *cell_playback, 00075 unsigned int nr, unsigned int offset); 00076 static int ifoRead_CELL_POSITION_TBL(ifo_handle_t *ifofile, 00077 cell_position_t *cell_position, 00078 unsigned int nr, unsigned int offset); 00079 static int ifoRead_VTS_ATTRIBUTES(ifo_handle_t *ifofile, 00080 vts_attributes_t *vts_attributes, 00081 unsigned int offset); 00082 static int ifoRead_C_ADT_internal(ifo_handle_t *ifofile, c_adt_t *c_adt, 00083 unsigned int sector); 00084 static int ifoRead_VOBU_ADMAP_internal(ifo_handle_t *ifofile, 00085 vobu_admap_t *vobu_admap, 00086 unsigned int sector); 00087 static int ifoRead_PGCIT_internal(ifo_handle_t *ifofile, pgcit_t *pgcit, 00088 unsigned int offset); 00089 00090 static void ifoFree_PGC(pgc_t *pgc); 00091 static void ifoFree_PGC_COMMAND_TBL(pgc_command_tbl_t *cmd_tbl); 00092 static void ifoFree_PGCIT_internal(pgcit_t *pgcit); 00093 00094 static inline int DVDFileSeekForce_( dvd_file_t *dvd_file, uint32_t offset, int force_size ) { 00095 return (DVDFileSeekForce(dvd_file, (int)offset, force_size) == (int)offset); 00096 } 00097 00098 static inline int DVDFileSeek_( dvd_file_t *dvd_file, uint32_t offset ) { 00099 return (DVDFileSeek(dvd_file, (int)offset) == (int)offset); 00100 } 00101 00102 static void read_video_attr(video_attr_t *va) { 00103 getbits_state_t state; 00104 uint8_t buf[sizeof(video_attr_t)]; 00105 00106 memcpy(buf, va, sizeof(video_attr_t)); 00107 if (!dvdread_getbits_init(&state, buf)) abort(); 00108 va->mpeg_version = dvdread_getbits(&state, 2); 00109 va->video_format = dvdread_getbits(&state, 2); 00110 va->display_aspect_ratio = dvdread_getbits(&state, 2); 00111 va->permitted_df = dvdread_getbits(&state, 2); 00112 va->line21_cc_1 = dvdread_getbits(&state, 1); 00113 va->line21_cc_2 = dvdread_getbits(&state, 1); 00114 va->unknown1 = dvdread_getbits(&state, 1); 00115 va->bit_rate = dvdread_getbits(&state, 1); 00116 va->picture_size = dvdread_getbits(&state, 2); 00117 va->letterboxed = dvdread_getbits(&state, 1); 00118 va->film_mode = dvdread_getbits(&state, 1); 00119 } 00120 00121 static void read_audio_attr(audio_attr_t *aa) { 00122 getbits_state_t state; 00123 uint8_t buf[sizeof(audio_attr_t)]; 00124 00125 memcpy(buf, aa, sizeof(audio_attr_t)); 00126 if (!dvdread_getbits_init(&state, buf)) abort(); 00127 aa->audio_format = dvdread_getbits(&state, 3); 00128 aa->multichannel_extension = dvdread_getbits(&state, 1); 00129 aa->lang_type = dvdread_getbits(&state, 2); 00130 aa->application_mode = dvdread_getbits(&state, 2); 00131 aa->quantization = dvdread_getbits(&state, 2); 00132 aa->sample_frequency = dvdread_getbits(&state, 2); 00133 aa->unknown1 = dvdread_getbits(&state, 1); 00134 aa->channels = dvdread_getbits(&state, 3); 00135 aa->lang_code = dvdread_getbits(&state, 16); 00136 aa->lang_extension = dvdread_getbits(&state, 8); 00137 aa->code_extension = dvdread_getbits(&state, 8); 00138 aa->unknown3 = dvdread_getbits(&state, 8); 00139 aa->app_info.karaoke.unknown4 = dvdread_getbits(&state, 1); 00140 aa->app_info.karaoke.channel_assignment = dvdread_getbits(&state, 3); 00141 aa->app_info.karaoke.version = dvdread_getbits(&state, 2); 00142 aa->app_info.karaoke.mc_intro = dvdread_getbits(&state, 1); 00143 aa->app_info.karaoke.mode = dvdread_getbits(&state, 1); 00144 } 00145 00146 static void read_multichannel_ext(multichannel_ext_t *me) { 00147 getbits_state_t state; 00148 uint8_t buf[sizeof(multichannel_ext_t)]; 00149 00150 memcpy(buf, me, sizeof(multichannel_ext_t)); 00151 if (!dvdread_getbits_init(&state, buf)) abort(); 00152 me->zero1 = dvdread_getbits(&state, 7); 00153 me->ach0_gme = dvdread_getbits(&state, 1); 00154 me->zero2 = dvdread_getbits(&state, 7); 00155 me->ach1_gme = dvdread_getbits(&state, 1); 00156 me->zero3 = dvdread_getbits(&state, 4); 00157 me->ach2_gv1e = dvdread_getbits(&state, 1); 00158 me->ach2_gv2e = dvdread_getbits(&state, 1); 00159 me->ach2_gm1e = dvdread_getbits(&state, 1); 00160 me->ach2_gm2e = dvdread_getbits(&state, 1); 00161 me->zero4 = dvdread_getbits(&state, 4); 00162 me->ach3_gv1e = dvdread_getbits(&state, 1); 00163 me->ach3_gv2e = dvdread_getbits(&state, 1); 00164 me->ach3_gmAe = dvdread_getbits(&state, 1); 00165 me->ach3_se2e = dvdread_getbits(&state, 1); 00166 me->zero5 = dvdread_getbits(&state, 4); 00167 me->ach4_gv1e = dvdread_getbits(&state, 1); 00168 me->ach4_gv2e = dvdread_getbits(&state, 1); 00169 me->ach4_gmBe = dvdread_getbits(&state, 1); 00170 me->ach4_seBe = dvdread_getbits(&state, 1); 00171 } 00172 00173 static void read_subp_attr(subp_attr_t *sa) { 00174 getbits_state_t state; 00175 uint8_t buf[sizeof(subp_attr_t)]; 00176 00177 memcpy(buf, sa, sizeof(subp_attr_t)); 00178 if (!dvdread_getbits_init(&state, buf)) abort(); 00179 sa->code_mode = dvdread_getbits(&state, 3); 00180 sa->zero1 = dvdread_getbits(&state, 3); 00181 sa->type = dvdread_getbits(&state, 2); 00182 sa->zero2 = dvdread_getbits(&state, 8); 00183 sa->lang_code = dvdread_getbits(&state, 16); 00184 sa->lang_extension = dvdread_getbits(&state, 8); 00185 sa->code_extension = dvdread_getbits(&state, 8); 00186 } 00187 00188 static void read_user_ops(user_ops_t *uo) { 00189 getbits_state_t state; 00190 uint8_t buf[sizeof(user_ops_t)]; 00191 00192 memcpy(buf, uo, sizeof(user_ops_t)); 00193 if (!dvdread_getbits_init(&state, buf)) abort(); 00194 uo->zero = dvdread_getbits(&state, 7); 00195 uo->video_pres_mode_change = dvdread_getbits(&state, 1); 00196 uo->karaoke_audio_pres_mode_change = dvdread_getbits(&state, 1); 00197 uo->angle_change = dvdread_getbits(&state, 1); 00198 uo->subpic_stream_change = dvdread_getbits(&state, 1); 00199 uo->audio_stream_change = dvdread_getbits(&state, 1); 00200 uo->pause_on = dvdread_getbits(&state, 1); 00201 uo->still_off = dvdread_getbits(&state, 1); 00202 uo->button_select_or_activate = dvdread_getbits(&state, 1); 00203 uo->resume = dvdread_getbits(&state, 1); 00204 uo->chapter_menu_call = dvdread_getbits(&state, 1); 00205 uo->angle_menu_call = dvdread_getbits(&state, 1); 00206 uo->audio_menu_call = dvdread_getbits(&state, 1); 00207 uo->subpic_menu_call = dvdread_getbits(&state, 1); 00208 uo->root_menu_call = dvdread_getbits(&state, 1); 00209 uo->title_menu_call = dvdread_getbits(&state, 1); 00210 uo->backward_scan = dvdread_getbits(&state, 1); 00211 uo->forward_scan = dvdread_getbits(&state, 1); 00212 uo->next_pg_search = dvdread_getbits(&state, 1); 00213 uo->prev_or_top_pg_search = dvdread_getbits(&state, 1); 00214 uo->time_or_chapter_search = dvdread_getbits(&state, 1); 00215 uo->go_up = dvdread_getbits(&state, 1); 00216 uo->stop = dvdread_getbits(&state, 1); 00217 uo->title_play = dvdread_getbits(&state, 1); 00218 uo->chapter_search_or_play = dvdread_getbits(&state, 1); 00219 uo->title_or_time_play = dvdread_getbits(&state, 1); 00220 } 00221 00222 static void read_pgci_srp(pgci_srp_t *ps) { 00223 getbits_state_t state; 00224 uint8_t buf[sizeof(pgci_srp_t)]; 00225 00226 memcpy(buf, ps, sizeof(pgci_srp_t)); 00227 if (!dvdread_getbits_init(&state, buf)) abort(); 00228 ps->entry_id = dvdread_getbits(&state, 8); 00229 ps->block_mode = dvdread_getbits(&state, 2); 00230 ps->block_type = dvdread_getbits(&state, 2); 00231 ps->unknown1 = dvdread_getbits(&state, 4); 00232 ps->ptl_id_mask = dvdread_getbits(&state, 16); 00233 ps->pgc_start_byte = dvdread_getbits(&state, 32); 00234 } 00235 00236 static void read_cell_playback(cell_playback_t *cp) { 00237 getbits_state_t state; 00238 uint8_t buf[sizeof(cell_playback_t)]; 00239 00240 memcpy(buf, cp, sizeof(cell_playback_t)); 00241 if (!dvdread_getbits_init(&state, buf)) abort(); 00242 cp->block_mode = dvdread_getbits(&state, 2); 00243 cp->block_type = dvdread_getbits(&state, 2); 00244 cp->seamless_play = dvdread_getbits(&state, 1); 00245 cp->interleaved = dvdread_getbits(&state, 1); 00246 cp->stc_discontinuity = dvdread_getbits(&state, 1); 00247 cp->seamless_angle = dvdread_getbits(&state, 1); 00248 cp->playback_mode = dvdread_getbits(&state, 1); 00249 cp->restricted = dvdread_getbits(&state, 1); 00250 cp->unknown2 = dvdread_getbits(&state, 6); 00251 cp->still_time = dvdread_getbits(&state, 8); 00252 cp->cell_cmd_nr = dvdread_getbits(&state, 8); 00253 00254 cp->playback_time.hour = dvdread_getbits(&state, 8); 00255 cp->playback_time.minute = dvdread_getbits(&state, 8); 00256 cp->playback_time.second = dvdread_getbits(&state, 8); 00257 cp->playback_time.frame_u = dvdread_getbits(&state, 8); 00258 00259 cp->first_sector = dvdread_getbits(&state, 32); 00260 cp->first_ilvu_end_sector = dvdread_getbits(&state, 32); 00261 cp->last_vobu_start_sector = dvdread_getbits(&state, 32); 00262 cp->last_sector = dvdread_getbits(&state, 32); 00263 } 00264 00265 static void read_playback_type(playback_type_t *pt) { 00266 getbits_state_t state; 00267 uint8_t buf[sizeof(playback_type_t)]; 00268 00269 memcpy(buf, pt, sizeof(playback_type_t)); 00270 if (!dvdread_getbits_init(&state, buf)) abort(); 00271 pt->zero_1 = dvdread_getbits(&state, 1); 00272 pt->multi_or_random_pgc_title = dvdread_getbits(&state, 1); 00273 pt->jlc_exists_in_cell_cmd = dvdread_getbits(&state, 1); 00274 pt->jlc_exists_in_prepost_cmd = dvdread_getbits(&state, 1); 00275 pt->jlc_exists_in_button_cmd = dvdread_getbits(&state, 1); 00276 pt->jlc_exists_in_tt_dom = dvdread_getbits(&state, 1); 00277 pt->chapter_search_or_play = dvdread_getbits(&state, 1); 00278 pt->title_or_time_play = dvdread_getbits(&state, 1); 00279 } 00280 00281 static void free_ptl_mait(ptl_mait_t* ptl_mait, int num_entries) { 00282 int i; 00283 for (i = 0; i < num_entries; i++) 00284 free(ptl_mait->countries[i].pf_ptl_mai); 00285 00286 free(ptl_mait->countries); 00287 free(ptl_mait); 00288 } 00289 00290 ifo_handle_t *ifoOpen(dvd_reader_t *dvd, int title) { 00291 ifo_handle_t *ifofile; 00292 int bup_file_opened = 0; 00293 char ifo_filename[13]; 00294 00295 ifofile = (ifo_handle_t *)malloc(sizeof(ifo_handle_t)); 00296 if(!ifofile) 00297 return NULL; 00298 00299 memset(ifofile, 0, sizeof(ifo_handle_t)); 00300 00301 ifofile->file = DVDOpenFile(dvd, title, DVD_READ_INFO_FILE); 00302 if(!ifofile->file) { /* Failed to open IFO, try to open BUP */ 00303 ifofile->file = DVDOpenFile(dvd, title, DVD_READ_INFO_BACKUP_FILE); 00304 bup_file_opened = 1; 00305 } 00306 00307 if (title) 00308 snprintf(ifo_filename, 12, "VTS_%02d_0.%s", title, bup_file_opened ? "BUP" : "IFO"); 00309 else 00310 snprintf(ifo_filename, 12, "VIDEO_TS.%s", bup_file_opened ? "BUP" : "IFO"); 00311 00312 ifo_filename[12] = '\0'; 00313 00314 if(!ifofile->file) { 00315 fprintf(stderr, "libdvdread: Can't open file %s.\n", ifo_filename); 00316 free(ifofile); 00317 return NULL; 00318 } 00319 00320 /* First check if this is a VMGI file. */ 00321 if(ifoRead_VMG(ifofile)) { 00322 00323 /* These are both mandatory. */ 00324 if(!ifoRead_FP_PGC(ifofile) || !ifoRead_TT_SRPT(ifofile)) 00325 goto ifoOpen_try_bup; 00326 00327 ifoRead_PGCI_UT(ifofile); 00328 ifoRead_PTL_MAIT(ifofile); 00329 00330 /* This is also mandatory. */ 00331 if(!ifoRead_VTS_ATRT(ifofile)) 00332 goto ifoOpen_try_bup; 00333 00334 ifoRead_TXTDT_MGI(ifofile); 00335 ifoRead_C_ADT(ifofile); 00336 ifoRead_VOBU_ADMAP(ifofile); 00337 00338 return ifofile; 00339 } 00340 00341 if(ifoRead_VTS(ifofile)) { 00342 00343 if(!ifoRead_VTS_PTT_SRPT(ifofile) || !ifoRead_PGCIT(ifofile)) 00344 goto ifoOpen_try_bup; 00345 00346 ifoRead_PGCI_UT(ifofile); 00347 ifoRead_VTS_TMAPT(ifofile); 00348 ifoRead_C_ADT(ifofile); 00349 ifoRead_VOBU_ADMAP(ifofile); 00350 00351 if(!ifoRead_TITLE_C_ADT(ifofile) || !ifoRead_TITLE_VOBU_ADMAP(ifofile)) 00352 goto ifoOpen_try_bup; 00353 00354 return ifofile; 00355 } 00356 00357 ifoOpen_try_bup: 00358 if (bup_file_opened) 00359 goto ifoOpen_fail; 00360 00361 /* Try BUP instead */ 00362 ifoClose(ifofile); 00363 00364 ifofile = (ifo_handle_t *)malloc(sizeof(ifo_handle_t)); 00365 if(!ifofile) 00366 return NULL; 00367 00368 memset(ifofile, 0, sizeof(ifo_handle_t)); 00369 ifofile->file = DVDOpenFile(dvd, title, DVD_READ_INFO_BACKUP_FILE); 00370 00371 if (title) 00372 snprintf(ifo_filename, 12, "VTS_%02d_0.BUP", title); 00373 else 00374 strncpy(ifo_filename, "VIDEO_TS.BUP", 12); 00375 00376 if (!ifofile->file) { 00377 fprintf(stderr, "libdvdread: Can't open file %s.\n", ifo_filename); 00378 free(ifofile); 00379 return NULL; 00380 } 00381 bup_file_opened = 1; 00382 00383 /* First check if this is a VMGI file. */ 00384 if(ifoRead_VMG(ifofile)) { 00385 00386 /* These are both mandatory. */ 00387 if(!ifoRead_FP_PGC(ifofile) || !ifoRead_TT_SRPT(ifofile)) 00388 goto ifoOpen_fail; 00389 00390 ifoRead_PGCI_UT(ifofile); 00391 ifoRead_PTL_MAIT(ifofile); 00392 00393 /* This is also mandatory. */ 00394 if(!ifoRead_VTS_ATRT(ifofile)) 00395 goto ifoOpen_fail; 00396 00397 ifoRead_TXTDT_MGI(ifofile); 00398 ifoRead_C_ADT(ifofile); 00399 ifoRead_VOBU_ADMAP(ifofile); 00400 00401 return ifofile; 00402 } 00403 00404 if(ifoRead_VTS(ifofile)) { 00405 00406 if(!ifoRead_VTS_PTT_SRPT(ifofile) || !ifoRead_PGCIT(ifofile)) 00407 goto ifoOpen_fail; 00408 00409 ifoRead_PGCI_UT(ifofile); 00410 ifoRead_VTS_TMAPT(ifofile); 00411 ifoRead_C_ADT(ifofile); 00412 ifoRead_VOBU_ADMAP(ifofile); 00413 00414 if(!ifoRead_TITLE_C_ADT(ifofile) || !ifoRead_TITLE_VOBU_ADMAP(ifofile)) 00415 goto ifoOpen_fail; 00416 00417 return ifofile; 00418 } 00419 00420 ifoOpen_fail: 00421 fprintf(stderr, "libdvdread: Invalid IFO for title %d (%s).\n", title, ifo_filename); 00422 ifoClose(ifofile); 00423 return NULL; 00424 } 00425 00426 00427 ifo_handle_t *ifoOpenVMGI(dvd_reader_t *dvd) { 00428 ifo_handle_t *ifofile; 00429 00430 ifofile = (ifo_handle_t *)malloc(sizeof(ifo_handle_t)); 00431 if(!ifofile) 00432 return NULL; 00433 00434 memset(ifofile, 0, sizeof(ifo_handle_t)); 00435 00436 ifofile->file = DVDOpenFile(dvd, 0, DVD_READ_INFO_FILE); 00437 if(!ifofile->file) /* Should really catch any error and try to fallback */ 00438 ifofile->file = DVDOpenFile(dvd, 0, DVD_READ_INFO_BACKUP_FILE); 00439 if(!ifofile->file) { 00440 fprintf(stderr, "libdvdread: Can't open file VIDEO_TS.IFO.\n"); 00441 free(ifofile); 00442 return NULL; 00443 } 00444 00445 if(ifoRead_VMG(ifofile)) 00446 return ifofile; 00447 00448 fprintf(stderr, "libdvdread,ifoOpenVMGI(): Invalid main menu IFO (VIDEO_TS.IFO).\n"); 00449 ifoClose(ifofile); 00450 return NULL; 00451 } 00452 00453 00454 ifo_handle_t *ifoOpenVTSI(dvd_reader_t *dvd, int title) { 00455 ifo_handle_t *ifofile; 00456 00457 ifofile = (ifo_handle_t *)malloc(sizeof(ifo_handle_t)); 00458 if(!ifofile) 00459 return NULL; 00460 00461 memset(ifofile, 0, sizeof(ifo_handle_t)); 00462 00463 if(title <= 0 || title > 99) { 00464 fprintf(stderr, "libdvdread: ifoOpenVTSI invalid title (%d).\n", title); 00465 free(ifofile); 00466 return NULL; 00467 } 00468 00469 ifofile->file = DVDOpenFile(dvd, title, DVD_READ_INFO_FILE); 00470 if(!ifofile->file) /* Should really catch any error and try to fallback */ 00471 ifofile->file = DVDOpenFile(dvd, title, DVD_READ_INFO_BACKUP_FILE); 00472 if(!ifofile->file) { 00473 fprintf(stderr, "libdvdread: Can't open file VTS_%02d_0.IFO.\n", title); 00474 free(ifofile); 00475 return NULL; 00476 } 00477 00478 ifoRead_VTS(ifofile); 00479 if(ifofile->vtsi_mat) 00480 return ifofile; 00481 00482 fprintf(stderr, "libdvdread: Invalid IFO for title %d (VTS_%02d_0.IFO).\n", 00483 title, title); 00484 ifoClose(ifofile); 00485 return NULL; 00486 } 00487 00488 00489 void ifoClose(ifo_handle_t *ifofile) { 00490 if(!ifofile) 00491 return; 00492 00493 ifoFree_VOBU_ADMAP(ifofile); 00494 ifoFree_TITLE_VOBU_ADMAP(ifofile); 00495 ifoFree_C_ADT(ifofile); 00496 ifoFree_TITLE_C_ADT(ifofile); 00497 ifoFree_TXTDT_MGI(ifofile); 00498 ifoFree_VTS_ATRT(ifofile); 00499 ifoFree_PTL_MAIT(ifofile); 00500 ifoFree_PGCI_UT(ifofile); 00501 ifoFree_TT_SRPT(ifofile); 00502 ifoFree_FP_PGC(ifofile); 00503 ifoFree_PGCIT(ifofile); 00504 ifoFree_VTS_PTT_SRPT(ifofile); 00505 ifoFree_VTS_TMAPT(ifofile); 00506 00507 if(ifofile->vmgi_mat) 00508 free(ifofile->vmgi_mat); 00509 00510 if(ifofile->vtsi_mat) 00511 free(ifofile->vtsi_mat); 00512 00513 DVDCloseFile(ifofile->file); 00514 ifofile->file = 0; 00515 free(ifofile); 00516 ifofile = 0; 00517 } 00518 00519 00520 static int ifoRead_VMG(ifo_handle_t *ifofile) { 00521 vmgi_mat_t *vmgi_mat; 00522 00523 vmgi_mat = (vmgi_mat_t *)malloc(sizeof(vmgi_mat_t)); 00524 if(!vmgi_mat) 00525 return 0; 00526 00527 ifofile->vmgi_mat = vmgi_mat; 00528 00529 if(!DVDFileSeek_(ifofile->file, 0)) { 00530 free(ifofile->vmgi_mat); 00531 ifofile->vmgi_mat = 0; 00532 return 0; 00533 } 00534 00535 if(!DVDReadBytes(ifofile->file, vmgi_mat, sizeof(vmgi_mat_t))) { 00536 free(ifofile->vmgi_mat); 00537 ifofile->vmgi_mat = 0; 00538 return 0; 00539 } 00540 00541 if(strncmp("DVDVIDEO-VMG", vmgi_mat->vmg_identifier, 12) != 0) { 00542 free(ifofile->vmgi_mat); 00543 ifofile->vmgi_mat = 0; 00544 return 0; 00545 } 00546 00547 B2N_32(vmgi_mat->vmg_last_sector); 00548 B2N_32(vmgi_mat->vmgi_last_sector); 00549 B2N_32(vmgi_mat->vmg_category); 00550 B2N_16(vmgi_mat->vmg_nr_of_volumes); 00551 B2N_16(vmgi_mat->vmg_this_volume_nr); 00552 B2N_16(vmgi_mat->vmg_nr_of_title_sets); 00553 B2N_64(vmgi_mat->vmg_pos_code); 00554 B2N_32(vmgi_mat->vmgi_last_byte); 00555 B2N_32(vmgi_mat->first_play_pgc); 00556 B2N_32(vmgi_mat->vmgm_vobs); 00557 B2N_32(vmgi_mat->tt_srpt); 00558 B2N_32(vmgi_mat->vmgm_pgci_ut); 00559 B2N_32(vmgi_mat->ptl_mait); 00560 B2N_32(vmgi_mat->vts_atrt); 00561 B2N_32(vmgi_mat->txtdt_mgi); 00562 B2N_32(vmgi_mat->vmgm_c_adt); 00563 B2N_32(vmgi_mat->vmgm_vobu_admap); 00564 read_video_attr(&vmgi_mat->vmgm_video_attr); 00565 read_audio_attr(&vmgi_mat->vmgm_audio_attr); 00566 read_subp_attr(&vmgi_mat->vmgm_subp_attr); 00567 00568 00569 CHECK_ZERO(vmgi_mat->zero_1); 00570 CHECK_ZERO(vmgi_mat->zero_2); 00571 CHECK_ZERO(vmgi_mat->zero_3); 00572 CHECK_ZERO(vmgi_mat->zero_4); 00573 CHECK_ZERO(vmgi_mat->zero_5); 00574 CHECK_ZERO(vmgi_mat->zero_6); 00575 CHECK_ZERO(vmgi_mat->zero_7); 00576 CHECK_ZERO(vmgi_mat->zero_8); 00577 CHECK_ZERO(vmgi_mat->zero_9); 00578 CHECK_ZERO(vmgi_mat->zero_10); 00579 CHECK_VALUE(vmgi_mat->vmg_last_sector != 0); 00580 CHECK_VALUE(vmgi_mat->vmgi_last_sector != 0); 00581 CHECK_VALUE(vmgi_mat->vmgi_last_sector * 2 <= vmgi_mat->vmg_last_sector); 00582 CHECK_VALUE(vmgi_mat->vmgi_last_sector * 2 <= vmgi_mat->vmg_last_sector); 00583 CHECK_VALUE(vmgi_mat->vmg_nr_of_volumes != 0); 00584 CHECK_VALUE(vmgi_mat->vmg_this_volume_nr != 0); 00585 CHECK_VALUE(vmgi_mat->vmg_this_volume_nr <= vmgi_mat->vmg_nr_of_volumes); 00586 CHECK_VALUE(vmgi_mat->disc_side == 1 || vmgi_mat->disc_side == 2); 00587 CHECK_VALUE(vmgi_mat->vmg_nr_of_title_sets != 0); 00588 CHECK_VALUE(vmgi_mat->vmgi_last_byte >= 341); 00589 CHECK_VALUE(vmgi_mat->vmgi_last_byte / DVD_BLOCK_LEN <= 00590 vmgi_mat->vmgi_last_sector); 00591 /* It seems that first_play_pgc is optional. */ 00592 CHECK_VALUE(vmgi_mat->first_play_pgc < vmgi_mat->vmgi_last_byte); 00593 CHECK_VALUE(vmgi_mat->vmgm_vobs == 0 || 00594 (vmgi_mat->vmgm_vobs > vmgi_mat->vmgi_last_sector && 00595 vmgi_mat->vmgm_vobs < vmgi_mat->vmg_last_sector)); 00596 CHECK_VALUE(vmgi_mat->tt_srpt <= vmgi_mat->vmgi_last_sector); 00597 CHECK_VALUE(vmgi_mat->vmgm_pgci_ut <= vmgi_mat->vmgi_last_sector); 00598 CHECK_VALUE(vmgi_mat->ptl_mait <= vmgi_mat->vmgi_last_sector); 00599 CHECK_VALUE(vmgi_mat->vts_atrt <= vmgi_mat->vmgi_last_sector); 00600 CHECK_VALUE(vmgi_mat->txtdt_mgi <= vmgi_mat->vmgi_last_sector); 00601 CHECK_VALUE(vmgi_mat->vmgm_c_adt <= vmgi_mat->vmgi_last_sector); 00602 CHECK_VALUE(vmgi_mat->vmgm_vobu_admap <= vmgi_mat->vmgi_last_sector); 00603 00604 CHECK_VALUE(vmgi_mat->nr_of_vmgm_audio_streams <= 1); 00605 CHECK_VALUE(vmgi_mat->nr_of_vmgm_subp_streams <= 1); 00606 00607 return 1; 00608 } 00609 00610 00611 static int ifoRead_VTS(ifo_handle_t *ifofile) { 00612 vtsi_mat_t *vtsi_mat; 00613 int i; 00614 00615 vtsi_mat = (vtsi_mat_t *)malloc(sizeof(vtsi_mat_t)); 00616 if(!vtsi_mat) 00617 return 0; 00618 00619 ifofile->vtsi_mat = vtsi_mat; 00620 00621 if(!DVDFileSeek_(ifofile->file, 0)) { 00622 free(ifofile->vtsi_mat); 00623 ifofile->vtsi_mat = 0; 00624 return 0; 00625 } 00626 00627 if(!(DVDReadBytes(ifofile->file, vtsi_mat, sizeof(vtsi_mat_t)))) { 00628 free(ifofile->vtsi_mat); 00629 ifofile->vtsi_mat = 0; 00630 return 0; 00631 } 00632 00633 if(strncmp("DVDVIDEO-VTS", vtsi_mat->vts_identifier, 12) != 0) { 00634 free(ifofile->vtsi_mat); 00635 ifofile->vtsi_mat = 0; 00636 return 0; 00637 } 00638 00639 read_video_attr(&vtsi_mat->vtsm_video_attr); 00640 read_video_attr(&vtsi_mat->vts_video_attr); 00641 read_audio_attr(&vtsi_mat->vtsm_audio_attr); 00642 for(i=0; i<8; i++) 00643 read_audio_attr(&vtsi_mat->vts_audio_attr[i]); 00644 read_subp_attr(&vtsi_mat->vtsm_subp_attr); 00645 for(i=0; i<32; i++) 00646 read_subp_attr(&vtsi_mat->vts_subp_attr[i]); 00647 B2N_32(vtsi_mat->vts_last_sector); 00648 B2N_32(vtsi_mat->vtsi_last_sector); 00649 B2N_32(vtsi_mat->vts_category); 00650 B2N_32(vtsi_mat->vtsi_last_byte); 00651 B2N_32(vtsi_mat->vtsm_vobs); 00652 B2N_32(vtsi_mat->vtstt_vobs); 00653 B2N_32(vtsi_mat->vts_ptt_srpt); 00654 B2N_32(vtsi_mat->vts_pgcit); 00655 B2N_32(vtsi_mat->vtsm_pgci_ut); 00656 B2N_32(vtsi_mat->vts_tmapt); 00657 B2N_32(vtsi_mat->vtsm_c_adt); 00658 B2N_32(vtsi_mat->vtsm_vobu_admap); 00659 B2N_32(vtsi_mat->vts_c_adt); 00660 B2N_32(vtsi_mat->vts_vobu_admap); 00661 00662 00663 CHECK_ZERO(vtsi_mat->zero_1); 00664 CHECK_ZERO(vtsi_mat->zero_2); 00665 CHECK_ZERO(vtsi_mat->zero_3); 00666 CHECK_ZERO(vtsi_mat->zero_4); 00667 CHECK_ZERO(vtsi_mat->zero_5); 00668 CHECK_ZERO(vtsi_mat->zero_6); 00669 CHECK_ZERO(vtsi_mat->zero_7); 00670 CHECK_ZERO(vtsi_mat->zero_8); 00671 CHECK_ZERO(vtsi_mat->zero_9); 00672 CHECK_ZERO(vtsi_mat->zero_10); 00673 CHECK_ZERO(vtsi_mat->zero_11); 00674 CHECK_ZERO(vtsi_mat->zero_12); 00675 CHECK_ZERO(vtsi_mat->zero_13); 00676 CHECK_ZERO(vtsi_mat->zero_14); 00677 CHECK_ZERO(vtsi_mat->zero_15); 00678 CHECK_ZERO(vtsi_mat->zero_16); 00679 CHECK_ZERO(vtsi_mat->zero_17); 00680 CHECK_ZERO(vtsi_mat->zero_18); 00681 CHECK_ZERO(vtsi_mat->zero_19); 00682 CHECK_ZERO(vtsi_mat->zero_20); 00683 CHECK_ZERO(vtsi_mat->zero_21); 00684 CHECK_VALUE(vtsi_mat->vtsi_last_sector*2 <= vtsi_mat->vts_last_sector); 00685 CHECK_VALUE(vtsi_mat->vtsi_last_byte/DVD_BLOCK_LEN <= vtsi_mat->vtsi_last_sector); 00686 CHECK_VALUE(vtsi_mat->vtsm_vobs == 0 || 00687 (vtsi_mat->vtsm_vobs > vtsi_mat->vtsi_last_sector && 00688 vtsi_mat->vtsm_vobs < vtsi_mat->vts_last_sector)); 00689 CHECK_VALUE(vtsi_mat->vtstt_vobs == 0 || 00690 (vtsi_mat->vtstt_vobs > vtsi_mat->vtsi_last_sector && 00691 vtsi_mat->vtstt_vobs < vtsi_mat->vts_last_sector)); 00692 CHECK_VALUE(vtsi_mat->vts_ptt_srpt <= vtsi_mat->vtsi_last_sector); 00693 CHECK_VALUE(vtsi_mat->vts_pgcit <= vtsi_mat->vtsi_last_sector); 00694 CHECK_VALUE(vtsi_mat->vtsm_pgci_ut <= vtsi_mat->vtsi_last_sector); 00695 CHECK_VALUE(vtsi_mat->vts_tmapt <= vtsi_mat->vtsi_last_sector); 00696 CHECK_VALUE(vtsi_mat->vtsm_c_adt <= vtsi_mat->vtsi_last_sector); 00697 CHECK_VALUE(vtsi_mat->vtsm_vobu_admap <= vtsi_mat->vtsi_last_sector); 00698 CHECK_VALUE(vtsi_mat->vts_c_adt <= vtsi_mat->vtsi_last_sector); 00699 CHECK_VALUE(vtsi_mat->vts_vobu_admap <= vtsi_mat->vtsi_last_sector); 00700 00701 CHECK_VALUE(vtsi_mat->nr_of_vtsm_audio_streams <= 1); 00702 CHECK_VALUE(vtsi_mat->nr_of_vtsm_subp_streams <= 1); 00703 00704 CHECK_VALUE(vtsi_mat->nr_of_vts_audio_streams <= 8); 00705 for(i = vtsi_mat->nr_of_vts_audio_streams; i < 8; i++) 00706 CHECK_ZERO(vtsi_mat->vts_audio_attr[i]); 00707 00708 CHECK_VALUE(vtsi_mat->nr_of_vts_subp_streams <= 32); 00709 for(i = vtsi_mat->nr_of_vts_subp_streams; i < 32; i++) 00710 CHECK_ZERO(vtsi_mat->vts_subp_attr[i]); 00711 00712 for(i = 0; i < 8; i++) { 00713 read_multichannel_ext(&vtsi_mat->vts_mu_audio_attr[i]); 00714 CHECK_ZERO0(vtsi_mat->vts_mu_audio_attr[i].zero1); 00715 CHECK_ZERO0(vtsi_mat->vts_mu_audio_attr[i].zero2); 00716 CHECK_ZERO0(vtsi_mat->vts_mu_audio_attr[i].zero3); 00717 CHECK_ZERO0(vtsi_mat->vts_mu_audio_attr[i].zero4); 00718 CHECK_ZERO0(vtsi_mat->vts_mu_audio_attr[i].zero5); 00719 CHECK_ZERO(vtsi_mat->vts_mu_audio_attr[i].zero6); 00720 } 00721 00722 return 1; 00723 } 00724 00725 00726 static int ifoRead_PGC_COMMAND_TBL(ifo_handle_t *ifofile, 00727 pgc_command_tbl_t *cmd_tbl, 00728 unsigned int offset) { 00729 00730 memset(cmd_tbl, 0, sizeof(pgc_command_tbl_t)); 00731 00732 if(!DVDFileSeek_(ifofile->file, offset)) 00733 return 0; 00734 00735 if(!(DVDReadBytes(ifofile->file, cmd_tbl, PGC_COMMAND_TBL_SIZE))) 00736 return 0; 00737 00738 B2N_16(cmd_tbl->nr_of_pre); 00739 B2N_16(cmd_tbl->nr_of_post); 00740 B2N_16(cmd_tbl->nr_of_cell); 00741 00742 CHECK_VALUE(cmd_tbl->nr_of_pre + cmd_tbl->nr_of_post + cmd_tbl->nr_of_cell<= 255); 00743 00744 if(cmd_tbl->nr_of_pre != 0) { 00745 unsigned int pre_cmds_size = cmd_tbl->nr_of_pre * COMMAND_DATA_SIZE; 00746 cmd_tbl->pre_cmds = (vm_cmd_t *)malloc(pre_cmds_size); 00747 if(!cmd_tbl->pre_cmds) 00748 return 0; 00749 00750 if(!(DVDReadBytes(ifofile->file, cmd_tbl->pre_cmds, pre_cmds_size))) { 00751 free(cmd_tbl->pre_cmds); 00752 return 0; 00753 } 00754 } 00755 00756 if(cmd_tbl->nr_of_post != 0) { 00757 unsigned int post_cmds_size = cmd_tbl->nr_of_post * COMMAND_DATA_SIZE; 00758 cmd_tbl->post_cmds = (vm_cmd_t *)malloc(post_cmds_size); 00759 if(!cmd_tbl->post_cmds) { 00760 if(cmd_tbl->pre_cmds) 00761 free(cmd_tbl->pre_cmds); 00762 return 0; 00763 } 00764 if(!(DVDReadBytes(ifofile->file, cmd_tbl->post_cmds, post_cmds_size))) { 00765 if(cmd_tbl->pre_cmds) 00766 free(cmd_tbl->pre_cmds); 00767 free(cmd_tbl->post_cmds); 00768 return 0; 00769 } 00770 } 00771 00772 if(cmd_tbl->nr_of_cell != 0) { 00773 unsigned int cell_cmds_size = cmd_tbl->nr_of_cell * COMMAND_DATA_SIZE; 00774 cmd_tbl->cell_cmds = (vm_cmd_t *)malloc(cell_cmds_size); 00775 if(!cmd_tbl->cell_cmds) { 00776 if(cmd_tbl->pre_cmds) 00777 free(cmd_tbl->pre_cmds); 00778 if(cmd_tbl->post_cmds) 00779 free(cmd_tbl->post_cmds); 00780 return 0; 00781 } 00782 if(!(DVDReadBytes(ifofile->file, cmd_tbl->cell_cmds, cell_cmds_size))) { 00783 if(cmd_tbl->pre_cmds) 00784 free(cmd_tbl->pre_cmds); 00785 if(cmd_tbl->post_cmds) 00786 free(cmd_tbl->post_cmds); 00787 free(cmd_tbl->cell_cmds); 00788 return 0; 00789 } 00790 } 00791 00792 /* 00793 * Make a run over all the commands and see that we can interpret them all? 00794 */ 00795 return 1; 00796 } 00797 00798 00799 static void ifoFree_PGC_COMMAND_TBL(pgc_command_tbl_t *cmd_tbl) { 00800 if(cmd_tbl) { 00801 if(cmd_tbl->nr_of_pre && cmd_tbl->pre_cmds) 00802 free(cmd_tbl->pre_cmds); 00803 if(cmd_tbl->nr_of_post && cmd_tbl->post_cmds) 00804 free(cmd_tbl->post_cmds); 00805 if(cmd_tbl->nr_of_cell && cmd_tbl->cell_cmds) 00806 free(cmd_tbl->cell_cmds); 00807 free(cmd_tbl); 00808 } 00809 } 00810 00811 static int ifoRead_PGC_PROGRAM_MAP(ifo_handle_t *ifofile, 00812 pgc_program_map_t *program_map, 00813 unsigned int nr, unsigned int offset) { 00814 unsigned int size = nr * sizeof(pgc_program_map_t); 00815 00816 if(!DVDFileSeek_(ifofile->file, offset)) 00817 return 0; 00818 00819 if(!(DVDReadBytes(ifofile->file, program_map, size))) 00820 return 0; 00821 00822 return 1; 00823 } 00824 00825 static int ifoRead_CELL_PLAYBACK_TBL(ifo_handle_t *ifofile, 00826 cell_playback_t *cell_playback, 00827 unsigned int nr, unsigned int offset) { 00828 unsigned int i; 00829 unsigned int size = nr * sizeof(cell_playback_t); 00830 00831 if(!DVDFileSeek_(ifofile->file, offset)) 00832 return 0; 00833 00834 if(!(DVDReadBytes(ifofile->file, cell_playback, size))) 00835 return 0; 00836 00837 for(i = 0; i < nr; i++) { 00838 read_cell_playback(&cell_playback[i]); 00839 /* Changed < to <= because this was false in the movie 'Pi'. */ 00840 CHECK_VALUE(cell_playback[i].last_vobu_start_sector <= 00841 cell_playback[i].last_sector); 00842 CHECK_VALUE(cell_playback[i].first_sector <= 00843 cell_playback[i].last_vobu_start_sector); 00844 } 00845 00846 return 1; 00847 } 00848 00849 00850 static int ifoRead_CELL_POSITION_TBL(ifo_handle_t *ifofile, 00851 cell_position_t *cell_position, 00852 unsigned int nr, unsigned int offset) { 00853 unsigned int i; 00854 unsigned int size = nr * sizeof(cell_position_t); 00855 00856 if(!DVDFileSeek_(ifofile->file, offset)) 00857 return 0; 00858 00859 if(!(DVDReadBytes(ifofile->file, cell_position, size))) 00860 return 0; 00861 00862 for(i = 0; i < nr; i++) { 00863 B2N_16(cell_position[i].vob_id_nr); 00864 CHECK_ZERO(cell_position[i].zero_1); 00865 } 00866 00867 return 1; 00868 } 00869 00870 static int ifoRead_PGC(ifo_handle_t *ifofile, pgc_t *pgc, unsigned int offset) { 00871 unsigned int i; 00872 00873 if(!DVDFileSeek_(ifofile->file, offset)) 00874 return 0; 00875 00876 if(!(DVDReadBytes(ifofile->file, pgc, PGC_SIZE))) 00877 return 0; 00878 00879 read_user_ops(&pgc->prohibited_ops); 00880 B2N_16(pgc->next_pgc_nr); 00881 B2N_16(pgc->prev_pgc_nr); 00882 B2N_16(pgc->goup_pgc_nr); 00883 B2N_16(pgc->command_tbl_offset); 00884 B2N_16(pgc->program_map_offset); 00885 B2N_16(pgc->cell_playback_offset); 00886 B2N_16(pgc->cell_position_offset); 00887 00888 for(i = 0; i < 8; i++) 00889 B2N_16(pgc->audio_control[i]); 00890 for(i = 0; i < 32; i++) 00891 B2N_32(pgc->subp_control[i]); 00892 for(i = 0; i < 16; i++) 00893 B2N_32(pgc->palette[i]); 00894 00895 CHECK_ZERO(pgc->zero_1); 00896 CHECK_VALUE(pgc->nr_of_programs <= pgc->nr_of_cells); 00897 00898 /* verify time (look at print_time) */ 00899 for(i = 0; i < 8; i++) 00900 if(!(pgc->audio_control[i] & 0x8000)) /* The 'is present' bit */ 00901 CHECK_ZERO(pgc->audio_control[i]); 00902 for(i = 0; i < 32; i++) 00903 if(!(pgc->subp_control[i] & 0x80000000)) /* The 'is present' bit */ 00904 CHECK_ZERO(pgc->subp_control[i]); 00905 00906 /* Check that time is 0:0:0:0 also if nr_of_programs == 0 */ 00907 if(pgc->nr_of_programs == 0) { 00908 CHECK_ZERO(pgc->still_time); 00909 CHECK_ZERO(pgc->pg_playback_mode); /* ?? */ 00910 CHECK_VALUE(pgc->program_map_offset == 0); 00911 CHECK_VALUE(pgc->cell_playback_offset == 0); 00912 CHECK_VALUE(pgc->cell_position_offset == 0); 00913 } else { 00914 CHECK_VALUE(pgc->program_map_offset != 0); 00915 CHECK_VALUE(pgc->cell_playback_offset != 0); 00916 CHECK_VALUE(pgc->cell_position_offset != 0); 00917 } 00918 00919 if(pgc->command_tbl_offset != 0) { 00920 pgc->command_tbl = malloc(sizeof(pgc_command_tbl_t)); 00921 if(!pgc->command_tbl) 00922 return 0; 00923 00924 if(!ifoRead_PGC_COMMAND_TBL(ifofile, pgc->command_tbl, 00925 offset + pgc->command_tbl_offset)) { 00926 free(pgc->command_tbl); 00927 return 0; 00928 } 00929 } else { 00930 pgc->command_tbl = NULL; 00931 } 00932 00933 if(pgc->program_map_offset != 0 && pgc->nr_of_programs>0) { 00934 pgc->program_map = malloc(pgc->nr_of_programs * sizeof(pgc_program_map_t)); 00935 if(!pgc->program_map) { 00936 ifoFree_PGC_COMMAND_TBL(pgc->command_tbl); 00937 return 0; 00938 } 00939 if(!ifoRead_PGC_PROGRAM_MAP(ifofile, pgc->program_map,pgc->nr_of_programs, 00940 offset + pgc->program_map_offset)) { 00941 ifoFree_PGC_COMMAND_TBL(pgc->command_tbl); 00942 free(pgc->program_map); 00943 return 0; 00944 } 00945 } else { 00946 pgc->program_map = NULL; 00947 } 00948 00949 if(pgc->cell_playback_offset != 0 && pgc->nr_of_cells>0) { 00950 pgc->cell_playback = malloc(pgc->nr_of_cells * sizeof(cell_playback_t)); 00951 if(!pgc->cell_playback) { 00952 ifoFree_PGC_COMMAND_TBL(pgc->command_tbl); 00953 if(pgc->program_map) 00954 free(pgc->program_map); 00955 return 0; 00956 } 00957 if(!ifoRead_CELL_PLAYBACK_TBL(ifofile, pgc->cell_playback, 00958 pgc->nr_of_cells, 00959 offset + pgc->cell_playback_offset)) { 00960 ifoFree_PGC_COMMAND_TBL(pgc->command_tbl); 00961 if(pgc->program_map) 00962 free(pgc->program_map); 00963 free(pgc->cell_playback); 00964 return 0; 00965 } 00966 } else { 00967 pgc->cell_playback = NULL; 00968 } 00969 00970 if(pgc->cell_position_offset != 0 && pgc->nr_of_cells>0) { 00971 pgc->cell_position = malloc(pgc->nr_of_cells * sizeof(cell_position_t)); 00972 if(!pgc->cell_position) { 00973 ifoFree_PGC(pgc); 00974 return 0; 00975 } 00976 if(!ifoRead_CELL_POSITION_TBL(ifofile, pgc->cell_position, 00977 pgc->nr_of_cells, 00978 offset + pgc->cell_position_offset)) { 00979 ifoFree_PGC(pgc); 00980 return 0; 00981 } 00982 } else { 00983 pgc->cell_position = NULL; 00984 } 00985 00986 return 1; 00987 } 00988 00989 int ifoRead_FP_PGC(ifo_handle_t *ifofile) { 00990 00991 if(!ifofile) 00992 return 0; 00993 00994 if(!ifofile->vmgi_mat) 00995 return 0; 00996 00997 /* It seems that first_play_pgc is optional after all. */ 00998 ifofile->first_play_pgc = 0; 00999 if(ifofile->vmgi_mat->first_play_pgc == 0) 01000 return 1; 01001 01002 ifofile->first_play_pgc = (pgc_t *)malloc(sizeof(pgc_t)); 01003 if(!ifofile->first_play_pgc) 01004 return 0; 01005 01006 if(!ifoRead_PGC(ifofile, ifofile->first_play_pgc, 01007 ifofile->vmgi_mat->first_play_pgc)) { 01008 free(ifofile->first_play_pgc); 01009 ifofile->first_play_pgc = 0; 01010 return 0; 01011 } 01012 01013 return 1; 01014 } 01015 01016 static void ifoFree_PGC(pgc_t *pgc) { 01017 if(pgc) { 01018 ifoFree_PGC_COMMAND_TBL(pgc->command_tbl); 01019 if(pgc->program_map) 01020 free(pgc->program_map); 01021 if(pgc->cell_playback) 01022 free(pgc->cell_playback); 01023 if(pgc->cell_position) 01024 free(pgc->cell_position); 01025 } 01026 } 01027 01028 void ifoFree_FP_PGC(ifo_handle_t *ifofile) { 01029 if(!ifofile) 01030 return; 01031 01032 if(ifofile->first_play_pgc) { 01033 ifoFree_PGC(ifofile->first_play_pgc); 01034 free(ifofile->first_play_pgc); 01035 ifofile->first_play_pgc = 0; 01036 } 01037 } 01038 01039 01040 int ifoRead_TT_SRPT(ifo_handle_t *ifofile) { 01041 tt_srpt_t *tt_srpt; 01042 int i, info_length; 01043 01044 if(!ifofile) 01045 return 0; 01046 01047 if(!ifofile->vmgi_mat) 01048 return 0; 01049 01050 if(ifofile->vmgi_mat->tt_srpt == 0) /* mandatory */ 01051 return 0; 01052 01053 if(!DVDFileSeek_(ifofile->file, ifofile->vmgi_mat->tt_srpt * DVD_BLOCK_LEN)) 01054 return 0; 01055 01056 tt_srpt = (tt_srpt_t *)malloc(sizeof(tt_srpt_t)); 01057 if(!tt_srpt) 01058 return 0; 01059 01060 ifofile->tt_srpt = tt_srpt; 01061 01062 if(!(DVDReadBytes(ifofile->file, tt_srpt, TT_SRPT_SIZE))) { 01063 fprintf(stderr, "libdvdread: Unable to read read TT_SRPT.\n"); 01064 free(tt_srpt); 01065 return 0; 01066 } 01067 01068 B2N_16(tt_srpt->nr_of_srpts); 01069 B2N_32(tt_srpt->last_byte); 01070 01071 info_length = tt_srpt->last_byte + 1 - TT_SRPT_SIZE; 01072 01073 tt_srpt->title = (title_info_t *)malloc(info_length); 01074 if(!tt_srpt->title) { 01075 free(tt_srpt); 01076 ifofile->tt_srpt = 0; 01077 return 0; 01078 } 01079 if(!(DVDReadBytes(ifofile->file, tt_srpt->title, info_length))) { 01080 fprintf(stderr, "libdvdread: Unable to read read TT_SRPT.\n"); 01081 ifoFree_TT_SRPT(ifofile); 01082 return 0; 01083 } 01084 01085 for(i = 0; i < tt_srpt->nr_of_srpts; i++) { 01086 B2N_16(tt_srpt->title[i].nr_of_ptts); 01087 B2N_16(tt_srpt->title[i].parental_id); 01088 B2N_32(tt_srpt->title[i].title_set_sector); 01089 } 01090 01091 01092 CHECK_ZERO(tt_srpt->zero_1); 01093 CHECK_VALUE(tt_srpt->nr_of_srpts != 0); 01094 CHECK_VALUE(tt_srpt->nr_of_srpts < 100); /* ?? */ 01095 CHECK_VALUE((int)tt_srpt->nr_of_srpts * sizeof(title_info_t) <= info_length); 01096 01097 for(i = 0; i < tt_srpt->nr_of_srpts; i++) { 01098 read_playback_type(&tt_srpt->title[i].pb_ty); 01099 CHECK_VALUE(tt_srpt->title[i].pb_ty.zero_1 == 0); 01100 CHECK_VALUE(tt_srpt->title[i].nr_of_angles != 0); 01101 CHECK_VALUE(tt_srpt->title[i].nr_of_angles < 10); 01102 /* CHECK_VALUE(tt_srpt->title[i].nr_of_ptts != 0); */ 01103 /* XXX: this assertion breaks Ghostbusters: */ 01104 CHECK_VALUE(tt_srpt->title[i].nr_of_ptts < 1000); /* ?? */ 01105 CHECK_VALUE(tt_srpt->title[i].title_set_nr != 0); 01106 CHECK_VALUE(tt_srpt->title[i].title_set_nr < 100); /* ?? */ 01107 CHECK_VALUE(tt_srpt->title[i].vts_ttn != 0); 01108 CHECK_VALUE(tt_srpt->title[i].vts_ttn < 100); /* ?? */ 01109 /* CHECK_VALUE(tt_srpt->title[i].title_set_sector != 0); */ 01110 } 01111 01112 /* Make this a function */ 01113 #if 0 01114 if(memcmp((uint8_t *)tt_srpt->title + 01115 tt_srpt->nr_of_srpts * sizeof(title_info_t), 01116 my_friendly_zeros, 01117 info_length - tt_srpt->nr_of_srpts * sizeof(title_info_t))) { 01118 fprintf(stderr, "VMG_PTT_SRPT slack is != 0, "); 01119 hexdump((uint8_t *)tt_srpt->title + 01120 tt_srpt->nr_of_srpts * sizeof(title_info_t), 01121 info_length - tt_srpt->nr_of_srpts * sizeof(title_info_t)); 01122 } 01123 #endif 01124 01125 return 1; 01126 } 01127 01128 01129 void ifoFree_TT_SRPT(ifo_handle_t *ifofile) { 01130 if(!ifofile) 01131 return; 01132 01133 if(ifofile->tt_srpt) { 01134 free(ifofile->tt_srpt->title); 01135 free(ifofile->tt_srpt); 01136 ifofile->tt_srpt = 0; 01137 } 01138 } 01139 01140 01141 int ifoRead_VTS_PTT_SRPT(ifo_handle_t *ifofile) { 01142 vts_ptt_srpt_t *vts_ptt_srpt = NULL; 01143 int info_length, i, j; 01144 uint32_t *data = NULL; 01145 01146 if(!ifofile) 01147 return 0; 01148 01149 if(!ifofile->vtsi_mat) 01150 return 0; 01151 01152 if(ifofile->vtsi_mat->vts_ptt_srpt == 0) /* mandatory */ 01153 return 0; 01154 01155 if(!DVDFileSeek_(ifofile->file, 01156 ifofile->vtsi_mat->vts_ptt_srpt * DVD_BLOCK_LEN)) 01157 return 0; 01158 01159 vts_ptt_srpt = malloc(sizeof(vts_ptt_srpt_t)); 01160 if(!vts_ptt_srpt) 01161 return 0; 01162 01163 vts_ptt_srpt->title = NULL; 01164 ifofile->vts_ptt_srpt = vts_ptt_srpt; 01165 01166 if(!(DVDReadBytes(ifofile->file, vts_ptt_srpt, VTS_PTT_SRPT_SIZE))) { 01167 fprintf(stderr, "libdvdread: Unable to read PTT search table.\n"); 01168 goto fail; 01169 } 01170 01171 B2N_16(vts_ptt_srpt->nr_of_srpts); 01172 B2N_32(vts_ptt_srpt->last_byte); 01173 01174 CHECK_ZERO(vts_ptt_srpt->zero_1); 01175 CHECK_VALUE(vts_ptt_srpt->nr_of_srpts != 0); 01176 CHECK_VALUE(vts_ptt_srpt->nr_of_srpts < 100); /* ?? */ 01177 01178 info_length = vts_ptt_srpt->last_byte + 1 - VTS_PTT_SRPT_SIZE; 01179 data = malloc(info_length); 01180 if(!data) 01181 goto fail; 01182 01183 if(!(DVDReadBytes(ifofile->file, data, info_length))) { 01184 fprintf(stderr, "libdvdread: Unable to read PTT search table.\n"); 01185 goto fail; 01186 } 01187 01188 if(vts_ptt_srpt->nr_of_srpts > info_length / sizeof(*data)) { 01189 fprintf(stderr, "libdvdread: PTT search table too small.\n"); 01190 goto fail; 01191 } 01192 for(i = 0; i < vts_ptt_srpt->nr_of_srpts; i++) { 01193 B2N_32(data[i]); 01194 /* assert(data[i] + sizeof(ptt_info_t) <= vts_ptt_srpt->last_byte + 1); 01195 Magic Knight Rayearth Daybreak is mastered very strange and has 01196 Titles with 0 PTTs. They all have a data[i] offsets beyond the end of 01197 of the vts_ptt_srpt structure. */ 01198 CHECK_VALUE(data[i] + sizeof(ptt_info_t) <= vts_ptt_srpt->last_byte + 1 + 4); 01199 } 01200 01201 vts_ptt_srpt->ttu_offset = data; 01202 01203 vts_ptt_srpt->title = malloc(vts_ptt_srpt->nr_of_srpts * sizeof(ttu_t)); 01204 if(!vts_ptt_srpt->title) 01205 goto fail; 01206 01207 for(i = 0; i < vts_ptt_srpt->nr_of_srpts; i++) { 01208 int n; 01209 if(i < vts_ptt_srpt->nr_of_srpts - 1) 01210 n = (data[i+1] - data[i]); 01211 else 01212 n = (vts_ptt_srpt->last_byte + 1 - data[i]); 01213 01214 /* assert(n > 0 && (n % 4) == 0); 01215 Magic Knight Rayearth Daybreak is mastered very strange and has 01216 Titles with 0 PTTs. */ 01217 if(n < 0) n = 0; 01218 01219 CHECK_VALUE(n % 4 == 0); 01220 01221 vts_ptt_srpt->title[i].nr_of_ptts = n / 4; 01222 vts_ptt_srpt->title[i].ptt = malloc(n * sizeof(ptt_info_t)); 01223 if(!vts_ptt_srpt->title[i].ptt) { 01224 for(n = 0; n < i; n++) 01225 free(vts_ptt_srpt->title[n].ptt); 01226 01227 goto fail; 01228 } 01229 for(j = 0; j < vts_ptt_srpt->title[i].nr_of_ptts; j++) { 01230 /* The assert placed here because of Magic Knight Rayearth Daybreak */ 01231 CHECK_VALUE(data[i] + sizeof(ptt_info_t) <= vts_ptt_srpt->last_byte + 1); 01232 vts_ptt_srpt->title[i].ptt[j].pgcn 01233 = *(uint16_t*)(((char *)data) + data[i] + 4*j - VTS_PTT_SRPT_SIZE); 01234 vts_ptt_srpt->title[i].ptt[j].pgn 01235 = *(uint16_t*)(((char *)data) + data[i] + 4*j + 2 - VTS_PTT_SRPT_SIZE); 01236 } 01237 } 01238 01239 for(i = 0; i < vts_ptt_srpt->nr_of_srpts; i++) { 01240 for(j = 0; j < vts_ptt_srpt->title[i].nr_of_ptts; j++) { 01241 B2N_16(vts_ptt_srpt->title[i].ptt[j].pgcn); 01242 B2N_16(vts_ptt_srpt->title[i].ptt[j].pgn); 01243 } 01244 } 01245 01246 for(i = 0; i < vts_ptt_srpt->nr_of_srpts; i++) { 01247 CHECK_VALUE(vts_ptt_srpt->title[i].nr_of_ptts < 1000); /* ?? */ 01248 for(j = 0; j < vts_ptt_srpt->title[i].nr_of_ptts; j++) { 01249 CHECK_VALUE(vts_ptt_srpt->title[i].ptt[j].pgcn != 0 ); 01250 CHECK_VALUE(vts_ptt_srpt->title[i].ptt[j].pgcn < 1000); /* ?? */ 01251 CHECK_VALUE(vts_ptt_srpt->title[i].ptt[j].pgn != 0); 01252 CHECK_VALUE(vts_ptt_srpt->title[i].ptt[j].pgn < 100); /* ?? */ 01253 } 01254 } 01255 01256 return 1; 01257 01258 fail: 01259 free(data); 01260 ifofile->vts_ptt_srpt = 0; 01261 free(vts_ptt_srpt->title); 01262 free(vts_ptt_srpt); 01263 return 0; 01264 } 01265 01266 01267 void ifoFree_VTS_PTT_SRPT(ifo_handle_t *ifofile) { 01268 if(!ifofile) 01269 return; 01270 01271 if(ifofile->vts_ptt_srpt) { 01272 int i; 01273 for(i = 0; i < ifofile->vts_ptt_srpt->nr_of_srpts; i++) 01274 free(ifofile->vts_ptt_srpt->title[i].ptt); 01275 free(ifofile->vts_ptt_srpt->ttu_offset); 01276 free(ifofile->vts_ptt_srpt->title); 01277 free(ifofile->vts_ptt_srpt); 01278 ifofile->vts_ptt_srpt = 0; 01279 } 01280 } 01281 01282 01283 int ifoRead_PTL_MAIT(ifo_handle_t *ifofile) { 01284 ptl_mait_t *ptl_mait; 01285 int info_length; 01286 unsigned int i, j; 01287 01288 if(!ifofile) 01289 return 0; 01290 01291 if(!ifofile->vmgi_mat) 01292 return 0; 01293 01294 if(ifofile->vmgi_mat->ptl_mait == NULL) 01295 return 1; 01296 01297 if(!DVDFileSeek_(ifofile->file, ifofile->vmgi_mat->ptl_mait * DVD_BLOCK_LEN)) 01298 return 0; 01299 01300 ptl_mait = (ptl_mait_t *)malloc(sizeof(ptl_mait_t)); 01301 if(!ptl_mait) 01302 return 0; 01303 01304 ifofile->ptl_mait = ptl_mait; 01305 01306 if(!(DVDReadBytes(ifofile->file, ptl_mait, PTL_MAIT_SIZE))) { 01307 free(ptl_mait); 01308 ifofile->ptl_mait = NULL; 01309 return 0; 01310 } 01311 01312 B2N_16(ptl_mait->nr_of_countries); 01313 B2N_16(ptl_mait->nr_of_vtss); 01314 B2N_32(ptl_mait->last_byte); 01315 01316 CHECK_VALUE(ptl_mait->nr_of_countries != 0); 01317 CHECK_VALUE(ptl_mait->nr_of_countries < 100); /* ?? */ 01318 CHECK_VALUE(ptl_mait->nr_of_vtss != 0); 01319 CHECK_VALUE(ptl_mait->nr_of_vtss < 100); /* ?? */ 01320 CHECK_VALUE(ptl_mait->nr_of_countries * PTL_MAIT_COUNTRY_SIZE 01321 <= ptl_mait->last_byte + 1 - PTL_MAIT_SIZE); 01322 01323 info_length = ptl_mait->nr_of_countries * sizeof(ptl_mait_country_t); 01324 ptl_mait->countries = (ptl_mait_country_t *)malloc(info_length); 01325 if(!ptl_mait->countries) { 01326 free(ptl_mait); 01327 ifofile->ptl_mait = NULL; 01328 return 0; 01329 } 01330 for(i = 0; i < ptl_mait->nr_of_countries; i++) { 01331 ptl_mait->countries[i].pf_ptl_mai = NULL; 01332 } 01333 01334 for(i = 0; i < ptl_mait->nr_of_countries; i++) { 01335 if(!(DVDReadBytes(ifofile->file, &ptl_mait->countries[i], PTL_MAIT_COUNTRY_SIZE))) { 01336 fprintf(stderr, "libdvdread: Unable to read PTL_MAIT.\n"); 01337 free(ptl_mait->countries); 01338 free(ptl_mait); 01339 ifofile->ptl_mait = NULL; 01340 return 0; 01341 } 01342 } 01343 01344 for(i = 0; i < ptl_mait->nr_of_countries; i++) { 01345 B2N_16(ptl_mait->countries[i].country_code); 01346 B2N_16(ptl_mait->countries[i].pf_ptl_mai_start_byte); 01347 } 01348 01349 for(i = 0; i < ptl_mait->nr_of_countries; i++) { 01350 CHECK_ZERO(ptl_mait->countries[i].zero_1); 01351 CHECK_ZERO(ptl_mait->countries[i].zero_2); 01352 CHECK_VALUE(ptl_mait->countries[i].pf_ptl_mai_start_byte 01353 + sizeof(pf_level_t) * (ptl_mait->nr_of_vtss + 1) <= ptl_mait->last_byte + 1); 01354 } 01355 01356 for(i = 0; i < ptl_mait->nr_of_countries; i++) { 01357 uint16_t *pf_temp; 01358 01359 if(!DVDFileSeek_(ifofile->file, 01360 ifofile->vmgi_mat->ptl_mait * DVD_BLOCK_LEN 01361 + ptl_mait->countries[i].pf_ptl_mai_start_byte)) { 01362 fprintf(stderr, "libdvdread: Unable to seek PTL_MAIT table at index %d.\n",i); 01363 free(ptl_mait->countries); 01364 free(ptl_mait); 01365 ifofile->ptl_mait = NULL; 01366 return 0; 01367 } 01368 info_length = (ptl_mait->nr_of_vtss + 1) * sizeof(pf_level_t); 01369 pf_temp = (uint16_t *)malloc(info_length); 01370 if(!pf_temp) { 01371 free_ptl_mait(ptl_mait, i); 01372 ifofile->ptl_mait = NULL; 01373 return 0; 01374 } 01375 if(!(DVDReadBytes(ifofile->file, pf_temp, info_length))) { 01376 fprintf(stderr, "libdvdread: Unable to read PTL_MAIT table at index %d.\n",i); 01377 free(pf_temp); 01378 free_ptl_mait(ptl_mait, i); 01379 ifofile->ptl_mait = NULL; 01380 return 0; 01381 } 01382 for (j = 0; j < ((ptl_mait->nr_of_vtss + 1) * 8); j++) { 01383 B2N_16(pf_temp[j]); 01384 } 01385 ptl_mait->countries[i].pf_ptl_mai = (pf_level_t *)malloc(info_length); 01386 if(!ptl_mait->countries[i].pf_ptl_mai) { 01387 free(pf_temp); 01388 free_ptl_mait(ptl_mait, i); 01389 ifofile->ptl_mait = NULL; 01390 return 0; 01391 } 01392 { /* Transpose the array so we can use C indexing. */ 01393 int level, vts; 01394 for(level = 0; level < PTL_MAIT_NUM_LEVEL; level++) { 01395 for(vts = 0; vts <= ptl_mait->nr_of_vtss; vts++) { 01396 ptl_mait->countries[i].pf_ptl_mai[vts][level] = 01397 pf_temp[(7-level)*(ptl_mait->nr_of_vtss+1) + vts]; 01398 } 01399 } 01400 free(pf_temp); 01401 } 01402 } 01403 return 1; 01404 } 01405 01406 void ifoFree_PTL_MAIT(ifo_handle_t *ifofile) { 01407 unsigned int i; 01408 01409 if(!ifofile) 01410 return; 01411 01412 if(ifofile->ptl_mait) { 01413 for(i = 0; i < ifofile->ptl_mait->nr_of_countries; i++) { 01414 free(ifofile->ptl_mait->countries[i].pf_ptl_mai); 01415 } 01416 free(ifofile->ptl_mait->countries); 01417 free(ifofile->ptl_mait); 01418 ifofile->ptl_mait = NULL; 01419 } 01420 } 01421 01422 int ifoRead_VTS_TMAPT(ifo_handle_t *ifofile) { 01423 vts_tmapt_t *vts_tmapt; 01424 uint32_t *vts_tmap_srp; 01425 unsigned int offset; 01426 int info_length; 01427 unsigned int i, j; 01428 01429 if(!ifofile) 01430 return 0; 01431 01432 if(!ifofile->vtsi_mat) 01433 return 0; 01434 01435 if(ifofile->vtsi_mat->vts_tmapt == 0) { /* optional(?) */ 01436 ifofile->vts_tmapt = NULL; 01437 fprintf(stderr,"Please send bug report - no VTS_TMAPT ?? \n"); 01438 return 1; 01439 } 01440 01441 offset = ifofile->vtsi_mat->vts_tmapt * DVD_BLOCK_LEN; 01442 01443 if(!DVDFileSeek_(ifofile->file, offset)) 01444 return 0; 01445 01446 vts_tmapt = (vts_tmapt_t *)malloc(sizeof(vts_tmapt_t)); 01447 if(!vts_tmapt) 01448 return 0; 01449 01450 ifofile->vts_tmapt = vts_tmapt; 01451 01452 if(!(DVDReadBytes(ifofile->file, vts_tmapt, VTS_TMAPT_SIZE))) { 01453 fprintf(stderr, "libdvdread: Unable to read VTS_TMAPT.\n"); 01454 free(vts_tmapt); 01455 ifofile->vts_tmapt = NULL; 01456 return 0; 01457 } 01458 01459 B2N_16(vts_tmapt->nr_of_tmaps); 01460 B2N_32(vts_tmapt->last_byte); 01461 01462 CHECK_ZERO(vts_tmapt->zero_1); 01463 01464 info_length = vts_tmapt->nr_of_tmaps * 4; 01465 01466 vts_tmap_srp = (uint32_t *)malloc(info_length); 01467 if(!vts_tmap_srp) { 01468 free(vts_tmapt); 01469 ifofile->vts_tmapt = NULL; 01470 return 0; 01471 } 01472 01473 vts_tmapt->tmap_offset = vts_tmap_srp; 01474 01475 if(!(DVDReadBytes(ifofile->file, vts_tmap_srp, info_length))) { 01476 fprintf(stderr, "libdvdread: Unable to read VTS_TMAPT.\n"); 01477 free(vts_tmap_srp); 01478 free(vts_tmapt); 01479 ifofile->vts_tmapt = NULL; 01480 return 0; 01481 } 01482 01483 for (i = 0; i < vts_tmapt->nr_of_tmaps; i++) { 01484 B2N_32(vts_tmap_srp[i]); 01485 } 01486 01487 01488 info_length = vts_tmapt->nr_of_tmaps * sizeof(vts_tmap_t); 01489 01490 vts_tmapt->tmap = (vts_tmap_t *)malloc(info_length); 01491 if(!vts_tmapt->tmap) { 01492 free(vts_tmap_srp); 01493 free(vts_tmapt); 01494 ifofile->vts_tmapt = NULL; 01495 return 0; 01496 } 01497 01498 memset(vts_tmapt->tmap, 0, info_length); /* So ifoFree_VTS_TMAPT works. */ 01499 01500 for(i = 0; i < vts_tmapt->nr_of_tmaps; i++) { 01501 if(!DVDFileSeek_(ifofile->file, offset + vts_tmap_srp[i])) { 01502 ifoFree_VTS_TMAPT(ifofile); 01503 return 0; 01504 } 01505 01506 if(!(DVDReadBytes(ifofile->file, &vts_tmapt->tmap[i], VTS_TMAP_SIZE))) { 01507 fprintf(stderr, "libdvdread: Unable to read VTS_TMAP.\n"); 01508 ifoFree_VTS_TMAPT(ifofile); 01509 return 0; 01510 } 01511 01512 B2N_16(vts_tmapt->tmap[i].nr_of_entries); 01513 CHECK_ZERO(vts_tmapt->tmap[i].zero_1); 01514 01515 if(vts_tmapt->tmap[i].nr_of_entries == 0) { /* Early out if zero entries */ 01516 vts_tmapt->tmap[i].map_ent = NULL; 01517 continue; 01518 } 01519 01520 info_length = vts_tmapt->tmap[i].nr_of_entries * sizeof(map_ent_t); 01521 01522 vts_tmapt->tmap[i].map_ent = (map_ent_t *)malloc(info_length); 01523 if(!vts_tmapt->tmap[i].map_ent) { 01524 ifoFree_VTS_TMAPT(ifofile); 01525 return 0; 01526 } 01527 01528 if(!(DVDReadBytes(ifofile->file, vts_tmapt->tmap[i].map_ent, info_length))) { 01529 fprintf(stderr, "libdvdread: Unable to read VTS_TMAP_ENT.\n"); 01530 ifoFree_VTS_TMAPT(ifofile); 01531 return 0; 01532 } 01533 01534 for(j = 0; j < vts_tmapt->tmap[i].nr_of_entries; j++) 01535 B2N_32(vts_tmapt->tmap[i].map_ent[j]); 01536 } 01537 01538 return 1; 01539 } 01540 01541 void ifoFree_VTS_TMAPT(ifo_handle_t *ifofile) { 01542 unsigned int i; 01543 01544 if(!ifofile) 01545 return; 01546 01547 if(ifofile->vts_tmapt) { 01548 for(i = 0; i < ifofile->vts_tmapt->nr_of_tmaps; i++) 01549 if(ifofile->vts_tmapt->tmap[i].map_ent) 01550 free(ifofile->vts_tmapt->tmap[i].map_ent); 01551 free(ifofile->vts_tmapt->tmap); 01552 free(ifofile->vts_tmapt->tmap_offset); 01553 free(ifofile->vts_tmapt); 01554 ifofile->vts_tmapt = NULL; 01555 } 01556 } 01557 01558 01559 int ifoRead_TITLE_C_ADT(ifo_handle_t *ifofile) { 01560 01561 if(!ifofile) 01562 return 0; 01563 01564 if(!ifofile->vtsi_mat) 01565 return 0; 01566 01567 if(ifofile->vtsi_mat->vts_c_adt == 0) /* mandatory */ 01568 return 0; 01569 01570 ifofile->vts_c_adt = (c_adt_t *)malloc(sizeof(c_adt_t)); 01571 if(!ifofile->vts_c_adt) 01572 return 0; 01573 01574 if(!ifoRead_C_ADT_internal(ifofile, ifofile->vts_c_adt, 01575 ifofile->vtsi_mat->vts_c_adt)) { 01576 free(ifofile->vts_c_adt); 01577 ifofile->vts_c_adt = 0; 01578 return 0; 01579 } 01580 01581 return 1; 01582 } 01583 01584 int ifoRead_C_ADT(ifo_handle_t *ifofile) { 01585 unsigned int sector; 01586 01587 if(!ifofile) 01588 return 0; 01589 01590 if(ifofile->vmgi_mat) { 01591 if(ifofile->vmgi_mat->vmgm_c_adt == 0) 01592 return 1; 01593 sector = ifofile->vmgi_mat->vmgm_c_adt; 01594 } else if(ifofile->vtsi_mat) { 01595 if(ifofile->vtsi_mat->vtsm_c_adt == 0) 01596 return 1; 01597 sector = ifofile->vtsi_mat->vtsm_c_adt; 01598 } else { 01599 return 0; 01600 } 01601 01602 ifofile->menu_c_adt = (c_adt_t *)malloc(sizeof(c_adt_t)); 01603 if(!ifofile->menu_c_adt) 01604 return 0; 01605 01606 if(!ifoRead_C_ADT_internal(ifofile, ifofile->menu_c_adt, sector)) { 01607 free(ifofile->menu_c_adt); 01608 ifofile->menu_c_adt = 0; 01609 return 0; 01610 } 01611 01612 return 1; 01613 } 01614 01615 static int ifoRead_C_ADT_internal(ifo_handle_t *ifofile, 01616 c_adt_t *c_adt, unsigned int sector) { 01617 int i, info_length; 01618 01619 if(!DVDFileSeek_(ifofile->file, sector * DVD_BLOCK_LEN)) 01620 return 0; 01621 01622 if(!(DVDReadBytes(ifofile->file, c_adt, C_ADT_SIZE))) 01623 return 0; 01624 01625 B2N_16(c_adt->nr_of_vobs); 01626 B2N_32(c_adt->last_byte); 01627 01628 info_length = c_adt->last_byte + 1 - C_ADT_SIZE; 01629 01630 CHECK_ZERO(c_adt->zero_1); 01631 /* assert(c_adt->nr_of_vobs > 0); 01632 Magic Knight Rayearth Daybreak is mastered very strange and has 01633 Titles with a VOBS that has no cells. */ 01634 CHECK_VALUE(info_length % sizeof(cell_adr_t) == 0); 01635 01636 /* assert(info_length / sizeof(cell_adr_t) >= c_adt->nr_of_vobs); 01637 Enemy of the State region 2 (de) has Titles where nr_of_vobs field 01638 is to high, they high ones are never referenced though. */ 01639 if(info_length / sizeof(cell_adr_t) < c_adt->nr_of_vobs) { 01640 fprintf(stderr, "libdvdread: *C_ADT nr_of_vobs > available info entries\n"); 01641 c_adt->nr_of_vobs = info_length / sizeof(cell_adr_t); 01642 } 01643 01644 c_adt->cell_adr_table = (cell_adr_t *)malloc(info_length); 01645 if(!c_adt->cell_adr_table) 01646 return 0; 01647 01648 if(info_length && 01649 !(DVDReadBytes(ifofile->file, c_adt->cell_adr_table, info_length))) { 01650 free(c_adt->cell_adr_table); 01651 return 0; 01652 } 01653 01654 for(i = 0; i < info_length/sizeof(cell_adr_t); i++) { 01655 B2N_16(c_adt->cell_adr_table[i].vob_id); 01656 B2N_32(c_adt->cell_adr_table[i].start_sector); 01657 B2N_32(c_adt->cell_adr_table[i].last_sector); 01658 01659 CHECK_ZERO(c_adt->cell_adr_table[i].zero_1); 01660 CHECK_VALUE(c_adt->cell_adr_table[i].vob_id > 0); 01661 CHECK_VALUE(c_adt->cell_adr_table[i].vob_id <= c_adt->nr_of_vobs); 01662 CHECK_VALUE(c_adt->cell_adr_table[i].cell_id > 0); 01663 CHECK_VALUE(c_adt->cell_adr_table[i].start_sector < 01664 c_adt->cell_adr_table[i].last_sector); 01665 } 01666 01667 return 1; 01668 } 01669 01670 01671 static void ifoFree_C_ADT_internal(c_adt_t *c_adt) { 01672 if(c_adt) { 01673 free(c_adt->cell_adr_table); 01674 free(c_adt); 01675 } 01676 } 01677 01678 void ifoFree_C_ADT(ifo_handle_t *ifofile) { 01679 if(!ifofile) 01680 return; 01681 01682 ifoFree_C_ADT_internal(ifofile->menu_c_adt); 01683 ifofile->menu_c_adt = 0; 01684 } 01685 01686 void ifoFree_TITLE_C_ADT(ifo_handle_t *ifofile) { 01687 if(!ifofile) 01688 return; 01689 01690 ifoFree_C_ADT_internal(ifofile->vts_c_adt); 01691 ifofile->vts_c_adt = 0; 01692 } 01693 01694 int ifoRead_TITLE_VOBU_ADMAP(ifo_handle_t *ifofile) { 01695 if(!ifofile) 01696 return 0; 01697 01698 if(!ifofile->vtsi_mat) 01699 return 0; 01700 01701 if(ifofile->vtsi_mat->vts_vobu_admap == 0) /* mandatory */ 01702 return 0; 01703 01704 ifofile->vts_vobu_admap = (vobu_admap_t *)malloc(sizeof(vobu_admap_t)); 01705 if(!ifofile->vts_vobu_admap) 01706 return 0; 01707 01708 if(!ifoRead_VOBU_ADMAP_internal(ifofile, ifofile->vts_vobu_admap, 01709 ifofile->vtsi_mat->vts_vobu_admap)) { 01710 free(ifofile->vts_vobu_admap); 01711 ifofile->vts_vobu_admap = 0; 01712 return 0; 01713 } 01714 01715 return 1; 01716 } 01717 01718 int ifoRead_VOBU_ADMAP(ifo_handle_t *ifofile) { 01719 unsigned int sector; 01720 01721 if(!ifofile) 01722 return 0; 01723 01724 if(ifofile->vmgi_mat) { 01725 if(ifofile->vmgi_mat->vmgm_vobu_admap == 0) 01726 return 1; 01727 sector = ifofile->vmgi_mat->vmgm_vobu_admap; 01728 } else if(ifofile->vtsi_mat) { 01729 if(ifofile->vtsi_mat->vtsm_vobu_admap == 0) 01730 return 1; 01731 sector = ifofile->vtsi_mat->vtsm_vobu_admap; 01732 } else { 01733 return 0; 01734 } 01735 01736 ifofile->menu_vobu_admap = (vobu_admap_t *)malloc(sizeof(vobu_admap_t)); 01737 if(!ifofile->menu_vobu_admap) 01738 return 0; 01739 01740 if(!ifoRead_VOBU_ADMAP_internal(ifofile, ifofile->menu_vobu_admap, sector)) { 01741 free(ifofile->menu_vobu_admap); 01742 ifofile->menu_vobu_admap = 0; 01743 return 0; 01744 } 01745 01746 return 1; 01747 } 01748 01749 static int ifoRead_VOBU_ADMAP_internal(ifo_handle_t *ifofile, 01750 vobu_admap_t *vobu_admap, 01751 unsigned int sector) { 01752 unsigned int i; 01753 int info_length; 01754 01755 if(!DVDFileSeekForce_(ifofile->file, sector * DVD_BLOCK_LEN, sector)) 01756 return 0; 01757 01758 if(!(DVDReadBytes(ifofile->file, vobu_admap, VOBU_ADMAP_SIZE))) 01759 return 0; 01760 01761 B2N_32(vobu_admap->last_byte); 01762 01763 info_length = vobu_admap->last_byte + 1 - VOBU_ADMAP_SIZE; 01764 /* assert(info_length > 0); 01765 Magic Knight Rayearth Daybreak is mastered very strange and has 01766 Titles with a VOBS that has no VOBUs. */ 01767 CHECK_VALUE(info_length % sizeof(uint32_t) == 0); 01768 01769 vobu_admap->vobu_start_sectors = (uint32_t *)malloc(info_length); 01770 if(!vobu_admap->vobu_start_sectors) { 01771 return 0; 01772 } 01773 if(info_length && 01774 !(DVDReadBytes(ifofile->file, 01775 vobu_admap->vobu_start_sectors, info_length))) { 01776 free(vobu_admap->vobu_start_sectors); 01777 return 0; 01778 } 01779 01780 for(i = 0; i < info_length/sizeof(uint32_t); i++) 01781 B2N_32(vobu_admap->vobu_start_sectors[i]); 01782 01783 return 1; 01784 } 01785 01786 01787 static void ifoFree_VOBU_ADMAP_internal(vobu_admap_t *vobu_admap) { 01788 if(vobu_admap) { 01789 free(vobu_admap->vobu_start_sectors); 01790 free(vobu_admap); 01791 } 01792 } 01793 01794 void ifoFree_VOBU_ADMAP(ifo_handle_t *ifofile) { 01795 if(!ifofile) 01796 return; 01797 01798 ifoFree_VOBU_ADMAP_internal(ifofile->menu_vobu_admap); 01799 ifofile->menu_vobu_admap = 0; 01800 } 01801 01802 void ifoFree_TITLE_VOBU_ADMAP(ifo_handle_t *ifofile) { 01803 if(!ifofile) 01804 return; 01805 01806 ifoFree_VOBU_ADMAP_internal(ifofile->vts_vobu_admap); 01807 ifofile->vts_vobu_admap = 0; 01808 } 01809 01810 int ifoRead_PGCIT(ifo_handle_t *ifofile) { 01811 01812 if(!ifofile) 01813 return 0; 01814 01815 if(!ifofile->vtsi_mat) 01816 return 0; 01817 01818 if(ifofile->vtsi_mat->vts_pgcit == 0) /* mandatory */ 01819 return 0; 01820 01821 ifofile->vts_pgcit = (pgcit_t *)malloc(sizeof(pgcit_t)); 01822 if(!ifofile->vts_pgcit) 01823 return 0; 01824 01825 if(!ifoRead_PGCIT_internal(ifofile, ifofile->vts_pgcit, 01826 ifofile->vtsi_mat->vts_pgcit * DVD_BLOCK_LEN)) { 01827 free(ifofile->vts_pgcit); 01828 ifofile->vts_pgcit = 0; 01829 return 0; 01830 } 01831 01832 return 1; 01833 } 01834 01835 static int ifoRead_PGCIT_internal(ifo_handle_t *ifofile, pgcit_t *pgcit, 01836 unsigned int offset) { 01837 int i, info_length; 01838 uint8_t *data, *ptr; 01839 01840 if(!DVDFileSeek_(ifofile->file, offset)) 01841 return 0; 01842 01843 if(!(DVDReadBytes(ifofile->file, pgcit, PGCIT_SIZE))) 01844 return 0; 01845 01846 B2N_16(pgcit->nr_of_pgci_srp); 01847 B2N_32(pgcit->last_byte); 01848 01849 CHECK_ZERO(pgcit->zero_1); 01850 /* assert(pgcit->nr_of_pgci_srp != 0); 01851 Magic Knight Rayearth Daybreak is mastered very strange and has 01852 Titles with 0 PTTs. */ 01853 CHECK_VALUE(pgcit->nr_of_pgci_srp < 10000); /* ?? seen max of 1338 */ 01854 01855 info_length = pgcit->nr_of_pgci_srp * PGCI_SRP_SIZE; 01856 data = malloc(info_length); 01857 if(!data) 01858 return 0; 01859 01860 if(info_length && !(DVDReadBytes(ifofile->file, data, info_length))) { 01861 free(data); 01862 return 0; 01863 } 01864 01865 pgcit->pgci_srp = malloc(pgcit->nr_of_pgci_srp * sizeof(pgci_srp_t)); 01866 if(!pgcit->pgci_srp) { 01867 free(data); 01868 return 0; 01869 } 01870 ptr = data; 01871 for(i = 0; i < pgcit->nr_of_pgci_srp; i++) { 01872 memcpy(&pgcit->pgci_srp[i], ptr, PGCI_SRP_SIZE); 01873 ptr += PGCI_SRP_SIZE; 01874 read_pgci_srp(&pgcit->pgci_srp[i]); 01875 CHECK_VALUE(pgcit->pgci_srp[i].unknown1 == 0); 01876 } 01877 free(data); 01878 01879 for(i = 0; i < pgcit->nr_of_pgci_srp; i++) 01880 CHECK_VALUE(pgcit->pgci_srp[i].pgc_start_byte + PGC_SIZE <= pgcit->last_byte+1); 01881 01882 for(i = 0; i < pgcit->nr_of_pgci_srp; i++) { 01883 pgcit->pgci_srp[i].pgc = malloc(sizeof(pgc_t)); 01884 if(!pgcit->pgci_srp[i].pgc) { 01885 int j; 01886 for(j = 0; j < i; j++) { 01887 ifoFree_PGC(pgcit->pgci_srp[j].pgc); 01888 free(pgcit->pgci_srp[j].pgc); 01889 } 01890 goto fail; 01891 } 01892 if(!ifoRead_PGC(ifofile, pgcit->pgci_srp[i].pgc, 01893 offset + pgcit->pgci_srp[i].pgc_start_byte)) { 01894 int j; 01895 for(j = 0; j < i; j++) { 01896 ifoFree_PGC(pgcit->pgci_srp[j].pgc); 01897 free(pgcit->pgci_srp[j].pgc); 01898 } 01899 free(pgcit->pgci_srp[i].pgc); 01900 goto fail; 01901 } 01902 } 01903 01904 return 1; 01905 fail: 01906 free(pgcit->pgci_srp); 01907 pgcit->pgci_srp = NULL; 01908 return 0; 01909 } 01910 01911 static void ifoFree_PGCIT_internal(pgcit_t *pgcit) { 01912 if(pgcit) { 01913 int i; 01914 for(i = 0; i < pgcit->nr_of_pgci_srp; i++) 01915 { 01916 ifoFree_PGC(pgcit->pgci_srp[i].pgc); 01917 free(pgcit->pgci_srp[i].pgc); 01918 } 01919 free(pgcit->pgci_srp); 01920 } 01921 } 01922 01923 void ifoFree_PGCIT(ifo_handle_t *ifofile) { 01924 if(!ifofile) 01925 return; 01926 01927 if(ifofile->vts_pgcit) { 01928 ifoFree_PGCIT_internal(ifofile->vts_pgcit); 01929 free(ifofile->vts_pgcit); 01930 ifofile->vts_pgcit = 0; 01931 } 01932 } 01933 01934 01935 int ifoRead_PGCI_UT(ifo_handle_t *ifofile) { 01936 pgci_ut_t *pgci_ut; 01937 unsigned int sector; 01938 unsigned int i; 01939 int info_length; 01940 uint8_t *data, *ptr; 01941 01942 if(!ifofile) 01943 return 0; 01944 01945 if(ifofile->vmgi_mat) { 01946 if(ifofile->vmgi_mat->vmgm_pgci_ut == 0) 01947 return 1; 01948 sector = ifofile->vmgi_mat->vmgm_pgci_ut; 01949 } else if(ifofile->vtsi_mat) { 01950 if(ifofile->vtsi_mat->vtsm_pgci_ut == 0) 01951 return 1; 01952 sector = ifofile->vtsi_mat->vtsm_pgci_ut; 01953 } else { 01954 return 0; 01955 } 01956 01957 ifofile->pgci_ut = (pgci_ut_t *)malloc(sizeof(pgci_ut_t)); 01958 if(!ifofile->pgci_ut) 01959 return 0; 01960 01961 if(!DVDFileSeek_(ifofile->file, sector * DVD_BLOCK_LEN)) { 01962 free(ifofile->pgci_ut); 01963 ifofile->pgci_ut = 0; 01964 return 0; 01965 } 01966 01967 if(!(DVDReadBytes(ifofile->file, ifofile->pgci_ut, PGCI_UT_SIZE))) { 01968 free(ifofile->pgci_ut); 01969 ifofile->pgci_ut = 0; 01970 return 0; 01971 } 01972 01973 pgci_ut = ifofile->pgci_ut; 01974 01975 B2N_16(pgci_ut->nr_of_lus); 01976 B2N_32(pgci_ut->last_byte); 01977 01978 CHECK_ZERO(pgci_ut->zero_1); 01979 CHECK_VALUE(pgci_ut->nr_of_lus != 0); 01980 CHECK_VALUE(pgci_ut->nr_of_lus < 100); /* ?? 3-4 ? */ 01981 CHECK_VALUE((uint32_t)pgci_ut->nr_of_lus * PGCI_LU_SIZE < pgci_ut->last_byte); 01982 01983 info_length = pgci_ut->nr_of_lus * PGCI_LU_SIZE; 01984 data = malloc(info_length); 01985 if(!data) { 01986 free(pgci_ut); 01987 ifofile->pgci_ut = 0; 01988 return 0; 01989 } 01990 if(!(DVDReadBytes(ifofile->file, data, info_length))) { 01991 free(data); 01992 free(pgci_ut); 01993 ifofile->pgci_ut = 0; 01994 return 0; 01995 } 01996 01997 pgci_ut->lu = malloc(pgci_ut->nr_of_lus * sizeof(pgci_lu_t)); 01998 if(!pgci_ut->lu) { 01999 free(data); 02000 free(pgci_ut); 02001 ifofile->pgci_ut = 0; 02002 return 0; 02003 } 02004 ptr = data; 02005 for(i = 0; i < pgci_ut->nr_of_lus; i++) { 02006 memcpy(&pgci_ut->lu[i], ptr, PGCI_LU_SIZE); 02007 ptr += PGCI_LU_SIZE; 02008 B2N_16(pgci_ut->lu[i].lang_code); 02009 B2N_32(pgci_ut->lu[i].lang_start_byte); 02010 } 02011 free(data); 02012 02013 for(i = 0; i < pgci_ut->nr_of_lus; i++) { 02014 /* Maybe this is only defined for v1.1 and later titles? */ 02015 /* If the bits in 'lu[i].exists' are enumerated abcd efgh then: 02016 VTS_x_yy.IFO VIDEO_TS.IFO 02017 a == 0x83 "Root" 0x82 "Title" 02018 b == 0x84 "Subpicture" 02019 c == 0x85 "Audio" 02020 d == 0x86 "Angle" 02021 e == 0x87 "PTT" 02022 */ 02023 CHECK_VALUE((pgci_ut->lu[i].exists & 0x07) == 0); 02024 } 02025 02026 for(i = 0; i < pgci_ut->nr_of_lus; i++) { 02027 pgci_ut->lu[i].pgcit = malloc(sizeof(pgcit_t)); 02028 if(!pgci_ut->lu[i].pgcit) { 02029 unsigned int j; 02030 for(j = 0; j < i; j++) { 02031 ifoFree_PGCIT_internal(pgci_ut->lu[j].pgcit); 02032 free(pgci_ut->lu[j].pgcit); 02033 } 02034 free(pgci_ut->lu); 02035 free(pgci_ut); 02036 ifofile->pgci_ut = 0; 02037 return 0; 02038 } 02039 if(!ifoRead_PGCIT_internal(ifofile, pgci_ut->lu[i].pgcit, 02040 sector * DVD_BLOCK_LEN 02041 + pgci_ut->lu[i].lang_start_byte)) { 02042 unsigned int j; 02043 for(j = 0; j < i; j++) { 02044 ifoFree_PGCIT_internal(pgci_ut->lu[j].pgcit); 02045 free(pgci_ut->lu[j].pgcit); 02046 } 02047 free(pgci_ut->lu[i].pgcit); 02048 free(pgci_ut->lu); 02049 free(pgci_ut); 02050 ifofile->pgci_ut = 0; 02051 return 0; 02052 } 02053 /* FIXME: Iterate and verify that all menus that should exists accordingly 02054 * to pgci_ut->lu[i].exists really do? */ 02055 } 02056 02057 return 1; 02058 } 02059 02060 02061 void ifoFree_PGCI_UT(ifo_handle_t *ifofile) { 02062 unsigned int i; 02063 02064 if(!ifofile) 02065 return; 02066 02067 if(ifofile->pgci_ut) { 02068 for(i = 0; i < ifofile->pgci_ut->nr_of_lus; i++) { 02069 ifoFree_PGCIT_internal(ifofile->pgci_ut->lu[i].pgcit); 02070 free(ifofile->pgci_ut->lu[i].pgcit); 02071 } 02072 free(ifofile->pgci_ut->lu); 02073 free(ifofile->pgci_ut); 02074 ifofile->pgci_ut = 0; 02075 } 02076 } 02077 02078 static int ifoRead_VTS_ATTRIBUTES(ifo_handle_t *ifofile, 02079 vts_attributes_t *vts_attributes, 02080 unsigned int offset) { 02081 unsigned int i; 02082 02083 if(!DVDFileSeek_(ifofile->file, offset)) 02084 return 0; 02085 02086 if(!(DVDReadBytes(ifofile->file, vts_attributes, sizeof(vts_attributes_t)))) 02087 return 0; 02088 02089 read_video_attr(&vts_attributes->vtsm_vobs_attr); 02090 read_video_attr(&vts_attributes->vtstt_vobs_video_attr); 02091 read_audio_attr(&vts_attributes->vtsm_audio_attr); 02092 for(i=0; i<8; i++) 02093 read_audio_attr(&vts_attributes->vtstt_audio_attr[i]); 02094 read_subp_attr(&vts_attributes->vtsm_subp_attr); 02095 for(i=0; i<32; i++) 02096 read_subp_attr(&vts_attributes->vtstt_subp_attr[i]); 02097 B2N_32(vts_attributes->last_byte); 02098 B2N_32(vts_attributes->vts_cat); 02099 02100 CHECK_ZERO(vts_attributes->zero_1); 02101 CHECK_ZERO(vts_attributes->zero_2); 02102 CHECK_ZERO(vts_attributes->zero_3); 02103 CHECK_ZERO(vts_attributes->zero_4); 02104 CHECK_ZERO(vts_attributes->zero_5); 02105 CHECK_ZERO(vts_attributes->zero_6); 02106 CHECK_ZERO(vts_attributes->zero_7); 02107 CHECK_VALUE(vts_attributes->nr_of_vtsm_audio_streams <= 1); 02108 CHECK_VALUE(vts_attributes->nr_of_vtsm_subp_streams <= 1); 02109 CHECK_VALUE(vts_attributes->nr_of_vtstt_audio_streams <= 8); 02110 for(i = vts_attributes->nr_of_vtstt_audio_streams; i < 8; i++) 02111 CHECK_ZERO(vts_attributes->vtstt_audio_attr[i]); 02112 CHECK_VALUE(vts_attributes->nr_of_vtstt_subp_streams <= 32); 02113 { 02114 unsigned int nr_coded; 02115 CHECK_VALUE(vts_attributes->last_byte + 1 >= VTS_ATTRIBUTES_MIN_SIZE); 02116 nr_coded = (vts_attributes->last_byte + 1 - VTS_ATTRIBUTES_MIN_SIZE)/6; 02117 /* This is often nr_coded = 70, how do you know how many there really are? */ 02118 if(nr_coded > 32) { /* We haven't read more from disk/file anyway */ 02119 nr_coded = 32; 02120 } 02121 CHECK_VALUE(vts_attributes->nr_of_vtstt_subp_streams <= nr_coded); 02122 for(i = vts_attributes->nr_of_vtstt_subp_streams; i < nr_coded; i++) 02123 CHECK_ZERO(vts_attributes->vtstt_subp_attr[i]); 02124 } 02125 02126 return 1; 02127 } 02128 02129 02130 02131 int ifoRead_VTS_ATRT(ifo_handle_t *ifofile) { 02132 vts_atrt_t *vts_atrt; 02133 unsigned int i, info_length, sector; 02134 uint32_t *data; 02135 02136 if(!ifofile) 02137 return 0; 02138 02139 if(!ifofile->vmgi_mat) 02140 return 0; 02141 02142 if(ifofile->vmgi_mat->vts_atrt == 0) /* mandatory */ 02143 return 0; 02144 02145 sector = ifofile->vmgi_mat->vts_atrt; 02146 if(!DVDFileSeek_(ifofile->file, sector * DVD_BLOCK_LEN)) 02147 return 0; 02148 02149 vts_atrt = (vts_atrt_t *)malloc(sizeof(vts_atrt_t)); 02150 if(!vts_atrt) 02151 return 0; 02152 02153 ifofile->vts_atrt = vts_atrt; 02154 02155 if(!(DVDReadBytes(ifofile->file, vts_atrt, VTS_ATRT_SIZE))) { 02156 free(vts_atrt); 02157 ifofile->vts_atrt = 0; 02158 return 0; 02159 } 02160 02161 B2N_16(vts_atrt->nr_of_vtss); 02162 B2N_32(vts_atrt->last_byte); 02163 02164 CHECK_ZERO(vts_atrt->zero_1); 02165 CHECK_VALUE(vts_atrt->nr_of_vtss != 0); 02166 CHECK_VALUE(vts_atrt->nr_of_vtss < 100); /* ?? */ 02167 CHECK_VALUE((uint32_t)vts_atrt->nr_of_vtss * (4 + VTS_ATTRIBUTES_MIN_SIZE) + 02168 VTS_ATRT_SIZE < vts_atrt->last_byte + 1); 02169 02170 info_length = vts_atrt->nr_of_vtss * sizeof(uint32_t); 02171 data = (uint32_t *)malloc(info_length); 02172 if(!data) { 02173 free(vts_atrt); 02174 ifofile->vts_atrt = 0; 02175 return 0; 02176 } 02177 02178 vts_atrt->vts_atrt_offsets = data; 02179 02180 if(!(DVDReadBytes(ifofile->file, data, info_length))) { 02181 free(data); 02182 free(vts_atrt); 02183 ifofile->vts_atrt = 0; 02184 return 0; 02185 } 02186 02187 for(i = 0; i < vts_atrt->nr_of_vtss; i++) { 02188 B2N_32(data[i]); 02189 CHECK_VALUE(data[i] + VTS_ATTRIBUTES_MIN_SIZE < vts_atrt->last_byte + 1); 02190 } 02191 02192 info_length = vts_atrt->nr_of_vtss * sizeof(vts_attributes_t); 02193 vts_atrt->vts = (vts_attributes_t *)malloc(info_length); 02194 if(!vts_atrt->vts) { 02195 free(data); 02196 free(vts_atrt); 02197 ifofile->vts_atrt = 0; 02198 return 0; 02199 } 02200 for(i = 0; i < vts_atrt->nr_of_vtss; i++) { 02201 unsigned int offset = data[i]; 02202 if(!ifoRead_VTS_ATTRIBUTES(ifofile, &(vts_atrt->vts[i]), 02203 (sector * DVD_BLOCK_LEN) + offset)) { 02204 free(data); 02205 free(vts_atrt); 02206 ifofile->vts_atrt = 0; 02207 return 0; 02208 } 02209 02210 /* This assert cant be in ifoRead_VTS_ATTRIBUTES */ 02211 CHECK_VALUE(offset + vts_atrt->vts[i].last_byte <= vts_atrt->last_byte + 1); 02212 /* Is this check correct? */ 02213 } 02214 02215 return 1; 02216 } 02217 02218 02219 void ifoFree_VTS_ATRT(ifo_handle_t *ifofile) { 02220 if(!ifofile) 02221 return; 02222 02223 if(ifofile->vts_atrt) { 02224 free(ifofile->vts_atrt->vts); 02225 free(ifofile->vts_atrt->vts_atrt_offsets); 02226 free(ifofile->vts_atrt); 02227 ifofile->vts_atrt = 0; 02228 } 02229 } 02230 02231 02232 int ifoRead_TXTDT_MGI(ifo_handle_t *ifofile) { 02233 txtdt_mgi_t *txtdt_mgi; 02234 02235 if(!ifofile) 02236 return 0; 02237 02238 if(!ifofile->vmgi_mat) 02239 return 0; 02240 02241 /* Return successfully if there is nothing to read. */ 02242 if(ifofile->vmgi_mat->txtdt_mgi == 0) 02243 return 1; 02244 02245 if(!DVDFileSeek_(ifofile->file, 02246 ifofile->vmgi_mat->txtdt_mgi * DVD_BLOCK_LEN)) 02247 return 0; 02248 02249 txtdt_mgi = (txtdt_mgi_t *)malloc(sizeof(txtdt_mgi_t)); 02250 if(!txtdt_mgi) { 02251 return 0; 02252 } 02253 ifofile->txtdt_mgi = txtdt_mgi; 02254 02255 if(!(DVDReadBytes(ifofile->file, txtdt_mgi, TXTDT_MGI_SIZE))) { 02256 fprintf(stderr, "libdvdread: Unable to read TXTDT_MGI.\n"); 02257 free(txtdt_mgi); 02258 ifofile->txtdt_mgi = 0; 02259 return 0; 02260 } 02261 02262 /* fprintf(stderr, "-- Not done yet --\n"); */ 02263 return 1; 02264 } 02265 02266 void ifoFree_TXTDT_MGI(ifo_handle_t *ifofile) { 02267 if(!ifofile) 02268 return; 02269 02270 if(ifofile->txtdt_mgi) { 02271 free(ifofile->txtdt_mgi); 02272 ifofile->txtdt_mgi = 0; 02273 } 02274 }
1.7.6.1