00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019
00020
00021 #include "config.h"
00022
00023 #include <stdio.h>
00024 #include <stdlib.h>
00025 #include <inttypes.h>
00026 #include <string.h>
00027
00028 #include "bswap.h"
00029 #include "ifo_types.h"
00030 #include "ifo_read.h"
00031 #include "dvd_reader.h"
00032 #include "dvdread_internal.h"
00033
00034 #ifndef DVD_BLOCK_LEN
00035 #define DVD_BLOCK_LEN 2048
00036 #endif
00037
00038 #ifndef NDEBUG
00039 #define CHECK_ZERO0(arg) \
00040 if(arg != 0) { \
00041 fprintf(stderr, "*** Zero check failed in %s:%i\n for %s = 0x%x\n", \
00042 __FILE__, __LINE__, # arg, arg); \
00043 }
00044 #define CHECK_ZERO(arg) \
00045 if(memcmp(my_friendly_zeros, &arg, sizeof(arg))) { \
00046 unsigned int i_CZ; \
00047 fprintf(stderr, "*** Zero check failed in %s:%i\n for %s = 0x", \
00048 __FILE__, __LINE__, # arg ); \
00049 for(i_CZ = 0; i_CZ < sizeof(arg); i_CZ++) \
00050 fprintf(stderr, "%02x", *((uint8_t *)&arg + i_CZ)); \
00051 fprintf(stderr, "\n"); \
00052 }
00053 static const uint8_t my_friendly_zeros[2048];
00054 #else
00055 #define CHECK_ZERO0(arg) (void)(arg)
00056 #define CHECK_ZERO(arg) (void)(arg)
00057 #endif
00058
00059
00060
00061 static int ifoRead_VMG(ifo_handle_t *ifofile);
00062 static int ifoRead_VTS(ifo_handle_t *ifofile);
00063 static int ifoRead_PGC(ifo_handle_t *ifofile, pgc_t *pgc, unsigned int offset);
00064 static int ifoRead_PGC_COMMAND_TBL(ifo_handle_t *ifofile,
00065 pgc_command_tbl_t *cmd_tbl,
00066 unsigned int offset);
00067 static int ifoRead_PGC_PROGRAM_MAP(ifo_handle_t *ifofile,
00068 pgc_program_map_t *program_map,
00069 unsigned int nr, unsigned int offset);
00070 static int ifoRead_CELL_PLAYBACK_TBL(ifo_handle_t *ifofile,
00071 cell_playback_t *cell_playback,
00072 unsigned int nr, unsigned int offset);
00073 static int ifoRead_CELL_POSITION_TBL(ifo_handle_t *ifofile,
00074 cell_position_t *cell_position,
00075 unsigned int nr, unsigned int offset);
00076 static int ifoRead_VTS_ATTRIBUTES(ifo_handle_t *ifofile,
00077 vts_attributes_t *vts_attributes,
00078 unsigned int offset);
00079 static int ifoRead_C_ADT_internal(ifo_handle_t *ifofile, c_adt_t *c_adt,
00080 unsigned int sector);
00081 static int ifoRead_VOBU_ADMAP_internal(ifo_handle_t *ifofile,
00082 vobu_admap_t *vobu_admap,
00083 unsigned int sector);
00084 static int ifoRead_PGCIT_internal(ifo_handle_t *ifofile, pgcit_t *pgcit,
00085 unsigned int offset);
00086
00087 static void ifoFree_PGC(pgc_t *pgc);
00088 static void ifoFree_PGC_COMMAND_TBL(pgc_command_tbl_t *cmd_tbl);
00089 static void ifoFree_PGCIT_internal(pgcit_t *pgcit);
00090
00091
00092 static inline int DVDFileSeek_( dvd_file_t *dvd_file, uint32_t offset ) {
00093 return (DVDFileSeek(dvd_file, (int)offset) == (int)offset);
00094 }
00095
00096
00097 ifo_handle_t *ifoOpen(dvd_reader_t *dvd, int title) {
00098 ifo_handle_t *ifofile;
00099
00100 ifofile = (ifo_handle_t *)malloc(sizeof(ifo_handle_t));
00101 if(!ifofile)
00102 return 0;
00103
00104 memset(ifofile, 0, sizeof(ifo_handle_t));
00105
00106 ifofile->file = DVDOpenFile(dvd, title, DVD_READ_INFO_FILE);
00107 if(!ifofile->file)
00108 ifofile->file = DVDOpenFile(dvd, title, DVD_READ_INFO_BACKUP_FILE);
00109 if(!ifofile->file) {
00110 if(title) {
00111 fprintf(stderr, "libdvdread: Can't open file VTS_%02d_0.IFO.\n", title);
00112 } else {
00113 fprintf(stderr, "libdvdread: Can't open file VIDEO_TS.IFO.\n");
00114 }
00115 free(ifofile);
00116 return 0;
00117 }
00118
00119
00120 if(ifoRead_VMG(ifofile)) {
00121
00122
00123 if(!ifoRead_FP_PGC(ifofile) || !ifoRead_TT_SRPT(ifofile)) {
00124 fprintf(stderr, "libdvdread: Invalid main menu IFO (VIDEO_TS.IFO).\n");
00125 ifoClose(ifofile);
00126 return 0;
00127 }
00128
00129 ifoRead_PGCI_UT(ifofile);
00130 ifoRead_PTL_MAIT(ifofile);
00131
00132
00133 if(!ifoRead_VTS_ATRT(ifofile)) {
00134 fprintf(stderr, "libdvdread: Invalid main menu IFO (VIDEO_TS.IFO).\n");
00135 ifoClose(ifofile);
00136 return 0;
00137 }
00138
00139 ifoRead_TXTDT_MGI(ifofile);
00140 ifoRead_C_ADT(ifofile);
00141 ifoRead_VOBU_ADMAP(ifofile);
00142
00143 return ifofile;
00144 }
00145
00146 if(ifoRead_VTS(ifofile)) {
00147
00148 if(!ifoRead_VTS_PTT_SRPT(ifofile) || !ifoRead_PGCIT(ifofile)) {
00149 fprintf(stderr, "libdvdread: Invalid title IFO (VTS_%02d_0.IFO).\n",
00150 title);
00151 ifoClose(ifofile);
00152 return 0;
00153 }
00154
00155
00156 ifoRead_PGCI_UT(ifofile);
00157 ifoRead_VTS_TMAPT(ifofile);
00158 ifoRead_C_ADT(ifofile);
00159 ifoRead_VOBU_ADMAP(ifofile);
00160
00161 if(!ifoRead_TITLE_C_ADT(ifofile) || !ifoRead_TITLE_VOBU_ADMAP(ifofile)) {
00162 fprintf(stderr, "libdvdread: Invalid title IFO (VTS_%02d_0.IFO).\n",
00163 title);
00164 ifoClose(ifofile);
00165 return 0;
00166 }
00167
00168 return ifofile;
00169 }
00170
00171 if(title) {
00172 fprintf(stderr, "libdvdread: Invalid IFO for title %d (VTS_%02d_0.IFO).\n",
00173 title, title);
00174 } else {
00175 fprintf(stderr, "libdvdread: Invalid IFO for VMGM (VIDEO_TS.IFO).\n");
00176 }
00177 ifoClose(ifofile);
00178 return 0;
00179 }
00180
00181
00182 ifo_handle_t *ifoOpenVMGI(dvd_reader_t *dvd) {
00183 ifo_handle_t *ifofile;
00184
00185 ifofile = (ifo_handle_t *)malloc(sizeof(ifo_handle_t));
00186 if(!ifofile)
00187 return 0;
00188
00189 memset(ifofile, 0, sizeof(ifo_handle_t));
00190
00191 ifofile->file = DVDOpenFile(dvd, 0, DVD_READ_INFO_FILE);
00192 if(!ifofile->file)
00193 ifofile->file = DVDOpenFile(dvd, 0, DVD_READ_INFO_BACKUP_FILE);
00194 if(!ifofile->file) {
00195 fprintf(stderr, "libdvdread: Can't open file VIDEO_TS.IFO.\n");
00196 free(ifofile);
00197 return 0;
00198 }
00199
00200 if(ifoRead_VMG(ifofile))
00201 return ifofile;
00202
00203 fprintf(stderr, "libdvdread: Invalid main menu IFO (VIDEO_TS.IFO).\n");
00204 ifoClose(ifofile);
00205 return 0;
00206 }
00207
00208
00209 ifo_handle_t *ifoOpenVTSI(dvd_reader_t *dvd, int title) {
00210 ifo_handle_t *ifofile;
00211
00212 ifofile = (ifo_handle_t *)malloc(sizeof(ifo_handle_t));
00213 if(!ifofile)
00214 return 0;
00215
00216 memset(ifofile, 0, sizeof(ifo_handle_t));
00217
00218 if(title <= 0 || title > 99) {
00219 fprintf(stderr, "libdvdread: ifoOpenVTSI invalid title (%d).\n", title);
00220 free(ifofile);
00221 return 0;
00222 }
00223
00224 ifofile->file = DVDOpenFile(dvd, title, DVD_READ_INFO_FILE);
00225 if(!ifofile->file)
00226 ifofile->file = DVDOpenFile(dvd, title, DVD_READ_INFO_BACKUP_FILE);
00227 if(!ifofile->file) {
00228 fprintf(stderr, "libdvdread: Can't open file VTS_%02d_0.IFO.\n", title);
00229 free(ifofile);
00230 return 0;
00231 }
00232
00233 ifoRead_VTS(ifofile);
00234 if(ifofile->vtsi_mat)
00235 return ifofile;
00236
00237 fprintf(stderr, "libdvdread: Invalid IFO for title %d (VTS_%02d_0.IFO).\n",
00238 title, title);
00239 ifoClose(ifofile);
00240 return 0;
00241 }
00242
00243
00244 void ifoClose(ifo_handle_t *ifofile) {
00245 if(!ifofile)
00246 return;
00247
00248 ifoFree_VOBU_ADMAP(ifofile);
00249 ifoFree_TITLE_VOBU_ADMAP(ifofile);
00250 ifoFree_C_ADT(ifofile);
00251 ifoFree_TITLE_C_ADT(ifofile);
00252 ifoFree_TXTDT_MGI(ifofile);
00253 ifoFree_VTS_ATRT(ifofile);
00254 ifoFree_PTL_MAIT(ifofile);
00255 ifoFree_PGCI_UT(ifofile);
00256 ifoFree_TT_SRPT(ifofile);
00257 ifoFree_FP_PGC(ifofile);
00258 ifoFree_PGCIT(ifofile);
00259 ifoFree_VTS_PTT_SRPT(ifofile);
00260
00261 if(ifofile->vmgi_mat)
00262 free(ifofile->vmgi_mat);
00263
00264 if(ifofile->vtsi_mat)
00265 free(ifofile->vtsi_mat);
00266
00267 DVDCloseFile(ifofile->file);
00268 ifofile->file = 0;
00269 free(ifofile);
00270 ifofile = 0;
00271 }
00272
00273
00274 static int ifoRead_VMG(ifo_handle_t *ifofile) {
00275 vmgi_mat_t *vmgi_mat;
00276
00277 vmgi_mat = (vmgi_mat_t *)malloc(sizeof(vmgi_mat_t));
00278 if(!vmgi_mat)
00279 return 0;
00280
00281 ifofile->vmgi_mat = vmgi_mat;
00282
00283 if(!DVDFileSeek_(ifofile->file, 0)) {
00284 free(ifofile->vmgi_mat);
00285 ifofile->vmgi_mat = 0;
00286 return 0;
00287 }
00288
00289 if(!DVDReadBytes(ifofile->file, vmgi_mat, sizeof(vmgi_mat_t))) {
00290 free(ifofile->vmgi_mat);
00291 ifofile->vmgi_mat = 0;
00292 return 0;
00293 }
00294
00295 if(strncmp("DVDVIDEO-VMG", vmgi_mat->vmg_identifier, 12) != 0) {
00296 free(ifofile->vmgi_mat);
00297 ifofile->vmgi_mat = 0;
00298 return 0;
00299 }
00300
00301 B2N_32(vmgi_mat->vmg_last_sector);
00302 B2N_32(vmgi_mat->vmgi_last_sector);
00303 B2N_32(vmgi_mat->vmg_category);
00304 B2N_16(vmgi_mat->vmg_nr_of_volumes);
00305 B2N_16(vmgi_mat->vmg_this_volume_nr);
00306 B2N_16(vmgi_mat->vmg_nr_of_title_sets);
00307 B2N_64(vmgi_mat->vmg_pos_code);
00308 B2N_32(vmgi_mat->vmgi_last_byte);
00309 B2N_32(vmgi_mat->first_play_pgc);
00310 B2N_32(vmgi_mat->vmgm_vobs);
00311 B2N_32(vmgi_mat->tt_srpt);
00312 B2N_32(vmgi_mat->vmgm_pgci_ut);
00313 B2N_32(vmgi_mat->ptl_mait);
00314 B2N_32(vmgi_mat->vts_atrt);
00315 B2N_32(vmgi_mat->txtdt_mgi);
00316 B2N_32(vmgi_mat->vmgm_c_adt);
00317 B2N_32(vmgi_mat->vmgm_vobu_admap);
00318 B2N_16(vmgi_mat->vmgm_audio_attr.lang_code);
00319 B2N_16(vmgi_mat->vmgm_subp_attr.lang_code);
00320
00321
00322 CHECK_ZERO(vmgi_mat->zero_1);
00323 CHECK_ZERO(vmgi_mat->zero_2);
00324 CHECK_ZERO(vmgi_mat->zero_3);
00325 CHECK_ZERO(vmgi_mat->zero_4);
00326 CHECK_ZERO(vmgi_mat->zero_5);
00327 CHECK_ZERO(vmgi_mat->zero_6);
00328 CHECK_ZERO(vmgi_mat->zero_7);
00329 CHECK_ZERO(vmgi_mat->zero_8);
00330 CHECK_ZERO(vmgi_mat->zero_9);
00331 CHECK_ZERO(vmgi_mat->zero_10);
00332 CHECK_VALUE(vmgi_mat->vmg_last_sector != 0);
00333 CHECK_VALUE(vmgi_mat->vmgi_last_sector != 0);
00334 CHECK_VALUE(vmgi_mat->vmgi_last_sector * 2 <= vmgi_mat->vmg_last_sector);
00335 CHECK_VALUE(vmgi_mat->vmgi_last_sector * 2 <= vmgi_mat->vmg_last_sector);
00336 CHECK_VALUE(vmgi_mat->vmg_nr_of_volumes != 0);
00337 CHECK_VALUE(vmgi_mat->vmg_this_volume_nr != 0);
00338 CHECK_VALUE(vmgi_mat->vmg_this_volume_nr <= vmgi_mat->vmg_nr_of_volumes);
00339 CHECK_VALUE(vmgi_mat->disc_side == 1 || vmgi_mat->disc_side == 2);
00340 CHECK_VALUE(vmgi_mat->vmg_nr_of_title_sets != 0);
00341 CHECK_VALUE(vmgi_mat->vmgi_last_byte >= 341);
00342 CHECK_VALUE(vmgi_mat->vmgi_last_byte / DVD_BLOCK_LEN <=
00343 vmgi_mat->vmgi_last_sector);
00344
00345 CHECK_VALUE(vmgi_mat->first_play_pgc < vmgi_mat->vmgi_last_byte);
00346 CHECK_VALUE(vmgi_mat->vmgm_vobs == 0 ||
00347 (vmgi_mat->vmgm_vobs > vmgi_mat->vmgi_last_sector &&
00348 vmgi_mat->vmgm_vobs < vmgi_mat->vmg_last_sector));
00349 CHECK_VALUE(vmgi_mat->tt_srpt <= vmgi_mat->vmgi_last_sector);
00350 CHECK_VALUE(vmgi_mat->vmgm_pgci_ut <= vmgi_mat->vmgi_last_sector);
00351 CHECK_VALUE(vmgi_mat->ptl_mait <= vmgi_mat->vmgi_last_sector);
00352 CHECK_VALUE(vmgi_mat->vts_atrt <= vmgi_mat->vmgi_last_sector);
00353 CHECK_VALUE(vmgi_mat->txtdt_mgi <= vmgi_mat->vmgi_last_sector);
00354 CHECK_VALUE(vmgi_mat->vmgm_c_adt <= vmgi_mat->vmgi_last_sector);
00355 CHECK_VALUE(vmgi_mat->vmgm_vobu_admap <= vmgi_mat->vmgi_last_sector);
00356
00357 CHECK_VALUE(vmgi_mat->nr_of_vmgm_audio_streams <= 1);
00358 CHECK_VALUE(vmgi_mat->nr_of_vmgm_subp_streams <= 1);
00359
00360 return 1;
00361 }
00362
00363
00364 static int ifoRead_VTS(ifo_handle_t *ifofile) {
00365 vtsi_mat_t *vtsi_mat;
00366 int i;
00367
00368 vtsi_mat = (vtsi_mat_t *)malloc(sizeof(vtsi_mat_t));
00369 if(!vtsi_mat)
00370 return 0;
00371
00372 ifofile->vtsi_mat = vtsi_mat;
00373
00374 if(!DVDFileSeek_(ifofile->file, 0)) {
00375 free(ifofile->vtsi_mat);
00376 ifofile->vtsi_mat = 0;
00377 return 0;
00378 }
00379
00380 if(!(DVDReadBytes(ifofile->file, vtsi_mat, sizeof(vtsi_mat_t)))) {
00381 free(ifofile->vtsi_mat);
00382 ifofile->vtsi_mat = 0;
00383 return 0;
00384 }
00385
00386 if(strncmp("DVDVIDEO-VTS", vtsi_mat->vts_identifier, 12) != 0) {
00387 free(ifofile->vtsi_mat);
00388 ifofile->vtsi_mat = 0;
00389 return 0;
00390 }
00391
00392 B2N_32(vtsi_mat->vts_last_sector);
00393 B2N_32(vtsi_mat->vtsi_last_sector);
00394 B2N_32(vtsi_mat->vts_category);
00395 B2N_32(vtsi_mat->vtsi_last_byte);
00396 B2N_32(vtsi_mat->vtsm_vobs);
00397 B2N_32(vtsi_mat->vtstt_vobs);
00398 B2N_32(vtsi_mat->vts_ptt_srpt);
00399 B2N_32(vtsi_mat->vts_pgcit);
00400 B2N_32(vtsi_mat->vtsm_pgci_ut);
00401 B2N_32(vtsi_mat->vts_tmapt);
00402 B2N_32(vtsi_mat->vtsm_c_adt);
00403 B2N_32(vtsi_mat->vtsm_vobu_admap);
00404 B2N_32(vtsi_mat->vts_c_adt);
00405 B2N_32(vtsi_mat->vts_vobu_admap);
00406 B2N_16(vtsi_mat->vtsm_audio_attr.lang_code);
00407 B2N_16(vtsi_mat->vtsm_subp_attr.lang_code);
00408 for(i = 0; i < 8; i++)
00409 B2N_16(vtsi_mat->vts_audio_attr[i].lang_code);
00410 for(i = 0; i < 32; i++)
00411 B2N_16(vtsi_mat->vts_subp_attr[i].lang_code);
00412
00413
00414 CHECK_ZERO(vtsi_mat->zero_1);
00415 CHECK_ZERO(vtsi_mat->zero_2);
00416 CHECK_ZERO(vtsi_mat->zero_3);
00417 CHECK_ZERO(vtsi_mat->zero_4);
00418 CHECK_ZERO(vtsi_mat->zero_5);
00419 CHECK_ZERO(vtsi_mat->zero_6);
00420 CHECK_ZERO(vtsi_mat->zero_7);
00421 CHECK_ZERO(vtsi_mat->zero_8);
00422 CHECK_ZERO(vtsi_mat->zero_9);
00423 CHECK_ZERO(vtsi_mat->zero_10);
00424 CHECK_ZERO(vtsi_mat->zero_11);
00425 CHECK_ZERO(vtsi_mat->zero_12);
00426 CHECK_ZERO(vtsi_mat->zero_13);
00427 CHECK_ZERO(vtsi_mat->zero_14);
00428 CHECK_ZERO(vtsi_mat->zero_15);
00429 CHECK_ZERO(vtsi_mat->zero_16);
00430 CHECK_ZERO(vtsi_mat->zero_17);
00431 CHECK_ZERO(vtsi_mat->zero_18);
00432 CHECK_ZERO(vtsi_mat->zero_19);
00433 CHECK_ZERO(vtsi_mat->zero_20);
00434 CHECK_ZERO(vtsi_mat->zero_21);
00435 CHECK_VALUE(vtsi_mat->vtsi_last_sector*2 <= vtsi_mat->vts_last_sector);
00436 CHECK_VALUE(vtsi_mat->vtsi_last_byte/DVD_BLOCK_LEN <= vtsi_mat->vtsi_last_sector);
00437 CHECK_VALUE(vtsi_mat->vtsm_vobs == 0 ||
00438 (vtsi_mat->vtsm_vobs > vtsi_mat->vtsi_last_sector &&
00439 vtsi_mat->vtsm_vobs < vtsi_mat->vts_last_sector));
00440 CHECK_VALUE(vtsi_mat->vtstt_vobs == 0 ||
00441 (vtsi_mat->vtstt_vobs > vtsi_mat->vtsi_last_sector &&
00442 vtsi_mat->vtstt_vobs < vtsi_mat->vts_last_sector));
00443 CHECK_VALUE(vtsi_mat->vts_ptt_srpt <= vtsi_mat->vtsi_last_sector);
00444 CHECK_VALUE(vtsi_mat->vts_pgcit <= vtsi_mat->vtsi_last_sector);
00445 CHECK_VALUE(vtsi_mat->vtsm_pgci_ut <= vtsi_mat->vtsi_last_sector);
00446 CHECK_VALUE(vtsi_mat->vts_tmapt <= vtsi_mat->vtsi_last_sector);
00447 CHECK_VALUE(vtsi_mat->vtsm_c_adt <= vtsi_mat->vtsi_last_sector);
00448 CHECK_VALUE(vtsi_mat->vtsm_vobu_admap <= vtsi_mat->vtsi_last_sector);
00449 CHECK_VALUE(vtsi_mat->vts_c_adt <= vtsi_mat->vtsi_last_sector);
00450 CHECK_VALUE(vtsi_mat->vts_vobu_admap <= vtsi_mat->vtsi_last_sector);
00451
00452 CHECK_VALUE(vtsi_mat->nr_of_vtsm_audio_streams <= 1);
00453 CHECK_VALUE(vtsi_mat->nr_of_vtsm_subp_streams <= 1);
00454
00455 CHECK_VALUE(vtsi_mat->nr_of_vts_audio_streams <= 8);
00456 for(i = vtsi_mat->nr_of_vts_audio_streams; i < 8; i++)
00457 CHECK_ZERO(vtsi_mat->vts_audio_attr[i]);
00458
00459 CHECK_VALUE(vtsi_mat->nr_of_vts_subp_streams <= 32);
00460 for(i = vtsi_mat->nr_of_vts_subp_streams; i < 32; i++)
00461 CHECK_ZERO(vtsi_mat->vts_subp_attr[i]);
00462
00463 for(i = 0; i < 8; i++) {
00464 CHECK_ZERO0(vtsi_mat->vts_mu_audio_attr[i].zero1);
00465 CHECK_ZERO0(vtsi_mat->vts_mu_audio_attr[i].zero2);
00466 CHECK_ZERO0(vtsi_mat->vts_mu_audio_attr[i].zero3);
00467 CHECK_ZERO0(vtsi_mat->vts_mu_audio_attr[i].zero4);
00468 CHECK_ZERO0(vtsi_mat->vts_mu_audio_attr[i].zero5);
00469 CHECK_ZERO(vtsi_mat->vts_mu_audio_attr[i].zero6);
00470 }
00471
00472 return 1;
00473 }
00474
00475
00476 static int ifoRead_PGC_COMMAND_TBL(ifo_handle_t *ifofile,
00477 pgc_command_tbl_t *cmd_tbl,
00478 unsigned int offset) {
00479
00480 memset(cmd_tbl, 0, sizeof(pgc_command_tbl_t));
00481
00482 if(!DVDFileSeek_(ifofile->file, offset))
00483 return 0;
00484
00485 if(!(DVDReadBytes(ifofile->file, cmd_tbl, PGC_COMMAND_TBL_SIZE)))
00486 return 0;
00487
00488 B2N_16(cmd_tbl->nr_of_pre);
00489 B2N_16(cmd_tbl->nr_of_post);
00490 B2N_16(cmd_tbl->nr_of_cell);
00491
00492 CHECK_VALUE(cmd_tbl->nr_of_pre + cmd_tbl->nr_of_post + cmd_tbl->nr_of_cell<= 255);
00493
00494 if(cmd_tbl->nr_of_pre != 0) {
00495 unsigned int pre_cmds_size = cmd_tbl->nr_of_pre * COMMAND_DATA_SIZE;
00496 cmd_tbl->pre_cmds = (vm_cmd_t *)malloc(pre_cmds_size);
00497 if(!cmd_tbl->pre_cmds)
00498 return 0;
00499
00500 if(!(DVDReadBytes(ifofile->file, cmd_tbl->pre_cmds, pre_cmds_size))) {
00501 free(cmd_tbl->pre_cmds);
00502 return 0;
00503 }
00504 }
00505
00506 if(cmd_tbl->nr_of_post != 0) {
00507 unsigned int post_cmds_size = cmd_tbl->nr_of_post * COMMAND_DATA_SIZE;
00508 cmd_tbl->post_cmds = (vm_cmd_t *)malloc(post_cmds_size);
00509 if(!cmd_tbl->post_cmds) {
00510 if(cmd_tbl->pre_cmds)
00511 free(cmd_tbl->pre_cmds);
00512 return 0;
00513 }
00514 if(!(DVDReadBytes(ifofile->file, cmd_tbl->post_cmds, post_cmds_size))) {
00515 if(cmd_tbl->pre_cmds)
00516 free(cmd_tbl->pre_cmds);
00517 free(cmd_tbl->post_cmds);
00518 return 0;
00519 }
00520 }
00521
00522 if(cmd_tbl->nr_of_cell != 0) {
00523 unsigned int cell_cmds_size = cmd_tbl->nr_of_cell * COMMAND_DATA_SIZE;
00524 cmd_tbl->cell_cmds = (vm_cmd_t *)malloc(cell_cmds_size);
00525 if(!cmd_tbl->cell_cmds) {
00526 if(cmd_tbl->pre_cmds)
00527 free(cmd_tbl->pre_cmds);
00528 if(cmd_tbl->post_cmds)
00529 free(cmd_tbl->post_cmds);
00530 return 0;
00531 }
00532 if(!(DVDReadBytes(ifofile->file, cmd_tbl->cell_cmds, cell_cmds_size))) {
00533 if(cmd_tbl->pre_cmds)
00534 free(cmd_tbl->pre_cmds);
00535 if(cmd_tbl->post_cmds)
00536 free(cmd_tbl->post_cmds);
00537 free(cmd_tbl->cell_cmds);
00538 return 0;
00539 }
00540 }
00541
00542
00543
00544
00545 return 1;
00546 }
00547
00548
00549 static void ifoFree_PGC_COMMAND_TBL(pgc_command_tbl_t *cmd_tbl) {
00550 if(cmd_tbl) {
00551 if(cmd_tbl->nr_of_pre && cmd_tbl->pre_cmds)
00552 free(cmd_tbl->pre_cmds);
00553 if(cmd_tbl->nr_of_post && cmd_tbl->post_cmds)
00554 free(cmd_tbl->post_cmds);
00555 if(cmd_tbl->nr_of_cell && cmd_tbl->cell_cmds)
00556 free(cmd_tbl->cell_cmds);
00557 free(cmd_tbl);
00558 }
00559 }
00560
00561 static int ifoRead_PGC_PROGRAM_MAP(ifo_handle_t *ifofile,
00562 pgc_program_map_t *program_map,
00563 unsigned int nr, unsigned int offset) {
00564 unsigned int size = nr * sizeof(pgc_program_map_t);
00565
00566 if(!DVDFileSeek_(ifofile->file, offset))
00567 return 0;
00568
00569 if(!(DVDReadBytes(ifofile->file, program_map, size)))
00570 return 0;
00571
00572 return 1;
00573 }
00574
00575 static int ifoRead_CELL_PLAYBACK_TBL(ifo_handle_t *ifofile,
00576 cell_playback_t *cell_playback,
00577 unsigned int nr, unsigned int offset) {
00578 unsigned int i;
00579 unsigned int size = nr * sizeof(cell_playback_t);
00580
00581 if(!DVDFileSeek_(ifofile->file, offset))
00582 return 0;
00583
00584 if(!(DVDReadBytes(ifofile->file, cell_playback, size)))
00585 return 0;
00586
00587 for(i = 0; i < nr; i++) {
00588 B2N_32(cell_playback[i].first_sector);
00589 B2N_32(cell_playback[i].first_ilvu_end_sector);
00590 B2N_32(cell_playback[i].last_vobu_start_sector);
00591 B2N_32(cell_playback[i].last_sector);
00592
00593
00594 CHECK_VALUE(cell_playback[i].last_vobu_start_sector <=
00595 cell_playback[i].last_sector);
00596 CHECK_VALUE(cell_playback[i].first_sector <=
00597 cell_playback[i].last_vobu_start_sector);
00598 }
00599
00600 return 1;
00601 }
00602
00603
00604 static int ifoRead_CELL_POSITION_TBL(ifo_handle_t *ifofile,
00605 cell_position_t *cell_position,
00606 unsigned int nr, unsigned int offset) {
00607 unsigned int i;
00608 unsigned int size = nr * sizeof(cell_position_t);
00609
00610 if(!DVDFileSeek_(ifofile->file, offset))
00611 return 0;
00612
00613 if(!(DVDReadBytes(ifofile->file, cell_position, size)))
00614 return 0;
00615
00616 for(i = 0; i < nr; i++) {
00617 B2N_16(cell_position[i].vob_id_nr);
00618 CHECK_ZERO(cell_position[i].zero_1);
00619 }
00620
00621 return 1;
00622 }
00623
00624 static int ifoRead_PGC(ifo_handle_t *ifofile, pgc_t *pgc, unsigned int offset) {
00625 unsigned int i;
00626
00627 if(!DVDFileSeek_(ifofile->file, offset))
00628 return 0;
00629
00630 if(!(DVDReadBytes(ifofile->file, pgc, PGC_SIZE)))
00631 return 0;
00632
00633 B2N_16(pgc->next_pgc_nr);
00634 B2N_16(pgc->prev_pgc_nr);
00635 B2N_16(pgc->goup_pgc_nr);
00636 B2N_16(pgc->command_tbl_offset);
00637 B2N_16(pgc->program_map_offset);
00638 B2N_16(pgc->cell_playback_offset);
00639 B2N_16(pgc->cell_position_offset);
00640
00641 for(i = 0; i < 16; i++)
00642 B2N_32(pgc->palette[i]);
00643
00644 CHECK_ZERO(pgc->zero_1);
00645 CHECK_VALUE(pgc->nr_of_programs <= pgc->nr_of_cells);
00646
00647
00648 for(i = 0; i < 8; i++)
00649 if(!pgc->audio_control[i].present)
00650 CHECK_ZERO(pgc->audio_control[i]);
00651 for(i = 0; i < 32; i++)
00652 if(!pgc->subp_control[i].present)
00653 CHECK_ZERO(pgc->subp_control[i]);
00654
00655
00656 if(pgc->nr_of_programs == 0) {
00657 CHECK_ZERO(pgc->still_time);
00658 CHECK_ZERO(pgc->pg_playback_mode);
00659 CHECK_VALUE(pgc->program_map_offset == 0);
00660 CHECK_VALUE(pgc->cell_playback_offset == 0);
00661 CHECK_VALUE(pgc->cell_position_offset == 0);
00662 } else {
00663 CHECK_VALUE(pgc->program_map_offset != 0);
00664 CHECK_VALUE(pgc->cell_playback_offset != 0);
00665 CHECK_VALUE(pgc->cell_position_offset != 0);
00666 }
00667
00668 if(pgc->command_tbl_offset != 0) {
00669 pgc->command_tbl = malloc(sizeof(pgc_command_tbl_t));
00670 if(!pgc->command_tbl)
00671 return 0;
00672
00673 if(!ifoRead_PGC_COMMAND_TBL(ifofile, pgc->command_tbl,
00674 offset + pgc->command_tbl_offset)) {
00675 free(pgc->command_tbl);
00676 return 0;
00677 }
00678 } else {
00679 pgc->command_tbl = NULL;
00680 }
00681
00682 if(pgc->program_map_offset != 0 && pgc->nr_of_programs>0) {
00683 pgc->program_map = malloc(pgc->nr_of_programs * sizeof(pgc_program_map_t));
00684 if(!pgc->program_map) {
00685 ifoFree_PGC_COMMAND_TBL(pgc->command_tbl);
00686 return 0;
00687 }
00688 if(!ifoRead_PGC_PROGRAM_MAP(ifofile, pgc->program_map,pgc->nr_of_programs,
00689 offset + pgc->program_map_offset)) {
00690 ifoFree_PGC_COMMAND_TBL(pgc->command_tbl);
00691 free(pgc->program_map);
00692 return 0;
00693 }
00694 } else {
00695 pgc->program_map = NULL;
00696 }
00697
00698 if(pgc->cell_playback_offset != 0 && pgc->nr_of_cells>0) {
00699 pgc->cell_playback = malloc(pgc->nr_of_cells * sizeof(cell_playback_t));
00700 if(!pgc->cell_playback) {
00701 ifoFree_PGC_COMMAND_TBL(pgc->command_tbl);
00702 if(pgc->program_map)
00703 free(pgc->program_map);
00704 return 0;
00705 }
00706 if(!ifoRead_CELL_PLAYBACK_TBL(ifofile, pgc->cell_playback,
00707 pgc->nr_of_cells,
00708 offset + pgc->cell_playback_offset)) {
00709 ifoFree_PGC_COMMAND_TBL(pgc->command_tbl);
00710 if(pgc->program_map)
00711 free(pgc->program_map);
00712 free(pgc->cell_playback);
00713 return 0;
00714 }
00715 } else {
00716 pgc->cell_playback = NULL;
00717 }
00718
00719 if(pgc->cell_position_offset != 0 && pgc->nr_of_cells>0) {
00720 pgc->cell_position = malloc(pgc->nr_of_cells * sizeof(cell_position_t));
00721 if(!pgc->cell_position) {
00722 ifoFree_PGC(pgc);
00723 return 0;
00724 }
00725 if(!ifoRead_CELL_POSITION_TBL(ifofile, pgc->cell_position,
00726 pgc->nr_of_cells,
00727 offset + pgc->cell_position_offset)) {
00728 ifoFree_PGC(pgc);
00729 return 0;
00730 }
00731 } else {
00732 pgc->cell_position = NULL;
00733 }
00734
00735 return 1;
00736 }
00737
00738 int ifoRead_FP_PGC(ifo_handle_t *ifofile) {
00739
00740 if(!ifofile)
00741 return 0;
00742
00743 if(!ifofile->vmgi_mat)
00744 return 0;
00745
00746
00747 ifofile->first_play_pgc = 0;
00748 if(ifofile->vmgi_mat->first_play_pgc == 0)
00749 return 1;
00750
00751 ifofile->first_play_pgc = (pgc_t *)malloc(sizeof(pgc_t));
00752 if(!ifofile->first_play_pgc)
00753 return 0;
00754
00755 if(!ifoRead_PGC(ifofile, ifofile->first_play_pgc,
00756 ifofile->vmgi_mat->first_play_pgc)) {
00757 free(ifofile->first_play_pgc);
00758 ifofile->first_play_pgc = 0;
00759 return 0;
00760 }
00761
00762 return 1;
00763 }
00764
00765 static void ifoFree_PGC(pgc_t *pgc) {
00766 if(pgc) {
00767 ifoFree_PGC_COMMAND_TBL(pgc->command_tbl);
00768 if(pgc->program_map)
00769 free(pgc->program_map);
00770 if(pgc->cell_playback)
00771 free(pgc->cell_playback);
00772 if(pgc->cell_position)
00773 free(pgc->cell_position);
00774 }
00775 }
00776
00777 void ifoFree_FP_PGC(ifo_handle_t *ifofile) {
00778 if(!ifofile)
00779 return;
00780
00781 if(ifofile->first_play_pgc) {
00782 ifoFree_PGC(ifofile->first_play_pgc);
00783 free(ifofile->first_play_pgc);
00784 ifofile->first_play_pgc = 0;
00785 }
00786 }
00787
00788
00789 int ifoRead_TT_SRPT(ifo_handle_t *ifofile) {
00790 tt_srpt_t *tt_srpt;
00791 int i, info_length;
00792
00793 if(!ifofile)
00794 return 0;
00795
00796 if(!ifofile->vmgi_mat)
00797 return 0;
00798
00799 if(ifofile->vmgi_mat->tt_srpt == 0)
00800 return 0;
00801
00802 if(!DVDFileSeek_(ifofile->file, ifofile->vmgi_mat->tt_srpt * DVD_BLOCK_LEN))
00803 return 0;
00804
00805 tt_srpt = (tt_srpt_t *)malloc(sizeof(tt_srpt_t));
00806 if(!tt_srpt)
00807 return 0;
00808
00809 ifofile->tt_srpt = tt_srpt;
00810
00811 if(!(DVDReadBytes(ifofile->file, tt_srpt, TT_SRPT_SIZE))) {
00812 fprintf(stderr, "libdvdread: Unable to read read TT_SRPT.\n");
00813 free(tt_srpt);
00814 return 0;
00815 }
00816
00817 B2N_16(tt_srpt->nr_of_srpts);
00818 B2N_32(tt_srpt->last_byte);
00819
00820 info_length = tt_srpt->last_byte + 1 - TT_SRPT_SIZE;
00821
00822 tt_srpt->title = (title_info_t *)malloc(info_length);
00823 if(!tt_srpt->title) {
00824 free(tt_srpt);
00825 ifofile->tt_srpt = 0;
00826 return 0;
00827 }
00828 if(!(DVDReadBytes(ifofile->file, tt_srpt->title, info_length))) {
00829 fprintf(stderr, "libdvdread: Unable to read read TT_SRPT.\n");
00830 ifoFree_TT_SRPT(ifofile);
00831 return 0;
00832 }
00833
00834 for(i = 0; i < tt_srpt->nr_of_srpts; i++) {
00835 B2N_16(tt_srpt->title[i].nr_of_ptts);
00836 B2N_16(tt_srpt->title[i].parental_id);
00837 B2N_32(tt_srpt->title[i].title_set_sector);
00838 }
00839
00840
00841 CHECK_ZERO(tt_srpt->zero_1);
00842 CHECK_VALUE(tt_srpt->nr_of_srpts != 0);
00843 CHECK_VALUE(tt_srpt->nr_of_srpts < 100);
00844 CHECK_VALUE((int)tt_srpt->nr_of_srpts * sizeof(title_info_t) <= info_length);
00845
00846 for(i = 0; i < tt_srpt->nr_of_srpts; i++) {
00847 CHECK_VALUE(tt_srpt->title[i].pb_ty.zero_1 == 0);
00848 CHECK_VALUE(tt_srpt->title[i].nr_of_angles != 0);
00849 CHECK_VALUE(tt_srpt->title[i].nr_of_angles < 10);
00850
00851
00852 CHECK_VALUE(tt_srpt->title[i].nr_of_ptts < 1000);
00853 CHECK_VALUE(tt_srpt->title[i].title_set_nr != 0);
00854 CHECK_VALUE(tt_srpt->title[i].title_set_nr < 100);
00855 CHECK_VALUE(tt_srpt->title[i].vts_ttn != 0);
00856 CHECK_VALUE(tt_srpt->title[i].vts_ttn < 100);
00857
00858 }
00859
00860
00861 #if 0
00862 if(memcmp((uint8_t *)tt_srpt->title +
00863 tt_srpt->nr_of_srpts * sizeof(title_info_t),
00864 my_friendly_zeros,
00865 info_length - tt_srpt->nr_of_srpts * sizeof(title_info_t))) {
00866 fprintf(stderr, "VMG_PTT_SRPT slack is != 0, ");
00867 hexdump((uint8_t *)tt_srpt->title +
00868 tt_srpt->nr_of_srpts * sizeof(title_info_t),
00869 info_length - tt_srpt->nr_of_srpts * sizeof(title_info_t));
00870 }
00871 #endif
00872
00873 return 1;
00874 }
00875
00876
00877 void ifoFree_TT_SRPT(ifo_handle_t *ifofile) {
00878 if(!ifofile)
00879 return;
00880
00881 if(ifofile->tt_srpt) {
00882 free(ifofile->tt_srpt->title);
00883 free(ifofile->tt_srpt);
00884 ifofile->tt_srpt = 0;
00885 }
00886 }
00887
00888
00889 int ifoRead_VTS_PTT_SRPT(ifo_handle_t *ifofile) {
00890 vts_ptt_srpt_t *vts_ptt_srpt;
00891 int info_length, i, j;
00892 uint32_t *data;
00893
00894 if(!ifofile)
00895 return 0;
00896
00897 if(!ifofile->vtsi_mat)
00898 return 0;
00899
00900 if(ifofile->vtsi_mat->vts_ptt_srpt == 0)
00901 return 0;
00902
00903 if(!DVDFileSeek_(ifofile->file,
00904 ifofile->vtsi_mat->vts_ptt_srpt * DVD_BLOCK_LEN))
00905 return 0;
00906
00907 vts_ptt_srpt = (vts_ptt_srpt_t *)malloc(sizeof(vts_ptt_srpt_t));
00908 if(!vts_ptt_srpt)
00909 return 0;
00910
00911 ifofile->vts_ptt_srpt = vts_ptt_srpt;
00912
00913 if(!(DVDReadBytes(ifofile->file, vts_ptt_srpt, VTS_PTT_SRPT_SIZE))) {
00914 fprintf(stderr, "libdvdread: Unable to read PTT search table.\n");
00915 free(vts_ptt_srpt);
00916 return 0;
00917 }
00918
00919 B2N_16(vts_ptt_srpt->nr_of_srpts);
00920 B2N_32(vts_ptt_srpt->last_byte);
00921
00922 CHECK_ZERO(vts_ptt_srpt->zero_1);
00923 CHECK_VALUE(vts_ptt_srpt->nr_of_srpts != 0);
00924 CHECK_VALUE(vts_ptt_srpt->nr_of_srpts < 100);
00925
00926 info_length = vts_ptt_srpt->last_byte + 1 - VTS_PTT_SRPT_SIZE;
00927
00928 data = (uint32_t *)malloc(info_length);
00929 if(!data) {
00930 free(vts_ptt_srpt);
00931 ifofile->vts_ptt_srpt = 0;
00932 return 0;
00933 }
00934 if(!(DVDReadBytes(ifofile->file, data, info_length))) {
00935 fprintf(stderr, "libdvdread: Unable to read PTT search table.\n");
00936 free(vts_ptt_srpt);
00937 free(data);
00938 ifofile->vts_ptt_srpt = 0;
00939 return 0;
00940 }
00941
00942 for(i = 0; i < vts_ptt_srpt->nr_of_srpts; i++) {
00943 B2N_32(data[i]);
00944
00945
00946
00947
00948 CHECK_VALUE(data[i] + sizeof(ptt_info_t) <= vts_ptt_srpt->last_byte + 1 + 4);
00949 }
00950
00951 vts_ptt_srpt->ttu_offset = data;
00952
00953 vts_ptt_srpt->title = malloc(vts_ptt_srpt->nr_of_srpts * sizeof(ttu_t));
00954 if(!vts_ptt_srpt->title) {
00955 free(vts_ptt_srpt);
00956 free(data);
00957 ifofile->vts_ptt_srpt = 0;
00958 return 0;
00959 }
00960 for(i = 0; i < vts_ptt_srpt->nr_of_srpts; i++) {
00961 int n;
00962 if(i < vts_ptt_srpt->nr_of_srpts - 1)
00963 n = (data[i+1] - data[i]);
00964 else
00965 n = (vts_ptt_srpt->last_byte + 1 - data[i]);
00966
00967
00968
00969 if(n < 0) n = 0;
00970 CHECK_VALUE(n % 4 == 0);
00971
00972 vts_ptt_srpt->title[i].nr_of_ptts = n / 4;
00973 vts_ptt_srpt->title[i].ptt = malloc(n * sizeof(ptt_info_t));
00974 if(!vts_ptt_srpt->title[i].ptt) {
00975 for(n = 0; n < i; n++)
00976 free(vts_ptt_srpt->title[n].ptt);
00977 free(vts_ptt_srpt);
00978 free(data);
00979 ifofile->vts_ptt_srpt = 0;
00980 return 0;
00981 }
00982 for(j = 0; j < vts_ptt_srpt->title[i].nr_of_ptts; j++) {
00983
00984 CHECK_VALUE(data[i] + sizeof(ptt_info_t) <= vts_ptt_srpt->last_byte + 1);
00985 vts_ptt_srpt->title[i].ptt[j].pgcn
00986 = *(uint16_t*)(((char *)data) + data[i] + 4*j - VTS_PTT_SRPT_SIZE);
00987 vts_ptt_srpt->title[i].ptt[j].pgn
00988 = *(uint16_t*)(((char *)data) + data[i] + 4*j + 2 - VTS_PTT_SRPT_SIZE);
00989 }
00990 }
00991
00992 for(i = 0; i < vts_ptt_srpt->nr_of_srpts; i++) {
00993 for(j = 0; j < vts_ptt_srpt->title[i].nr_of_ptts; j++) {
00994 B2N_16(vts_ptt_srpt->title[i].ptt[j].pgcn);
00995 B2N_16(vts_ptt_srpt->title[i].ptt[j].pgn);
00996 }
00997 }
00998
00999 for(i = 0; i < vts_ptt_srpt->nr_of_srpts; i++) {
01000 CHECK_VALUE(vts_ptt_srpt->title[i].nr_of_ptts < 1000);
01001 for(j = 0; j < vts_ptt_srpt->title[i].nr_of_ptts; j++) {
01002 CHECK_VALUE(vts_ptt_srpt->title[i].ptt[j].pgcn != 0 );
01003 CHECK_VALUE(vts_ptt_srpt->title[i].ptt[j].pgcn < 1000);
01004 CHECK_VALUE(vts_ptt_srpt->title[i].ptt[j].pgn != 0);
01005 CHECK_VALUE(vts_ptt_srpt->title[i].ptt[j].pgn < 100);
01006 }
01007 }
01008
01009 return 1;
01010 }
01011
01012
01013 void ifoFree_VTS_PTT_SRPT(ifo_handle_t *ifofile) {
01014 if(!ifofile)
01015 return;
01016
01017 if(ifofile->vts_ptt_srpt) {
01018 int i;
01019 for(i = 0; i < ifofile->vts_ptt_srpt->nr_of_srpts; i++)
01020 free(ifofile->vts_ptt_srpt->title[i].ptt);
01021 free(ifofile->vts_ptt_srpt->ttu_offset);
01022 free(ifofile->vts_ptt_srpt->title);
01023 free(ifofile->vts_ptt_srpt);
01024 ifofile->vts_ptt_srpt = 0;
01025 }
01026 }
01027
01028
01029 int ifoRead_PTL_MAIT(ifo_handle_t *ifofile) {
01030 ptl_mait_t *ptl_mait;
01031 int info_length;
01032 unsigned int i, j;
01033
01034 if(!ifofile)
01035 return 0;
01036
01037 if(!ifofile->vmgi_mat)
01038 return 0;
01039
01040 if(ifofile->vmgi_mat->ptl_mait == 0)
01041 return 1;
01042
01043 if(!DVDFileSeek_(ifofile->file, ifofile->vmgi_mat->ptl_mait * DVD_BLOCK_LEN))
01044 return 0;
01045
01046 ptl_mait = (ptl_mait_t *)malloc(sizeof(ptl_mait_t));
01047 if(!ptl_mait)
01048 return 0;
01049
01050 ifofile->ptl_mait = ptl_mait;
01051
01052 if(!(DVDReadBytes(ifofile->file, ptl_mait, PTL_MAIT_SIZE))) {
01053 free(ptl_mait);
01054 ifofile->ptl_mait = 0;
01055 return 0;
01056 }
01057
01058 B2N_16(ptl_mait->nr_of_countries);
01059 B2N_16(ptl_mait->nr_of_vtss);
01060 B2N_32(ptl_mait->last_byte);
01061
01062 CHECK_VALUE(ptl_mait->nr_of_countries != 0);
01063 CHECK_VALUE(ptl_mait->nr_of_countries < 100);
01064 CHECK_VALUE(ptl_mait->nr_of_vtss != 0);
01065 CHECK_VALUE(ptl_mait->nr_of_vtss < 100);
01066 CHECK_VALUE(ptl_mait->nr_of_countries * PTL_MAIT_COUNTRY_SIZE
01067 <= ptl_mait->last_byte + 1 - PTL_MAIT_SIZE);
01068
01069 info_length = ptl_mait->nr_of_countries * sizeof(ptl_mait_country_t);
01070 ptl_mait->countries = (ptl_mait_country_t *)malloc(info_length);
01071 if(!ptl_mait->countries) {
01072 free(ptl_mait);
01073 ifofile->ptl_mait = 0;
01074 return 0;
01075 }
01076
01077 for(i = 0; i < ptl_mait->nr_of_countries; i++) {
01078 if(!(DVDReadBytes(ifofile->file, &ptl_mait->countries[i], PTL_MAIT_COUNTRY_SIZE))) {
01079 fprintf(stderr, "libdvdread: Unable to read PTL_MAIT.\n");
01080 free(ptl_mait->countries);
01081 free(ptl_mait);
01082 ifofile->ptl_mait = 0;
01083 return 0;
01084 }
01085 }
01086
01087 for(i = 0; i < ptl_mait->nr_of_countries; i++) {
01088 B2N_16(ptl_mait->countries[i].country_code);
01089 B2N_16(ptl_mait->countries[i].pf_ptl_mai_start_byte);
01090 }
01091
01092 for(i = 0; i < ptl_mait->nr_of_countries; i++) {
01093 CHECK_ZERO(ptl_mait->countries[i].zero_1);
01094 CHECK_ZERO(ptl_mait->countries[i].zero_2);
01095 CHECK_VALUE(ptl_mait->countries[i].pf_ptl_mai_start_byte
01096 + 8*2 * (ptl_mait->nr_of_vtss + 1) <= ptl_mait->last_byte + 1);
01097 }
01098
01099 for(i = 0; i < ptl_mait->nr_of_countries; i++) {
01100 uint16_t *pf_temp;
01101
01102 if(!DVDFileSeek_(ifofile->file,
01103 ifofile->vmgi_mat->ptl_mait * DVD_BLOCK_LEN
01104 + ptl_mait->countries[i].pf_ptl_mai_start_byte)) {
01105 fprintf(stderr, "libdvdread: Unable to seak PTL_MAIT table.\n");
01106 free(ptl_mait->countries);
01107 free(ptl_mait);
01108 return 0;
01109 }
01110 info_length = (ptl_mait->nr_of_vtss + 1) * sizeof(pf_level_t);
01111 pf_temp = (uint16_t *)malloc(info_length);
01112 if(!pf_temp) {
01113 for(j = 0; j < i ; j++) {
01114 free(ptl_mait->countries[j].pf_ptl_mai);
01115 }
01116 free(ptl_mait->countries);
01117 free(ptl_mait);
01118 return 0;
01119 }
01120 if(!(DVDReadBytes(ifofile->file, pf_temp, info_length))) {
01121 fprintf(stderr, "libdvdread: Unable to read PTL_MAIT table.\n");
01122 free(pf_temp);
01123 for(j = 0; j < i ; j++) {
01124 free(ptl_mait->countries[j].pf_ptl_mai);
01125 }
01126 free(ptl_mait->countries);
01127 free(ptl_mait);
01128 return 0;
01129 }
01130 for (j = 0; j < ((ptl_mait->nr_of_vtss + 1) * 8); j++) {
01131 B2N_16(pf_temp[j]);
01132 }
01133 ptl_mait->countries[i].pf_ptl_mai = (pf_level_t *)malloc(info_length);
01134 if(!ptl_mait->countries[i].pf_ptl_mai) {
01135 free(pf_temp);
01136 for(j = 0; j < i ; j++) {
01137 free(ptl_mait->countries[j].pf_ptl_mai);
01138 }
01139 free(ptl_mait->countries);
01140 free(ptl_mait);
01141 return 0;
01142 }
01143 {
01144 int level, vts;
01145 for(level = 0; level < 8; level++) {
01146 for(vts = 0; vts <= ptl_mait->nr_of_vtss; vts++) {
01147 ptl_mait->countries[i].pf_ptl_mai[vts][level] =
01148 pf_temp[(7-level)*(ptl_mait->nr_of_vtss+1) + vts];
01149 }
01150 }
01151 free(pf_temp);
01152 }
01153 }
01154 return 1;
01155 }
01156
01157 void ifoFree_PTL_MAIT(ifo_handle_t *ifofile) {
01158 unsigned int i;
01159
01160 if(!ifofile)
01161 return;
01162
01163 if(ifofile->ptl_mait) {
01164 for(i = 0; i < ifofile->ptl_mait->nr_of_countries; i++) {
01165 free(ifofile->ptl_mait->countries[i].pf_ptl_mai);
01166 }
01167 free(ifofile->ptl_mait->countries);
01168 free(ifofile->ptl_mait);
01169 ifofile->ptl_mait = 0;
01170 }
01171 }
01172
01173 int ifoRead_VTS_TMAPT(ifo_handle_t *ifofile) {
01174 vts_tmapt_t *vts_tmapt;
01175 uint32_t *vts_tmap_srp;
01176 unsigned int offset;
01177 int info_length;
01178 unsigned int i, j;
01179
01180 if(!ifofile)
01181 return 0;
01182
01183 if(!ifofile->vtsi_mat)
01184 return 0;
01185
01186 if(ifofile->vtsi_mat->vts_tmapt == 0) {
01187 ifofile->vts_tmapt = NULL;
01188 fprintf(stderr,"Please send bug report - no VTS_TMAPT ?? \n");
01189 return 1;
01190 }
01191
01192 offset = ifofile->vtsi_mat->vts_tmapt * DVD_BLOCK_LEN;
01193
01194 if(!DVDFileSeek_(ifofile->file, offset))
01195 return 0;
01196
01197 vts_tmapt = (vts_tmapt_t *)malloc(sizeof(vts_tmapt_t));
01198 if(!vts_tmapt)
01199 return 0;
01200
01201 ifofile->vts_tmapt = vts_tmapt;
01202
01203 if(!(DVDReadBytes(ifofile->file, vts_tmapt, VTS_TMAPT_SIZE))) {
01204 fprintf(stderr, "libdvdread: Unable to read VTS_TMAPT.\n");
01205 free(vts_tmapt);
01206 ifofile->vts_tmapt = NULL;
01207 return 0;
01208 }
01209
01210 B2N_16(vts_tmapt->nr_of_tmaps);
01211 B2N_32(vts_tmapt->last_byte);
01212
01213 CHECK_ZERO(vts_tmapt->zero_1);
01214
01215 info_length = vts_tmapt->nr_of_tmaps * 4;
01216
01217 vts_tmap_srp = (uint32_t *)malloc(info_length);
01218 if(!vts_tmap_srp) {
01219 free(vts_tmapt);
01220 ifofile->vts_tmapt = NULL;
01221 return 0;
01222 }
01223
01224 vts_tmapt->tmap_offset = vts_tmap_srp;
01225
01226 if(!(DVDReadBytes(ifofile->file, vts_tmap_srp, info_length))) {
01227 fprintf(stderr, "libdvdread: Unable to read VTS_TMAPT.\n");
01228 free(vts_tmap_srp);
01229 free(vts_tmapt);
01230 ifofile->vts_tmapt = NULL;
01231 return 0;
01232 }
01233
01234 for (i = 0; i < vts_tmapt->nr_of_tmaps; i++) {
01235 B2N_32(vts_tmap_srp[i]);
01236 }
01237
01238
01239 info_length = vts_tmapt->nr_of_tmaps * sizeof(vts_tmap_t);
01240
01241 vts_tmapt->tmap = (vts_tmap_t *)malloc(info_length);
01242 if(!vts_tmapt->tmap) {
01243 free(vts_tmap_srp);
01244 free(vts_tmapt);
01245 ifofile->vts_tmapt = NULL;
01246 return 0;
01247 }
01248
01249 memset(vts_tmapt->tmap, 0, info_length);
01250
01251 for(i = 0; i < vts_tmapt->nr_of_tmaps; i++) {
01252 if(!DVDFileSeek_(ifofile->file, offset + vts_tmap_srp[i])) {
01253 ifoFree_VTS_TMAPT(ifofile);
01254 return 0;
01255 }
01256
01257 if(!(DVDReadBytes(ifofile->file, &vts_tmapt->tmap[i], VTS_TMAP_SIZE))) {
01258 fprintf(stderr, "libdvdread: Unable to read VTS_TMAP.\n");
01259 ifoFree_VTS_TMAPT(ifofile);
01260 return 0;
01261 }
01262
01263 B2N_16(vts_tmapt->tmap[i].nr_of_entries);
01264 CHECK_ZERO(vts_tmapt->tmap[i].zero_1);
01265
01266 if(vts_tmapt->tmap[i].nr_of_entries == 0) {
01267 vts_tmapt->tmap[i].map_ent = NULL;
01268 continue;
01269 }
01270
01271 info_length = vts_tmapt->tmap[i].nr_of_entries * sizeof(map_ent_t);
01272
01273 vts_tmapt->tmap[i].map_ent = (map_ent_t *)malloc(info_length);
01274 if(!vts_tmapt->tmap[i].map_ent) {
01275 ifoFree_VTS_TMAPT(ifofile);
01276 return 0;
01277 }
01278
01279 if(!(DVDReadBytes(ifofile->file, vts_tmapt->tmap[i].map_ent, info_length))) {
01280 fprintf(stderr, "libdvdread: Unable to read VTS_TMAP_ENT.\n");
01281 ifoFree_VTS_TMAPT(ifofile);
01282 return 0;
01283 }
01284
01285 for(j = 0; j < vts_tmapt->tmap[i].nr_of_entries; j++)
01286 B2N_32(vts_tmapt->tmap[i].map_ent[j]);
01287 }
01288
01289 return 1;
01290 }
01291
01292 void ifoFree_VTS_TMAPT(ifo_handle_t *ifofile) {
01293 unsigned int i;
01294
01295 if(!ifofile)
01296 return;
01297
01298 if(ifofile->vts_tmapt) {
01299 for(i = 0; i < ifofile->vts_tmapt->nr_of_tmaps; i++)
01300 if(ifofile->vts_tmapt->tmap[i].map_ent)
01301 free(ifofile->vts_tmapt->tmap[i].map_ent);
01302 free(ifofile->vts_tmapt->tmap);
01303 free(ifofile->vts_tmapt->tmap_offset);
01304 free(ifofile->vts_tmapt);
01305 ifofile->vts_tmapt = NULL;
01306 }
01307 }
01308
01309
01310 int ifoRead_TITLE_C_ADT(ifo_handle_t *ifofile) {
01311
01312 if(!ifofile)
01313 return 0;
01314
01315 if(!ifofile->vtsi_mat)
01316 return 0;
01317
01318 if(ifofile->vtsi_mat->vts_c_adt == 0)
01319 return 0;
01320
01321 ifofile->vts_c_adt = (c_adt_t *)malloc(sizeof(c_adt_t));
01322 if(!ifofile->vts_c_adt)
01323 return 0;
01324
01325 if(!ifoRead_C_ADT_internal(ifofile, ifofile->vts_c_adt,
01326 ifofile->vtsi_mat->vts_c_adt)) {
01327 free(ifofile->vts_c_adt);
01328 ifofile->vts_c_adt = 0;
01329 return 0;
01330 }
01331
01332 return 1;
01333 }
01334
01335 int ifoRead_C_ADT(ifo_handle_t *ifofile) {
01336 unsigned int sector;
01337
01338 if(!ifofile)
01339 return 0;
01340
01341 if(ifofile->vmgi_mat) {
01342 if(ifofile->vmgi_mat->vmgm_c_adt == 0)
01343 return 1;
01344 sector = ifofile->vmgi_mat->vmgm_c_adt;
01345 } else if(ifofile->vtsi_mat) {
01346 if(ifofile->vtsi_mat->vtsm_c_adt == 0)
01347 return 1;
01348 sector = ifofile->vtsi_mat->vtsm_c_adt;
01349 } else {
01350 return 0;
01351 }
01352
01353 ifofile->menu_c_adt = (c_adt_t *)malloc(sizeof(c_adt_t));
01354 if(!ifofile->menu_c_adt)
01355 return 0;
01356
01357 if(!ifoRead_C_ADT_internal(ifofile, ifofile->menu_c_adt, sector)) {
01358 free(ifofile->menu_c_adt);
01359 ifofile->menu_c_adt = 0;
01360 return 0;
01361 }
01362
01363 return 1;
01364 }
01365
01366 static int ifoRead_C_ADT_internal(ifo_handle_t *ifofile,
01367 c_adt_t *c_adt, unsigned int sector) {
01368 int i, info_length;
01369
01370 if(!DVDFileSeek_(ifofile->file, sector * DVD_BLOCK_LEN))
01371 return 0;
01372
01373 if(!(DVDReadBytes(ifofile->file, c_adt, C_ADT_SIZE)))
01374 return 0;
01375
01376 B2N_16(c_adt->nr_of_vobs);
01377 B2N_32(c_adt->last_byte);
01378
01379 info_length = c_adt->last_byte + 1 - C_ADT_SIZE;
01380
01381 CHECK_ZERO(c_adt->zero_1);
01382
01383
01384
01385 CHECK_VALUE(info_length % sizeof(cell_adr_t) == 0);
01386
01387
01388
01389
01390 if(info_length / sizeof(cell_adr_t) < c_adt->nr_of_vobs) {
01391 fprintf(stderr, "libdvdread: *C_ADT nr_of_vobs > avaiable info entries\n");
01392 c_adt->nr_of_vobs = info_length / sizeof(cell_adr_t);
01393 }
01394
01395 c_adt->cell_adr_table = (cell_adr_t *)malloc(info_length);
01396 if(!c_adt->cell_adr_table)
01397 return 0;
01398
01399 if(info_length &&
01400 !(DVDReadBytes(ifofile->file, c_adt->cell_adr_table, info_length))) {
01401 free(c_adt->cell_adr_table);
01402 return 0;
01403 }
01404
01405 for(i = 0; i < info_length/sizeof(cell_adr_t); i++) {
01406 B2N_16(c_adt->cell_adr_table[i].vob_id);
01407 B2N_32(c_adt->cell_adr_table[i].start_sector);
01408 B2N_32(c_adt->cell_adr_table[i].last_sector);
01409
01410 CHECK_ZERO(c_adt->cell_adr_table[i].zero_1);
01411 CHECK_VALUE(c_adt->cell_adr_table[i].vob_id > 0);
01412 CHECK_VALUE(c_adt->cell_adr_table[i].vob_id <= c_adt->nr_of_vobs);
01413 CHECK_VALUE(c_adt->cell_adr_table[i].cell_id > 0);
01414 CHECK_VALUE(c_adt->cell_adr_table[i].start_sector <
01415 c_adt->cell_adr_table[i].last_sector);
01416 }
01417
01418 return 1;
01419 }
01420
01421
01422 static void ifoFree_C_ADT_internal(c_adt_t *c_adt) {
01423 if(c_adt) {
01424 free(c_adt->cell_adr_table);
01425 free(c_adt);
01426 }
01427 }
01428
01429 void ifoFree_C_ADT(ifo_handle_t *ifofile) {
01430 if(!ifofile)
01431 return;
01432
01433 ifoFree_C_ADT_internal(ifofile->menu_c_adt);
01434 ifofile->menu_c_adt = 0;
01435 }
01436
01437 void ifoFree_TITLE_C_ADT(ifo_handle_t *ifofile) {
01438 if(!ifofile)
01439 return;
01440
01441 ifoFree_C_ADT_internal(ifofile->vts_c_adt);
01442 ifofile->vts_c_adt = 0;
01443 }
01444
01445 int ifoRead_TITLE_VOBU_ADMAP(ifo_handle_t *ifofile) {
01446 if(!ifofile)
01447 return 0;
01448
01449 if(!ifofile->vtsi_mat)
01450 return 0;
01451
01452 if(ifofile->vtsi_mat->vts_vobu_admap == 0)
01453 return 0;
01454
01455 ifofile->vts_vobu_admap = (vobu_admap_t *)malloc(sizeof(vobu_admap_t));
01456 if(!ifofile->vts_vobu_admap)
01457 return 0;
01458
01459 if(!ifoRead_VOBU_ADMAP_internal(ifofile, ifofile->vts_vobu_admap,
01460 ifofile->vtsi_mat->vts_vobu_admap)) {
01461 free(ifofile->vts_vobu_admap);
01462 ifofile->vts_vobu_admap = 0;
01463 return 0;
01464 }
01465
01466 return 1;
01467 }
01468
01469 int ifoRead_VOBU_ADMAP(ifo_handle_t *ifofile) {
01470 unsigned int sector;
01471
01472 if(!ifofile)
01473 return 0;
01474
01475 if(ifofile->vmgi_mat) {
01476 if(ifofile->vmgi_mat->vmgm_vobu_admap == 0)
01477 return 1;
01478 sector = ifofile->vmgi_mat->vmgm_vobu_admap;
01479 } else if(ifofile->vtsi_mat) {
01480 if(ifofile->vtsi_mat->vtsm_vobu_admap == 0)
01481 return 1;
01482 sector = ifofile->vtsi_mat->vtsm_vobu_admap;
01483 } else {
01484 return 0;
01485 }
01486
01487 ifofile->menu_vobu_admap = (vobu_admap_t *)malloc(sizeof(vobu_admap_t));
01488 if(!ifofile->menu_vobu_admap)
01489 return 0;
01490
01491 if(!ifoRead_VOBU_ADMAP_internal(ifofile, ifofile->menu_vobu_admap, sector)) {
01492 free(ifofile->menu_vobu_admap);
01493 ifofile->menu_vobu_admap = 0;
01494 return 0;
01495 }
01496
01497 return 1;
01498 }
01499
01500 static int ifoRead_VOBU_ADMAP_internal(ifo_handle_t *ifofile,
01501 vobu_admap_t *vobu_admap,
01502 unsigned int sector) {
01503 unsigned int i;
01504 int info_length;
01505
01506 if(!DVDFileSeek_(ifofile->file, sector * DVD_BLOCK_LEN))
01507 return 0;
01508
01509 if(!(DVDReadBytes(ifofile->file, vobu_admap, VOBU_ADMAP_SIZE)))
01510 return 0;
01511
01512 B2N_32(vobu_admap->last_byte);
01513
01514 info_length = vobu_admap->last_byte + 1 - VOBU_ADMAP_SIZE;
01515
01516
01517
01518 CHECK_VALUE(info_length % sizeof(uint32_t) == 0);
01519
01520 vobu_admap->vobu_start_sectors = (uint32_t *)malloc(info_length);
01521 if(!vobu_admap->vobu_start_sectors) {
01522 return 0;
01523 }
01524 if(info_length &&
01525 !(DVDReadBytes(ifofile->file,
01526 vobu_admap->vobu_start_sectors, info_length))) {
01527 free(vobu_admap->vobu_start_sectors);
01528 return 0;
01529 }
01530
01531 for(i = 0; i < info_length/sizeof(uint32_t); i++)
01532 B2N_32(vobu_admap->vobu_start_sectors[i]);
01533
01534 return 1;
01535 }
01536
01537
01538 static void ifoFree_VOBU_ADMAP_internal(vobu_admap_t *vobu_admap) {
01539 if(vobu_admap) {
01540 free(vobu_admap->vobu_start_sectors);
01541 free(vobu_admap);
01542 }
01543 }
01544
01545 void ifoFree_VOBU_ADMAP(ifo_handle_t *ifofile) {
01546 if(!ifofile)
01547 return;
01548
01549 ifoFree_VOBU_ADMAP_internal(ifofile->menu_vobu_admap);
01550 ifofile->menu_vobu_admap = 0;
01551 }
01552
01553 void ifoFree_TITLE_VOBU_ADMAP(ifo_handle_t *ifofile) {
01554 if(!ifofile)
01555 return;
01556
01557 ifoFree_VOBU_ADMAP_internal(ifofile->vts_vobu_admap);
01558 ifofile->vts_vobu_admap = 0;
01559 }
01560
01561 int ifoRead_PGCIT(ifo_handle_t *ifofile) {
01562
01563 if(!ifofile)
01564 return 0;
01565
01566 if(!ifofile->vtsi_mat)
01567 return 0;
01568
01569 if(ifofile->vtsi_mat->vts_pgcit == 0)
01570 return 0;
01571
01572 ifofile->vts_pgcit = (pgcit_t *)malloc(sizeof(pgcit_t));
01573 if(!ifofile->vts_pgcit)
01574 return 0;
01575
01576 if(!ifoRead_PGCIT_internal(ifofile, ifofile->vts_pgcit,
01577 ifofile->vtsi_mat->vts_pgcit * DVD_BLOCK_LEN)) {
01578 free(ifofile->vts_pgcit);
01579 ifofile->vts_pgcit = 0;
01580 return 0;
01581 }
01582
01583 return 1;
01584 }
01585
01586 static int ifoRead_PGCIT_internal(ifo_handle_t *ifofile, pgcit_t *pgcit,
01587 unsigned int offset) {
01588 int i, info_length;
01589 uint8_t *data, *ptr;
01590
01591 if(!DVDFileSeek_(ifofile->file, offset))
01592 return 0;
01593
01594 if(!(DVDReadBytes(ifofile->file, pgcit, PGCIT_SIZE)))
01595 return 0;
01596
01597 B2N_16(pgcit->nr_of_pgci_srp);
01598 B2N_32(pgcit->last_byte);
01599
01600 CHECK_ZERO(pgcit->zero_1);
01601
01602
01603
01604 CHECK_VALUE(pgcit->nr_of_pgci_srp < 10000);
01605
01606 info_length = pgcit->nr_of_pgci_srp * PGCI_SRP_SIZE;
01607 data = malloc(info_length);
01608 if(!data)
01609 return 0;
01610
01611 if(info_length && !(DVDReadBytes(ifofile->file, data, info_length))) {
01612 free(data);
01613 return 0;
01614 }
01615
01616 pgcit->pgci_srp = malloc(pgcit->nr_of_pgci_srp * sizeof(pgci_srp_t));
01617 if(!pgcit->pgci_srp) {
01618 free(data);
01619 return 0;
01620 }
01621 ptr = data;
01622 for(i = 0; i < pgcit->nr_of_pgci_srp; i++) {
01623 memcpy(&pgcit->pgci_srp[i], ptr, PGCI_SRP_SIZE);
01624 ptr += PGCI_SRP_SIZE;
01625 B2N_16(pgcit->pgci_srp[i].ptl_id_mask);
01626 B2N_32(pgcit->pgci_srp[i].pgc_start_byte);
01627 CHECK_VALUE(pgcit->pgci_srp[i].unknown1 == 0);
01628 }
01629 free(data);
01630
01631 for(i = 0; i < pgcit->nr_of_pgci_srp; i++)
01632 CHECK_VALUE(pgcit->pgci_srp[i].pgc_start_byte + PGC_SIZE <= pgcit->last_byte+1);
01633
01634 for(i = 0; i < pgcit->nr_of_pgci_srp; i++) {
01635 pgcit->pgci_srp[i].pgc = malloc(sizeof(pgc_t));
01636 if(!pgcit->pgci_srp[i].pgc) {
01637 int j;
01638 for(j = 0; j < i; j++) {
01639 ifoFree_PGC(pgcit->pgci_srp[j].pgc);
01640 free(pgcit->pgci_srp[j].pgc);
01641 }
01642 return 0;
01643 }
01644 if(!ifoRead_PGC(ifofile, pgcit->pgci_srp[i].pgc,
01645 offset + pgcit->pgci_srp[i].pgc_start_byte)) {
01646 int j;
01647 for(j = 0; j < i; j++) {
01648 ifoFree_PGC(pgcit->pgci_srp[j].pgc);
01649 free(pgcit->pgci_srp[j].pgc);
01650 }
01651 free(pgcit->pgci_srp);
01652 return 0;
01653 }
01654 }
01655
01656 return 1;
01657 }
01658
01659 static void ifoFree_PGCIT_internal(pgcit_t *pgcit) {
01660 if(pgcit) {
01661 int i;
01662 for(i = 0; i < pgcit->nr_of_pgci_srp; i++)
01663 ifoFree_PGC(pgcit->pgci_srp[i].pgc);
01664 free(pgcit->pgci_srp);
01665 }
01666 }
01667
01668 void ifoFree_PGCIT(ifo_handle_t *ifofile) {
01669 if(!ifofile)
01670 return;
01671
01672 if(ifofile->vts_pgcit) {
01673 ifoFree_PGCIT_internal(ifofile->vts_pgcit);
01674 free(ifofile->vts_pgcit);
01675 ifofile->vts_pgcit = 0;
01676 }
01677 }
01678
01679
01680 int ifoRead_PGCI_UT(ifo_handle_t *ifofile) {
01681 pgci_ut_t *pgci_ut;
01682 unsigned int sector;
01683 unsigned int i;
01684 int info_length;
01685 uint8_t *data, *ptr;
01686
01687 if(!ifofile)
01688 return 0;
01689
01690 if(ifofile->vmgi_mat) {
01691 if(ifofile->vmgi_mat->vmgm_pgci_ut == 0)
01692 return 1;
01693 sector = ifofile->vmgi_mat->vmgm_pgci_ut;
01694 } else if(ifofile->vtsi_mat) {
01695 if(ifofile->vtsi_mat->vtsm_pgci_ut == 0)
01696 return 1;
01697 sector = ifofile->vtsi_mat->vtsm_pgci_ut;
01698 } else {
01699 return 0;
01700 }
01701
01702 ifofile->pgci_ut = (pgci_ut_t *)malloc(sizeof(pgci_ut_t));
01703 if(!ifofile->pgci_ut)
01704 return 0;
01705
01706 if(!DVDFileSeek_(ifofile->file, sector * DVD_BLOCK_LEN)) {
01707 free(ifofile->pgci_ut);
01708 ifofile->pgci_ut = 0;
01709 return 0;
01710 }
01711
01712 if(!(DVDReadBytes(ifofile->file, ifofile->pgci_ut, PGCI_UT_SIZE))) {
01713 free(ifofile->pgci_ut);
01714 ifofile->pgci_ut = 0;
01715 return 0;
01716 }
01717
01718 pgci_ut = ifofile->pgci_ut;
01719
01720 B2N_16(pgci_ut->nr_of_lus);
01721 B2N_32(pgci_ut->last_byte);
01722
01723 CHECK_ZERO(pgci_ut->zero_1);
01724 CHECK_VALUE(pgci_ut->nr_of_lus != 0);
01725 CHECK_VALUE(pgci_ut->nr_of_lus < 100);
01726 CHECK_VALUE((uint32_t)pgci_ut->nr_of_lus * PGCI_LU_SIZE < pgci_ut->last_byte);
01727
01728 info_length = pgci_ut->nr_of_lus * PGCI_LU_SIZE;
01729 data = malloc(info_length);
01730 if(!data) {
01731 free(pgci_ut);
01732 ifofile->pgci_ut = 0;
01733 return 0;
01734 }
01735 if(!(DVDReadBytes(ifofile->file, data, info_length))) {
01736 free(data);
01737 free(pgci_ut);
01738 ifofile->pgci_ut = 0;
01739 return 0;
01740 }
01741
01742 pgci_ut->lu = malloc(pgci_ut->nr_of_lus * sizeof(pgci_lu_t));
01743 if(!pgci_ut->lu) {
01744 free(data);
01745 free(pgci_ut);
01746 ifofile->pgci_ut = 0;
01747 return 0;
01748 }
01749 ptr = data;
01750 for(i = 0; i < pgci_ut->nr_of_lus; i++) {
01751 memcpy(&pgci_ut->lu[i], ptr, PGCI_LU_SIZE);
01752 ptr += PGCI_LU_SIZE;
01753 B2N_16(pgci_ut->lu[i].lang_code);
01754 B2N_32(pgci_ut->lu[i].lang_start_byte);
01755 }
01756 free(data);
01757
01758 for(i = 0; i < pgci_ut->nr_of_lus; i++) {
01759
01760
01761
01762
01763
01764
01765
01766
01767
01768 CHECK_VALUE((pgci_ut->lu[i].exists & 0x07) == 0);
01769 }
01770
01771 for(i = 0; i < pgci_ut->nr_of_lus; i++) {
01772 pgci_ut->lu[i].pgcit = malloc(sizeof(pgcit_t));
01773 if(!pgci_ut->lu[i].pgcit) {
01774 unsigned int j;
01775 for(j = 0; j < i; j++) {
01776 ifoFree_PGCIT_internal(pgci_ut->lu[j].pgcit);
01777 free(pgci_ut->lu[j].pgcit);
01778 }
01779 free(pgci_ut->lu);
01780 free(pgci_ut);
01781 ifofile->pgci_ut = 0;
01782 return 0;
01783 }
01784 if(!ifoRead_PGCIT_internal(ifofile, pgci_ut->lu[i].pgcit,
01785 sector * DVD_BLOCK_LEN
01786 + pgci_ut->lu[i].lang_start_byte)) {
01787 unsigned int j;
01788 for(j = 0; j < i; j++) {
01789 ifoFree_PGCIT_internal(pgci_ut->lu[j].pgcit);
01790 free(pgci_ut->lu[j].pgcit);
01791 }
01792 free(pgci_ut->lu[i].pgcit);
01793 free(pgci_ut->lu);
01794 free(pgci_ut);
01795 ifofile->pgci_ut = 0;
01796 return 0;
01797 }
01798
01799
01800
01801
01802 }
01803
01804 return 1;
01805 }
01806
01807
01808 void ifoFree_PGCI_UT(ifo_handle_t *ifofile) {
01809 unsigned int i;
01810
01811 if(!ifofile)
01812 return;
01813
01814 if(ifofile->pgci_ut) {
01815 for(i = 0; i < ifofile->pgci_ut->nr_of_lus; i++) {
01816 ifoFree_PGCIT_internal(ifofile->pgci_ut->lu[i].pgcit);
01817 free(ifofile->pgci_ut->lu[i].pgcit);
01818 }
01819 free(ifofile->pgci_ut->lu);
01820 free(ifofile->pgci_ut);
01821 ifofile->pgci_ut = 0;
01822 }
01823 }
01824
01825 static int ifoRead_VTS_ATTRIBUTES(ifo_handle_t *ifofile,
01826 vts_attributes_t *vts_attributes,
01827 unsigned int offset) {
01828 unsigned int i;
01829
01830 if(!DVDFileSeek_(ifofile->file, offset))
01831 return 0;
01832
01833 if(!(DVDReadBytes(ifofile->file, vts_attributes, sizeof(vts_attributes_t))))
01834 return 0;
01835
01836 B2N_32(vts_attributes->last_byte);
01837 B2N_32(vts_attributes->vts_cat);
01838 B2N_16(vts_attributes->vtsm_audio_attr.lang_code);
01839 B2N_16(vts_attributes->vtsm_subp_attr.lang_code);
01840 for(i = 0; i < 8; i++)
01841 B2N_16(vts_attributes->vtstt_audio_attr[i].lang_code);
01842 for(i = 0; i < 32; i++)
01843 B2N_16(vts_attributes->vtstt_subp_attr[i].lang_code);
01844
01845 CHECK_ZERO(vts_attributes->zero_1);
01846 CHECK_ZERO(vts_attributes->zero_2);
01847 CHECK_ZERO(vts_attributes->zero_3);
01848 CHECK_ZERO(vts_attributes->zero_4);
01849 CHECK_ZERO(vts_attributes->zero_5);
01850 CHECK_ZERO(vts_attributes->zero_6);
01851 CHECK_ZERO(vts_attributes->zero_7);
01852 CHECK_VALUE(vts_attributes->nr_of_vtsm_audio_streams <= 1);
01853 CHECK_VALUE(vts_attributes->nr_of_vtsm_subp_streams <= 1);
01854 CHECK_VALUE(vts_attributes->nr_of_vtstt_audio_streams <= 8);
01855 for(i = vts_attributes->nr_of_vtstt_audio_streams; i < 8; i++)
01856 CHECK_ZERO(vts_attributes->vtstt_audio_attr[i]);
01857 CHECK_VALUE(vts_attributes->nr_of_vtstt_subp_streams <= 32);
01858 {
01859 unsigned int nr_coded;
01860 CHECK_VALUE(vts_attributes->last_byte + 1 >= VTS_ATTRIBUTES_MIN_SIZE);
01861 nr_coded = (vts_attributes->last_byte + 1 - VTS_ATTRIBUTES_MIN_SIZE)/6;
01862
01863 if(nr_coded > 32) {
01864 nr_coded = 32;
01865 }
01866 CHECK_VALUE(vts_attributes->nr_of_vtstt_subp_streams <= nr_coded);
01867 for(i = vts_attributes->nr_of_vtstt_subp_streams; i < nr_coded; i++)
01868 CHECK_ZERO(vts_attributes->vtstt_subp_attr[i]);
01869 }
01870
01871 return 1;
01872 }
01873
01874
01875
01876 int ifoRead_VTS_ATRT(ifo_handle_t *ifofile) {
01877 vts_atrt_t *vts_atrt;
01878 unsigned int i, info_length, sector;
01879 uint32_t *data;
01880
01881 if(!ifofile)
01882 return 0;
01883
01884 if(!ifofile->vmgi_mat)
01885 return 0;
01886
01887 if(ifofile->vmgi_mat->vts_atrt == 0)
01888 return 0;
01889
01890 sector = ifofile->vmgi_mat->vts_atrt;
01891 if(!DVDFileSeek_(ifofile->file, sector * DVD_BLOCK_LEN))
01892 return 0;
01893
01894 vts_atrt = (vts_atrt_t *)malloc(sizeof(vts_atrt_t));
01895 if(!vts_atrt)
01896 return 0;
01897
01898 ifofile->vts_atrt = vts_atrt;
01899
01900 if(!(DVDReadBytes(ifofile->file, vts_atrt, VTS_ATRT_SIZE))) {
01901 free(vts_atrt);
01902 ifofile->vts_atrt = 0;
01903 return 0;
01904 }
01905
01906 B2N_16(vts_atrt->nr_of_vtss);
01907 B2N_32(vts_atrt->last_byte);
01908
01909 CHECK_ZERO(vts_atrt->zero_1);
01910 CHECK_VALUE(vts_atrt->nr_of_vtss != 0);
01911 CHECK_VALUE(vts_atrt->nr_of_vtss < 100);
01912 CHECK_VALUE((uint32_t)vts_atrt->nr_of_vtss * (4 + VTS_ATTRIBUTES_MIN_SIZE) +
01913 VTS_ATRT_SIZE < vts_atrt->last_byte + 1);
01914
01915 info_length = vts_atrt->nr_of_vtss * sizeof(uint32_t);
01916 data = (uint32_t *)malloc(info_length);
01917 if(!data) {
01918 free(vts_atrt);
01919 ifofile->vts_atrt = 0;
01920 return 0;
01921 }
01922
01923 vts_atrt->vts_atrt_offsets = data;
01924
01925 if(!(DVDReadBytes(ifofile->file, data, info_length))) {
01926 free(data);
01927 free(vts_atrt);
01928 ifofile->vts_atrt = 0;
01929 return 0;
01930 }
01931
01932 for(i = 0; i < vts_atrt->nr_of_vtss; i++) {
01933 B2N_32(data[i]);
01934 CHECK_VALUE(data[i] + VTS_ATTRIBUTES_MIN_SIZE < vts_atrt->last_byte + 1);
01935 }
01936
01937 info_length = vts_atrt->nr_of_vtss * sizeof(vts_attributes_t);
01938 vts_atrt->vts = (vts_attributes_t *)malloc(info_length);
01939 if(!vts_atrt->vts) {
01940 free(data);
01941 free(vts_atrt);
01942 ifofile->vts_atrt = 0;
01943 return 0;
01944 }
01945 for(i = 0; i < vts_atrt->nr_of_vtss; i++) {
01946 unsigned int offset = data[i];
01947 if(!ifoRead_VTS_ATTRIBUTES(ifofile, &(vts_atrt->vts[i]),
01948 (sector * DVD_BLOCK_LEN) + offset)) {
01949 free(data);
01950 free(vts_atrt);
01951 ifofile->vts_atrt = 0;
01952 return 0;
01953 }
01954
01955
01956 CHECK_VALUE(offset + vts_atrt->vts[i].last_byte <= vts_atrt->last_byte + 1);
01957
01958 }
01959
01960 return 1;
01961 }
01962
01963
01964 void ifoFree_VTS_ATRT(ifo_handle_t *ifofile) {
01965 if(!ifofile)
01966 return;
01967
01968 if(ifofile->vts_atrt) {
01969 free(ifofile->vts_atrt->vts);
01970 free(ifofile->vts_atrt->vts_atrt_offsets);
01971 free(ifofile->vts_atrt);
01972 ifofile->vts_atrt = 0;
01973 }
01974 }
01975
01976
01977 int ifoRead_TXTDT_MGI(ifo_handle_t *ifofile) {
01978 txtdt_mgi_t *txtdt_mgi;
01979
01980 if(!ifofile)
01981 return 0;
01982
01983 if(!ifofile->vmgi_mat)
01984 return 0;
01985
01986
01987 if(ifofile->vmgi_mat->txtdt_mgi == 0)
01988 return 1;
01989
01990 if(!DVDFileSeek_(ifofile->file,
01991 ifofile->vmgi_mat->txtdt_mgi * DVD_BLOCK_LEN))
01992 return 0;
01993
01994 txtdt_mgi = (txtdt_mgi_t *)malloc(sizeof(txtdt_mgi_t));
01995 if(!txtdt_mgi) {
01996 return 0;
01997 }
01998 ifofile->txtdt_mgi = txtdt_mgi;
01999
02000 if(!(DVDReadBytes(ifofile->file, txtdt_mgi, TXTDT_MGI_SIZE))) {
02001 fprintf(stderr, "libdvdread: Unable to read TXTDT_MGI.\n");
02002 free(txtdt_mgi);
02003 ifofile->txtdt_mgi = 0;
02004 return 0;
02005 }
02006
02007
02008 return 1;
02009 }
02010
02011 void ifoFree_TXTDT_MGI(ifo_handle_t *ifofile) {
02012 if(!ifofile)
02013 return;
02014
02015 if(ifofile->txtdt_mgi) {
02016 free(ifofile->txtdt_mgi);
02017 ifofile->txtdt_mgi = 0;
02018 }
02019 }
02020