Fix vf_tcdump's compilation
[mplayer/kovensky.git] / libdvdread4 / ifo_read.c
blob682589a17411942193476a7c21950db2b56bd74f
1 /*
2 * Copyright (C) 2000, 2001, 2002, 2003
3 * Björn Englund <d4bjorn@dtek.chalmers.se>,
4 * Håkan Hjort <d95hjort@dtek.chalmers.se>
6 * This file is part of libdvdread.
8 * libdvdread is free software; you can redistribute it and/or modify
9 * it under the terms of the GNU General Public License as published by
10 * the Free Software Foundation; either version 2 of the License, or
11 * (at your option) any later version.
13 * libdvdread is distributed in the hope that it will be useful,
14 * but WITHOUT ANY WARRANTY; without even the implied warranty of
15 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
16 * GNU General Public License for more details.
18 * You should have received a copy of the GNU General Public License along
19 * with libdvdread; if not, write to the Free Software Foundation, Inc.,
20 * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
23 #include "config.h"
25 #include <stdio.h>
26 #include <stdlib.h>
27 #include <inttypes.h>
28 #include <string.h>
30 #include "bswap.h"
31 #include "dvdread/ifo_types.h"
32 #include "dvdread/ifo_read.h"
33 #include "dvdread/dvd_reader.h"
34 #include "dvdread_internal.h"
35 #include "dvdread/bitreader.h"
37 #ifndef DVD_BLOCK_LEN
38 #define DVD_BLOCK_LEN 2048
39 #endif
41 #ifndef NDEBUG
42 #define CHECK_ZERO0(arg) \
43 if(arg != 0) { \
44 fprintf(stderr, "*** Zero check failed in %s:%i\n for %s = 0x%x\n", \
45 __FILE__, __LINE__, # arg, arg); \
47 #define CHECK_ZERO(arg) \
48 if(memcmp(my_friendly_zeros, &arg, sizeof(arg))) { \
49 unsigned int i_CZ; \
50 fprintf(stderr, "*** Zero check failed in %s:%i\n for %s = 0x", \
51 __FILE__, __LINE__, # arg ); \
52 for(i_CZ = 0; i_CZ < sizeof(arg); i_CZ++) \
53 fprintf(stderr, "%02x", *((uint8_t *)&arg + i_CZ)); \
54 fprintf(stderr, "\n"); \
56 static const uint8_t my_friendly_zeros[2048];
57 #else
58 #define CHECK_ZERO0(arg) (void)(arg)
59 #define CHECK_ZERO(arg) (void)(arg)
60 #endif
63 /* Prototypes for internal functions */
64 static int ifoRead_VMG(ifo_handle_t *ifofile);
65 static int ifoRead_VTS(ifo_handle_t *ifofile);
66 static int ifoRead_PGC(ifo_handle_t *ifofile, pgc_t *pgc, unsigned int offset);
67 static int ifoRead_PGC_COMMAND_TBL(ifo_handle_t *ifofile,
68 pgc_command_tbl_t *cmd_tbl,
69 unsigned int offset);
70 static int ifoRead_PGC_PROGRAM_MAP(ifo_handle_t *ifofile,
71 pgc_program_map_t *program_map,
72 unsigned int nr, unsigned int offset);
73 static int ifoRead_CELL_PLAYBACK_TBL(ifo_handle_t *ifofile,
74 cell_playback_t *cell_playback,
75 unsigned int nr, unsigned int offset);
76 static int ifoRead_CELL_POSITION_TBL(ifo_handle_t *ifofile,
77 cell_position_t *cell_position,
78 unsigned int nr, unsigned int offset);
79 static int ifoRead_VTS_ATTRIBUTES(ifo_handle_t *ifofile,
80 vts_attributes_t *vts_attributes,
81 unsigned int offset);
82 static int ifoRead_C_ADT_internal(ifo_handle_t *ifofile, c_adt_t *c_adt,
83 unsigned int sector);
84 static int ifoRead_VOBU_ADMAP_internal(ifo_handle_t *ifofile,
85 vobu_admap_t *vobu_admap,
86 unsigned int sector);
87 static int ifoRead_PGCIT_internal(ifo_handle_t *ifofile, pgcit_t *pgcit,
88 unsigned int offset);
90 static void ifoFree_PGC(pgc_t *pgc);
91 static void ifoFree_PGC_COMMAND_TBL(pgc_command_tbl_t *cmd_tbl);
92 static void ifoFree_PGCIT_internal(pgcit_t *pgcit);
94 static inline int DVDFileSeekForce_( dvd_file_t *dvd_file, uint32_t offset, int force_size ) {
95 return (DVDFileSeekForce(dvd_file, (int)offset, force_size) == (int)offset);
98 static inline int DVDFileSeek_( dvd_file_t *dvd_file, uint32_t offset ) {
99 return (DVDFileSeek(dvd_file, (int)offset) == (int)offset);
102 static void read_video_attr(video_attr_t *va) {
103 getbits_state_t state;
104 uint8_t buf[sizeof(video_attr_t)];
106 memcpy(buf, va, sizeof(video_attr_t));
107 if (!dvdread_getbits_init(&state, buf)) abort();
108 va->mpeg_version = dvdread_getbits(&state, 2);
109 va->video_format = dvdread_getbits(&state, 2);
110 va->display_aspect_ratio = dvdread_getbits(&state, 2);
111 va->permitted_df = dvdread_getbits(&state, 2);
112 va->line21_cc_1 = dvdread_getbits(&state, 1);
113 va->line21_cc_2 = dvdread_getbits(&state, 1);
114 va->unknown1 = dvdread_getbits(&state, 1);
115 va->bit_rate = dvdread_getbits(&state, 1);
116 va->picture_size = dvdread_getbits(&state, 2);
117 va->letterboxed = dvdread_getbits(&state, 1);
118 va->film_mode = dvdread_getbits(&state, 1);
121 static void read_audio_attr(audio_attr_t *aa) {
122 getbits_state_t state;
123 uint8_t buf[sizeof(audio_attr_t)];
125 memcpy(buf, aa, sizeof(audio_attr_t));
126 if (!dvdread_getbits_init(&state, buf)) abort();
127 aa->audio_format = dvdread_getbits(&state, 3);
128 aa->multichannel_extension = dvdread_getbits(&state, 1);
129 aa->lang_type = dvdread_getbits(&state, 2);
130 aa->application_mode = dvdread_getbits(&state, 2);
131 aa->quantization = dvdread_getbits(&state, 2);
132 aa->sample_frequency = dvdread_getbits(&state, 2);
133 aa->unknown1 = dvdread_getbits(&state, 1);
134 aa->channels = dvdread_getbits(&state, 3);
135 aa->lang_code = dvdread_getbits(&state, 16);
136 aa->lang_extension = dvdread_getbits(&state, 8);
137 aa->code_extension = dvdread_getbits(&state, 8);
138 aa->unknown3 = dvdread_getbits(&state, 8);
139 aa->app_info.karaoke.unknown4 = dvdread_getbits(&state, 1);
140 aa->app_info.karaoke.channel_assignment = dvdread_getbits(&state, 3);
141 aa->app_info.karaoke.version = dvdread_getbits(&state, 2);
142 aa->app_info.karaoke.mc_intro = dvdread_getbits(&state, 1);
143 aa->app_info.karaoke.mode = dvdread_getbits(&state, 1);
146 static void read_multichannel_ext(multichannel_ext_t *me) {
147 getbits_state_t state;
148 uint8_t buf[sizeof(multichannel_ext_t)];
150 memcpy(buf, me, sizeof(multichannel_ext_t));
151 if (!dvdread_getbits_init(&state, buf)) abort();
152 me->zero1 = dvdread_getbits(&state, 7);
153 me->ach0_gme = dvdread_getbits(&state, 1);
154 me->zero2 = dvdread_getbits(&state, 7);
155 me->ach1_gme = dvdread_getbits(&state, 1);
156 me->zero3 = dvdread_getbits(&state, 4);
157 me->ach2_gv1e = dvdread_getbits(&state, 1);
158 me->ach2_gv2e = dvdread_getbits(&state, 1);
159 me->ach2_gm1e = dvdread_getbits(&state, 1);
160 me->ach2_gm2e = dvdread_getbits(&state, 1);
161 me->zero4 = dvdread_getbits(&state, 4);
162 me->ach3_gv1e = dvdread_getbits(&state, 1);
163 me->ach3_gv2e = dvdread_getbits(&state, 1);
164 me->ach3_gmAe = dvdread_getbits(&state, 1);
165 me->ach3_se2e = dvdread_getbits(&state, 1);
166 me->zero5 = dvdread_getbits(&state, 4);
167 me->ach4_gv1e = dvdread_getbits(&state, 1);
168 me->ach4_gv2e = dvdread_getbits(&state, 1);
169 me->ach4_gmBe = dvdread_getbits(&state, 1);
170 me->ach4_seBe = dvdread_getbits(&state, 1);
173 static void read_subp_attr(subp_attr_t *sa) {
174 getbits_state_t state;
175 uint8_t buf[sizeof(subp_attr_t)];
177 memcpy(buf, sa, sizeof(subp_attr_t));
178 if (!dvdread_getbits_init(&state, buf)) abort();
179 sa->code_mode = dvdread_getbits(&state, 3);
180 sa->zero1 = dvdread_getbits(&state, 3);
181 sa->type = dvdread_getbits(&state, 2);
182 sa->zero2 = dvdread_getbits(&state, 8);
183 sa->lang_code = dvdread_getbits(&state, 16);
184 sa->lang_extension = dvdread_getbits(&state, 8);
185 sa->code_extension = dvdread_getbits(&state, 8);
188 static void read_user_ops(user_ops_t *uo) {
189 getbits_state_t state;
190 uint8_t buf[sizeof(user_ops_t)];
192 memcpy(buf, uo, sizeof(user_ops_t));
193 if (!dvdread_getbits_init(&state, buf)) abort();
194 uo->zero = dvdread_getbits(&state, 7);
195 uo->video_pres_mode_change = dvdread_getbits(&state, 1);
196 uo->karaoke_audio_pres_mode_change = dvdread_getbits(&state, 1);
197 uo->angle_change = dvdread_getbits(&state, 1);
198 uo->subpic_stream_change = dvdread_getbits(&state, 1);
199 uo->audio_stream_change = dvdread_getbits(&state, 1);
200 uo->pause_on = dvdread_getbits(&state, 1);
201 uo->still_off = dvdread_getbits(&state, 1);
202 uo->button_select_or_activate = dvdread_getbits(&state, 1);
203 uo->resume = dvdread_getbits(&state, 1);
204 uo->chapter_menu_call = dvdread_getbits(&state, 1);
205 uo->angle_menu_call = dvdread_getbits(&state, 1);
206 uo->audio_menu_call = dvdread_getbits(&state, 1);
207 uo->subpic_menu_call = dvdread_getbits(&state, 1);
208 uo->root_menu_call = dvdread_getbits(&state, 1);
209 uo->title_menu_call = dvdread_getbits(&state, 1);
210 uo->backward_scan = dvdread_getbits(&state, 1);
211 uo->forward_scan = dvdread_getbits(&state, 1);
212 uo->next_pg_search = dvdread_getbits(&state, 1);
213 uo->prev_or_top_pg_search = dvdread_getbits(&state, 1);
214 uo->time_or_chapter_search = dvdread_getbits(&state, 1);
215 uo->go_up = dvdread_getbits(&state, 1);
216 uo->stop = dvdread_getbits(&state, 1);
217 uo->title_play = dvdread_getbits(&state, 1);
218 uo->chapter_search_or_play = dvdread_getbits(&state, 1);
219 uo->title_or_time_play = dvdread_getbits(&state, 1);
222 static void read_pgci_srp(pgci_srp_t *ps) {
223 getbits_state_t state;
224 uint8_t buf[sizeof(pgci_srp_t)];
226 memcpy(buf, ps, sizeof(pgci_srp_t));
227 if (!dvdread_getbits_init(&state, buf)) abort();
228 ps->entry_id = dvdread_getbits(&state, 8);
229 ps->block_mode = dvdread_getbits(&state, 2);
230 ps->block_type = dvdread_getbits(&state, 2);
231 ps->unknown1 = dvdread_getbits(&state, 4);
232 ps->ptl_id_mask = dvdread_getbits(&state, 16);
233 ps->pgc_start_byte = dvdread_getbits(&state, 32);
236 static void read_cell_playback(cell_playback_t *cp) {
237 getbits_state_t state;
238 uint8_t buf[sizeof(cell_playback_t)];
240 memcpy(buf, cp, sizeof(cell_playback_t));
241 if (!dvdread_getbits_init(&state, buf)) abort();
242 cp->block_mode = dvdread_getbits(&state, 2);
243 cp->block_type = dvdread_getbits(&state, 2);
244 cp->seamless_play = dvdread_getbits(&state, 1);
245 cp->interleaved = dvdread_getbits(&state, 1);
246 cp->stc_discontinuity = dvdread_getbits(&state, 1);
247 cp->seamless_angle = dvdread_getbits(&state, 1);
248 cp->playback_mode = dvdread_getbits(&state, 1);
249 cp->restricted = dvdread_getbits(&state, 1);
250 cp->unknown2 = dvdread_getbits(&state, 6);
251 cp->still_time = dvdread_getbits(&state, 8);
252 cp->cell_cmd_nr = dvdread_getbits(&state, 8);
254 cp->playback_time.hour = dvdread_getbits(&state, 8);
255 cp->playback_time.minute = dvdread_getbits(&state, 8);
256 cp->playback_time.second = dvdread_getbits(&state, 8);
257 cp->playback_time.frame_u = dvdread_getbits(&state, 8);
259 cp->first_sector = dvdread_getbits(&state, 32);
260 cp->first_ilvu_end_sector = dvdread_getbits(&state, 32);
261 cp->last_vobu_start_sector = dvdread_getbits(&state, 32);
262 cp->last_sector = dvdread_getbits(&state, 32);
265 static void read_playback_type(playback_type_t *pt) {
266 getbits_state_t state;
267 uint8_t buf[sizeof(playback_type_t)];
269 memcpy(buf, pt, sizeof(playback_type_t));
270 if (!dvdread_getbits_init(&state, buf)) abort();
271 pt->zero_1 = dvdread_getbits(&state, 1);
272 pt->multi_or_random_pgc_title = dvdread_getbits(&state, 1);
273 pt->jlc_exists_in_cell_cmd = dvdread_getbits(&state, 1);
274 pt->jlc_exists_in_prepost_cmd = dvdread_getbits(&state, 1);
275 pt->jlc_exists_in_button_cmd = dvdread_getbits(&state, 1);
276 pt->jlc_exists_in_tt_dom = dvdread_getbits(&state, 1);
277 pt->chapter_search_or_play = dvdread_getbits(&state, 1);
278 pt->title_or_time_play = dvdread_getbits(&state, 1);
281 static void free_ptl_mait(ptl_mait_t* ptl_mait, int num_entries) {
282 int i;
283 for (i = 0; i < num_entries; i++)
284 free(ptl_mait->countries[i].pf_ptl_mai);
286 free(ptl_mait->countries);
287 free(ptl_mait);
290 ifo_handle_t *ifoOpen(dvd_reader_t *dvd, int title) {
291 ifo_handle_t *ifofile;
293 ifofile = (ifo_handle_t *)malloc(sizeof(ifo_handle_t));
294 if(!ifofile)
295 return NULL;
297 memset(ifofile, 0, sizeof(ifo_handle_t));
299 ifofile->file = DVDOpenFile(dvd, title, DVD_READ_INFO_FILE);
300 if(!ifofile->file) /* Should really catch any error and try to fallback */
301 ifofile->file = DVDOpenFile(dvd, title, DVD_READ_INFO_BACKUP_FILE);
302 if(!ifofile->file) {
303 if(title) {
304 fprintf(stderr, "libdvdread: Can't open file VTS_%02d_0.IFO.\n", title);
305 } else {
306 fprintf(stderr, "libdvdread: Can't open file VIDEO_TS.IFO.\n");
308 free(ifofile);
309 return NULL;
312 /* First check if this is a VMGI file. */
313 if(ifoRead_VMG(ifofile)) {
315 /* These are both mandatory. */
316 if(!ifoRead_FP_PGC(ifofile) || !ifoRead_TT_SRPT(ifofile)) {
317 fprintf(stderr, "libdvdread: Invalid main menu IFO (VIDEO_TS.IFO), ifoRead_FP_PGC() failed.\n");
318 ifoClose(ifofile);
319 return NULL;
322 ifoRead_PGCI_UT(ifofile);
323 ifoRead_PTL_MAIT(ifofile);
325 /* This is also mandatory. */
326 if(!ifoRead_VTS_ATRT(ifofile)) {
327 fprintf(stderr, "libdvdread: Invalid main menu IFO (VIDEO_TS.IFO), ifoRead_VTS_ATRT() failed.\n");
328 ifoClose(ifofile);
329 return NULL;
332 ifoRead_TXTDT_MGI(ifofile);
333 ifoRead_C_ADT(ifofile);
334 ifoRead_VOBU_ADMAP(ifofile);
336 return ifofile;
339 if(ifoRead_VTS(ifofile)) {
341 if(!ifoRead_VTS_PTT_SRPT(ifofile) || !ifoRead_PGCIT(ifofile)) {
342 fprintf(stderr, "libdvdread: Invalid title IFO (VTS_%02d_0.IFO).\n",
343 title);
344 ifoClose(ifofile);
345 return NULL;
348 ifoRead_PGCI_UT(ifofile);
349 ifoRead_VTS_TMAPT(ifofile);
350 ifoRead_C_ADT(ifofile);
351 ifoRead_VOBU_ADMAP(ifofile);
353 if(!ifoRead_TITLE_C_ADT(ifofile) || !ifoRead_TITLE_VOBU_ADMAP(ifofile)) {
354 fprintf(stderr, "libdvdread: Invalid title IFO (VTS_%02d_0.IFO).\n",
355 title);
356 ifoClose(ifofile);
357 return NULL;
360 return ifofile;
363 if(title) {
364 fprintf(stderr, "libdvdread: Invalid IFO for title %d (VTS_%02d_0.IFO).\n",
365 title, title);
366 } else {
367 fprintf(stderr, "libdvdread: Invalid IFO for VMGM (VIDEO_TS.IFO).\n");
369 ifoClose(ifofile);
370 return NULL;
374 ifo_handle_t *ifoOpenVMGI(dvd_reader_t *dvd) {
375 ifo_handle_t *ifofile;
377 ifofile = (ifo_handle_t *)malloc(sizeof(ifo_handle_t));
378 if(!ifofile)
379 return NULL;
381 memset(ifofile, 0, sizeof(ifo_handle_t));
383 ifofile->file = DVDOpenFile(dvd, 0, DVD_READ_INFO_FILE);
384 if(!ifofile->file) /* Should really catch any error and try to fallback */
385 ifofile->file = DVDOpenFile(dvd, 0, DVD_READ_INFO_BACKUP_FILE);
386 if(!ifofile->file) {
387 fprintf(stderr, "libdvdread: Can't open file VIDEO_TS.IFO.\n");
388 free(ifofile);
389 return NULL;
392 if(ifoRead_VMG(ifofile))
393 return ifofile;
395 fprintf(stderr, "libdvdread,ifoOpenVMGI(): Invalid main menu IFO (VIDEO_TS.IFO).\n");
396 ifoClose(ifofile);
397 return NULL;
401 ifo_handle_t *ifoOpenVTSI(dvd_reader_t *dvd, int title) {
402 ifo_handle_t *ifofile;
404 ifofile = (ifo_handle_t *)malloc(sizeof(ifo_handle_t));
405 if(!ifofile)
406 return NULL;
408 memset(ifofile, 0, sizeof(ifo_handle_t));
410 if(title <= 0 || title > 99) {
411 fprintf(stderr, "libdvdread: ifoOpenVTSI invalid title (%d).\n", title);
412 free(ifofile);
413 return NULL;
416 ifofile->file = DVDOpenFile(dvd, title, DVD_READ_INFO_FILE);
417 if(!ifofile->file) /* Should really catch any error and try to fallback */
418 ifofile->file = DVDOpenFile(dvd, title, DVD_READ_INFO_BACKUP_FILE);
419 if(!ifofile->file) {
420 fprintf(stderr, "libdvdread: Can't open file VTS_%02d_0.IFO.\n", title);
421 free(ifofile);
422 return NULL;
425 ifoRead_VTS(ifofile);
426 if(ifofile->vtsi_mat)
427 return ifofile;
429 fprintf(stderr, "libdvdread: Invalid IFO for title %d (VTS_%02d_0.IFO).\n",
430 title, title);
431 ifoClose(ifofile);
432 return NULL;
436 void ifoClose(ifo_handle_t *ifofile) {
437 if(!ifofile)
438 return;
440 ifoFree_VOBU_ADMAP(ifofile);
441 ifoFree_TITLE_VOBU_ADMAP(ifofile);
442 ifoFree_C_ADT(ifofile);
443 ifoFree_TITLE_C_ADT(ifofile);
444 ifoFree_TXTDT_MGI(ifofile);
445 ifoFree_VTS_ATRT(ifofile);
446 ifoFree_PTL_MAIT(ifofile);
447 ifoFree_PGCI_UT(ifofile);
448 ifoFree_TT_SRPT(ifofile);
449 ifoFree_FP_PGC(ifofile);
450 ifoFree_PGCIT(ifofile);
451 ifoFree_VTS_PTT_SRPT(ifofile);
452 ifoFree_VTS_TMAPT(ifofile);
454 if(ifofile->vmgi_mat)
455 free(ifofile->vmgi_mat);
457 if(ifofile->vtsi_mat)
458 free(ifofile->vtsi_mat);
460 DVDCloseFile(ifofile->file);
461 ifofile->file = 0;
462 free(ifofile);
463 ifofile = 0;
467 static int ifoRead_VMG(ifo_handle_t *ifofile) {
468 vmgi_mat_t *vmgi_mat;
470 vmgi_mat = (vmgi_mat_t *)malloc(sizeof(vmgi_mat_t));
471 if(!vmgi_mat)
472 return 0;
474 ifofile->vmgi_mat = vmgi_mat;
476 if(!DVDFileSeek_(ifofile->file, 0)) {
477 free(ifofile->vmgi_mat);
478 ifofile->vmgi_mat = 0;
479 return 0;
482 if(!DVDReadBytes(ifofile->file, vmgi_mat, sizeof(vmgi_mat_t))) {
483 free(ifofile->vmgi_mat);
484 ifofile->vmgi_mat = 0;
485 return 0;
488 if(strncmp("DVDVIDEO-VMG", vmgi_mat->vmg_identifier, 12) != 0) {
489 free(ifofile->vmgi_mat);
490 ifofile->vmgi_mat = 0;
491 return 0;
494 B2N_32(vmgi_mat->vmg_last_sector);
495 B2N_32(vmgi_mat->vmgi_last_sector);
496 B2N_32(vmgi_mat->vmg_category);
497 B2N_16(vmgi_mat->vmg_nr_of_volumes);
498 B2N_16(vmgi_mat->vmg_this_volume_nr);
499 B2N_16(vmgi_mat->vmg_nr_of_title_sets);
500 B2N_64(vmgi_mat->vmg_pos_code);
501 B2N_32(vmgi_mat->vmgi_last_byte);
502 B2N_32(vmgi_mat->first_play_pgc);
503 B2N_32(vmgi_mat->vmgm_vobs);
504 B2N_32(vmgi_mat->tt_srpt);
505 B2N_32(vmgi_mat->vmgm_pgci_ut);
506 B2N_32(vmgi_mat->ptl_mait);
507 B2N_32(vmgi_mat->vts_atrt);
508 B2N_32(vmgi_mat->txtdt_mgi);
509 B2N_32(vmgi_mat->vmgm_c_adt);
510 B2N_32(vmgi_mat->vmgm_vobu_admap);
511 read_video_attr(&vmgi_mat->vmgm_video_attr);
512 read_audio_attr(&vmgi_mat->vmgm_audio_attr);
513 read_subp_attr(&vmgi_mat->vmgm_subp_attr);
516 CHECK_ZERO(vmgi_mat->zero_1);
517 CHECK_ZERO(vmgi_mat->zero_2);
518 CHECK_ZERO(vmgi_mat->zero_3);
519 CHECK_ZERO(vmgi_mat->zero_4);
520 CHECK_ZERO(vmgi_mat->zero_5);
521 CHECK_ZERO(vmgi_mat->zero_6);
522 CHECK_ZERO(vmgi_mat->zero_7);
523 CHECK_ZERO(vmgi_mat->zero_8);
524 CHECK_ZERO(vmgi_mat->zero_9);
525 CHECK_ZERO(vmgi_mat->zero_10);
526 CHECK_VALUE(vmgi_mat->vmg_last_sector != 0);
527 CHECK_VALUE(vmgi_mat->vmgi_last_sector != 0);
528 CHECK_VALUE(vmgi_mat->vmgi_last_sector * 2 <= vmgi_mat->vmg_last_sector);
529 CHECK_VALUE(vmgi_mat->vmgi_last_sector * 2 <= vmgi_mat->vmg_last_sector);
530 CHECK_VALUE(vmgi_mat->vmg_nr_of_volumes != 0);
531 CHECK_VALUE(vmgi_mat->vmg_this_volume_nr != 0);
532 CHECK_VALUE(vmgi_mat->vmg_this_volume_nr <= vmgi_mat->vmg_nr_of_volumes);
533 CHECK_VALUE(vmgi_mat->disc_side == 1 || vmgi_mat->disc_side == 2);
534 CHECK_VALUE(vmgi_mat->vmg_nr_of_title_sets != 0);
535 CHECK_VALUE(vmgi_mat->vmgi_last_byte >= 341);
536 CHECK_VALUE(vmgi_mat->vmgi_last_byte / DVD_BLOCK_LEN <=
537 vmgi_mat->vmgi_last_sector);
538 /* It seems that first_play_pgc is optional. */
539 CHECK_VALUE(vmgi_mat->first_play_pgc < vmgi_mat->vmgi_last_byte);
540 CHECK_VALUE(vmgi_mat->vmgm_vobs == 0 ||
541 (vmgi_mat->vmgm_vobs > vmgi_mat->vmgi_last_sector &&
542 vmgi_mat->vmgm_vobs < vmgi_mat->vmg_last_sector));
543 CHECK_VALUE(vmgi_mat->tt_srpt <= vmgi_mat->vmgi_last_sector);
544 CHECK_VALUE(vmgi_mat->vmgm_pgci_ut <= vmgi_mat->vmgi_last_sector);
545 CHECK_VALUE(vmgi_mat->ptl_mait <= vmgi_mat->vmgi_last_sector);
546 CHECK_VALUE(vmgi_mat->vts_atrt <= vmgi_mat->vmgi_last_sector);
547 CHECK_VALUE(vmgi_mat->txtdt_mgi <= vmgi_mat->vmgi_last_sector);
548 CHECK_VALUE(vmgi_mat->vmgm_c_adt <= vmgi_mat->vmgi_last_sector);
549 CHECK_VALUE(vmgi_mat->vmgm_vobu_admap <= vmgi_mat->vmgi_last_sector);
551 CHECK_VALUE(vmgi_mat->nr_of_vmgm_audio_streams <= 1);
552 CHECK_VALUE(vmgi_mat->nr_of_vmgm_subp_streams <= 1);
554 return 1;
558 static int ifoRead_VTS(ifo_handle_t *ifofile) {
559 vtsi_mat_t *vtsi_mat;
560 int i;
562 vtsi_mat = (vtsi_mat_t *)malloc(sizeof(vtsi_mat_t));
563 if(!vtsi_mat)
564 return 0;
566 ifofile->vtsi_mat = vtsi_mat;
568 if(!DVDFileSeek_(ifofile->file, 0)) {
569 free(ifofile->vtsi_mat);
570 ifofile->vtsi_mat = 0;
571 return 0;
574 if(!(DVDReadBytes(ifofile->file, vtsi_mat, sizeof(vtsi_mat_t)))) {
575 free(ifofile->vtsi_mat);
576 ifofile->vtsi_mat = 0;
577 return 0;
580 if(strncmp("DVDVIDEO-VTS", vtsi_mat->vts_identifier, 12) != 0) {
581 free(ifofile->vtsi_mat);
582 ifofile->vtsi_mat = 0;
583 return 0;
586 read_video_attr(&vtsi_mat->vtsm_video_attr);
587 read_video_attr(&vtsi_mat->vts_video_attr);
588 read_audio_attr(&vtsi_mat->vtsm_audio_attr);
589 for(i=0; i<8; i++)
590 read_audio_attr(&vtsi_mat->vts_audio_attr[i]);
591 read_subp_attr(&vtsi_mat->vtsm_subp_attr);
592 for(i=0; i<32; i++)
593 read_subp_attr(&vtsi_mat->vts_subp_attr[i]);
594 B2N_32(vtsi_mat->vts_last_sector);
595 B2N_32(vtsi_mat->vtsi_last_sector);
596 B2N_32(vtsi_mat->vts_category);
597 B2N_32(vtsi_mat->vtsi_last_byte);
598 B2N_32(vtsi_mat->vtsm_vobs);
599 B2N_32(vtsi_mat->vtstt_vobs);
600 B2N_32(vtsi_mat->vts_ptt_srpt);
601 B2N_32(vtsi_mat->vts_pgcit);
602 B2N_32(vtsi_mat->vtsm_pgci_ut);
603 B2N_32(vtsi_mat->vts_tmapt);
604 B2N_32(vtsi_mat->vtsm_c_adt);
605 B2N_32(vtsi_mat->vtsm_vobu_admap);
606 B2N_32(vtsi_mat->vts_c_adt);
607 B2N_32(vtsi_mat->vts_vobu_admap);
610 CHECK_ZERO(vtsi_mat->zero_1);
611 CHECK_ZERO(vtsi_mat->zero_2);
612 CHECK_ZERO(vtsi_mat->zero_3);
613 CHECK_ZERO(vtsi_mat->zero_4);
614 CHECK_ZERO(vtsi_mat->zero_5);
615 CHECK_ZERO(vtsi_mat->zero_6);
616 CHECK_ZERO(vtsi_mat->zero_7);
617 CHECK_ZERO(vtsi_mat->zero_8);
618 CHECK_ZERO(vtsi_mat->zero_9);
619 CHECK_ZERO(vtsi_mat->zero_10);
620 CHECK_ZERO(vtsi_mat->zero_11);
621 CHECK_ZERO(vtsi_mat->zero_12);
622 CHECK_ZERO(vtsi_mat->zero_13);
623 CHECK_ZERO(vtsi_mat->zero_14);
624 CHECK_ZERO(vtsi_mat->zero_15);
625 CHECK_ZERO(vtsi_mat->zero_16);
626 CHECK_ZERO(vtsi_mat->zero_17);
627 CHECK_ZERO(vtsi_mat->zero_18);
628 CHECK_ZERO(vtsi_mat->zero_19);
629 CHECK_ZERO(vtsi_mat->zero_20);
630 CHECK_ZERO(vtsi_mat->zero_21);
631 CHECK_VALUE(vtsi_mat->vtsi_last_sector*2 <= vtsi_mat->vts_last_sector);
632 CHECK_VALUE(vtsi_mat->vtsi_last_byte/DVD_BLOCK_LEN <= vtsi_mat->vtsi_last_sector);
633 CHECK_VALUE(vtsi_mat->vtsm_vobs == 0 ||
634 (vtsi_mat->vtsm_vobs > vtsi_mat->vtsi_last_sector &&
635 vtsi_mat->vtsm_vobs < vtsi_mat->vts_last_sector));
636 CHECK_VALUE(vtsi_mat->vtstt_vobs == 0 ||
637 (vtsi_mat->vtstt_vobs > vtsi_mat->vtsi_last_sector &&
638 vtsi_mat->vtstt_vobs < vtsi_mat->vts_last_sector));
639 CHECK_VALUE(vtsi_mat->vts_ptt_srpt <= vtsi_mat->vtsi_last_sector);
640 CHECK_VALUE(vtsi_mat->vts_pgcit <= vtsi_mat->vtsi_last_sector);
641 CHECK_VALUE(vtsi_mat->vtsm_pgci_ut <= vtsi_mat->vtsi_last_sector);
642 CHECK_VALUE(vtsi_mat->vts_tmapt <= vtsi_mat->vtsi_last_sector);
643 CHECK_VALUE(vtsi_mat->vtsm_c_adt <= vtsi_mat->vtsi_last_sector);
644 CHECK_VALUE(vtsi_mat->vtsm_vobu_admap <= vtsi_mat->vtsi_last_sector);
645 CHECK_VALUE(vtsi_mat->vts_c_adt <= vtsi_mat->vtsi_last_sector);
646 CHECK_VALUE(vtsi_mat->vts_vobu_admap <= vtsi_mat->vtsi_last_sector);
648 CHECK_VALUE(vtsi_mat->nr_of_vtsm_audio_streams <= 1);
649 CHECK_VALUE(vtsi_mat->nr_of_vtsm_subp_streams <= 1);
651 CHECK_VALUE(vtsi_mat->nr_of_vts_audio_streams <= 8);
652 for(i = vtsi_mat->nr_of_vts_audio_streams; i < 8; i++)
653 CHECK_ZERO(vtsi_mat->vts_audio_attr[i]);
655 CHECK_VALUE(vtsi_mat->nr_of_vts_subp_streams <= 32);
656 for(i = vtsi_mat->nr_of_vts_subp_streams; i < 32; i++)
657 CHECK_ZERO(vtsi_mat->vts_subp_attr[i]);
659 for(i = 0; i < 8; i++) {
660 read_multichannel_ext(&vtsi_mat->vts_mu_audio_attr[i]);
661 CHECK_ZERO0(vtsi_mat->vts_mu_audio_attr[i].zero1);
662 CHECK_ZERO0(vtsi_mat->vts_mu_audio_attr[i].zero2);
663 CHECK_ZERO0(vtsi_mat->vts_mu_audio_attr[i].zero3);
664 CHECK_ZERO0(vtsi_mat->vts_mu_audio_attr[i].zero4);
665 CHECK_ZERO0(vtsi_mat->vts_mu_audio_attr[i].zero5);
666 CHECK_ZERO(vtsi_mat->vts_mu_audio_attr[i].zero6);
669 return 1;
673 static int ifoRead_PGC_COMMAND_TBL(ifo_handle_t *ifofile,
674 pgc_command_tbl_t *cmd_tbl,
675 unsigned int offset) {
677 memset(cmd_tbl, 0, sizeof(pgc_command_tbl_t));
679 if(!DVDFileSeek_(ifofile->file, offset))
680 return 0;
682 if(!(DVDReadBytes(ifofile->file, cmd_tbl, PGC_COMMAND_TBL_SIZE)))
683 return 0;
685 B2N_16(cmd_tbl->nr_of_pre);
686 B2N_16(cmd_tbl->nr_of_post);
687 B2N_16(cmd_tbl->nr_of_cell);
689 CHECK_VALUE(cmd_tbl->nr_of_pre + cmd_tbl->nr_of_post + cmd_tbl->nr_of_cell<= 255);
691 if(cmd_tbl->nr_of_pre != 0) {
692 unsigned int pre_cmds_size = cmd_tbl->nr_of_pre * COMMAND_DATA_SIZE;
693 cmd_tbl->pre_cmds = (vm_cmd_t *)malloc(pre_cmds_size);
694 if(!cmd_tbl->pre_cmds)
695 return 0;
697 if(!(DVDReadBytes(ifofile->file, cmd_tbl->pre_cmds, pre_cmds_size))) {
698 free(cmd_tbl->pre_cmds);
699 return 0;
703 if(cmd_tbl->nr_of_post != 0) {
704 unsigned int post_cmds_size = cmd_tbl->nr_of_post * COMMAND_DATA_SIZE;
705 cmd_tbl->post_cmds = (vm_cmd_t *)malloc(post_cmds_size);
706 if(!cmd_tbl->post_cmds) {
707 if(cmd_tbl->pre_cmds)
708 free(cmd_tbl->pre_cmds);
709 return 0;
711 if(!(DVDReadBytes(ifofile->file, cmd_tbl->post_cmds, post_cmds_size))) {
712 if(cmd_tbl->pre_cmds)
713 free(cmd_tbl->pre_cmds);
714 free(cmd_tbl->post_cmds);
715 return 0;
719 if(cmd_tbl->nr_of_cell != 0) {
720 unsigned int cell_cmds_size = cmd_tbl->nr_of_cell * COMMAND_DATA_SIZE;
721 cmd_tbl->cell_cmds = (vm_cmd_t *)malloc(cell_cmds_size);
722 if(!cmd_tbl->cell_cmds) {
723 if(cmd_tbl->pre_cmds)
724 free(cmd_tbl->pre_cmds);
725 if(cmd_tbl->post_cmds)
726 free(cmd_tbl->post_cmds);
727 return 0;
729 if(!(DVDReadBytes(ifofile->file, cmd_tbl->cell_cmds, cell_cmds_size))) {
730 if(cmd_tbl->pre_cmds)
731 free(cmd_tbl->pre_cmds);
732 if(cmd_tbl->post_cmds)
733 free(cmd_tbl->post_cmds);
734 free(cmd_tbl->cell_cmds);
735 return 0;
740 * Make a run over all the commands and see that we can interpret them all?
742 return 1;
746 static void ifoFree_PGC_COMMAND_TBL(pgc_command_tbl_t *cmd_tbl) {
747 if(cmd_tbl) {
748 if(cmd_tbl->nr_of_pre && cmd_tbl->pre_cmds)
749 free(cmd_tbl->pre_cmds);
750 if(cmd_tbl->nr_of_post && cmd_tbl->post_cmds)
751 free(cmd_tbl->post_cmds);
752 if(cmd_tbl->nr_of_cell && cmd_tbl->cell_cmds)
753 free(cmd_tbl->cell_cmds);
754 free(cmd_tbl);
758 static int ifoRead_PGC_PROGRAM_MAP(ifo_handle_t *ifofile,
759 pgc_program_map_t *program_map,
760 unsigned int nr, unsigned int offset) {
761 unsigned int size = nr * sizeof(pgc_program_map_t);
763 if(!DVDFileSeek_(ifofile->file, offset))
764 return 0;
766 if(!(DVDReadBytes(ifofile->file, program_map, size)))
767 return 0;
769 return 1;
772 static int ifoRead_CELL_PLAYBACK_TBL(ifo_handle_t *ifofile,
773 cell_playback_t *cell_playback,
774 unsigned int nr, unsigned int offset) {
775 unsigned int i;
776 unsigned int size = nr * sizeof(cell_playback_t);
778 if(!DVDFileSeek_(ifofile->file, offset))
779 return 0;
781 if(!(DVDReadBytes(ifofile->file, cell_playback, size)))
782 return 0;
784 for(i = 0; i < nr; i++) {
785 read_cell_playback(&cell_playback[i]);
786 /* Changed < to <= because this was false in the movie 'Pi'. */
787 CHECK_VALUE(cell_playback[i].last_vobu_start_sector <=
788 cell_playback[i].last_sector);
789 CHECK_VALUE(cell_playback[i].first_sector <=
790 cell_playback[i].last_vobu_start_sector);
793 return 1;
797 static int ifoRead_CELL_POSITION_TBL(ifo_handle_t *ifofile,
798 cell_position_t *cell_position,
799 unsigned int nr, unsigned int offset) {
800 unsigned int i;
801 unsigned int size = nr * sizeof(cell_position_t);
803 if(!DVDFileSeek_(ifofile->file, offset))
804 return 0;
806 if(!(DVDReadBytes(ifofile->file, cell_position, size)))
807 return 0;
809 for(i = 0; i < nr; i++) {
810 B2N_16(cell_position[i].vob_id_nr);
811 CHECK_ZERO(cell_position[i].zero_1);
814 return 1;
817 static int ifoRead_PGC(ifo_handle_t *ifofile, pgc_t *pgc, unsigned int offset) {
818 unsigned int i;
820 if(!DVDFileSeek_(ifofile->file, offset))
821 return 0;
823 if(!(DVDReadBytes(ifofile->file, pgc, PGC_SIZE)))
824 return 0;
826 read_user_ops(&pgc->prohibited_ops);
827 B2N_16(pgc->next_pgc_nr);
828 B2N_16(pgc->prev_pgc_nr);
829 B2N_16(pgc->goup_pgc_nr);
830 B2N_16(pgc->command_tbl_offset);
831 B2N_16(pgc->program_map_offset);
832 B2N_16(pgc->cell_playback_offset);
833 B2N_16(pgc->cell_position_offset);
835 for(i = 0; i < 8; i++)
836 B2N_16(pgc->audio_control[i]);
837 for(i = 0; i < 32; i++)
838 B2N_32(pgc->subp_control[i]);
839 for(i = 0; i < 16; i++)
840 B2N_32(pgc->palette[i]);
842 CHECK_ZERO(pgc->zero_1);
843 CHECK_VALUE(pgc->nr_of_programs <= pgc->nr_of_cells);
845 /* verify time (look at print_time) */
846 for(i = 0; i < 8; i++)
847 if(!(pgc->audio_control[i] & 0x8000)) /* The 'is present' bit */
848 CHECK_ZERO(pgc->audio_control[i]);
849 for(i = 0; i < 32; i++)
850 if(!(pgc->subp_control[i] & 0x80000000)) /* The 'is present' bit */
851 CHECK_ZERO(pgc->subp_control[i]);
853 /* Check that time is 0:0:0:0 also if nr_of_programs == 0 */
854 if(pgc->nr_of_programs == 0) {
855 CHECK_ZERO(pgc->still_time);
856 CHECK_ZERO(pgc->pg_playback_mode); /* ?? */
857 CHECK_VALUE(pgc->program_map_offset == 0);
858 CHECK_VALUE(pgc->cell_playback_offset == 0);
859 CHECK_VALUE(pgc->cell_position_offset == 0);
860 } else {
861 CHECK_VALUE(pgc->program_map_offset != 0);
862 CHECK_VALUE(pgc->cell_playback_offset != 0);
863 CHECK_VALUE(pgc->cell_position_offset != 0);
866 if(pgc->command_tbl_offset != 0) {
867 pgc->command_tbl = malloc(sizeof(pgc_command_tbl_t));
868 if(!pgc->command_tbl)
869 return 0;
871 if(!ifoRead_PGC_COMMAND_TBL(ifofile, pgc->command_tbl,
872 offset + pgc->command_tbl_offset)) {
873 free(pgc->command_tbl);
874 return 0;
876 } else {
877 pgc->command_tbl = NULL;
880 if(pgc->program_map_offset != 0 && pgc->nr_of_programs>0) {
881 pgc->program_map = malloc(pgc->nr_of_programs * sizeof(pgc_program_map_t));
882 if(!pgc->program_map) {
883 ifoFree_PGC_COMMAND_TBL(pgc->command_tbl);
884 return 0;
886 if(!ifoRead_PGC_PROGRAM_MAP(ifofile, pgc->program_map,pgc->nr_of_programs,
887 offset + pgc->program_map_offset)) {
888 ifoFree_PGC_COMMAND_TBL(pgc->command_tbl);
889 free(pgc->program_map);
890 return 0;
892 } else {
893 pgc->program_map = NULL;
896 if(pgc->cell_playback_offset != 0 && pgc->nr_of_cells>0) {
897 pgc->cell_playback = malloc(pgc->nr_of_cells * sizeof(cell_playback_t));
898 if(!pgc->cell_playback) {
899 ifoFree_PGC_COMMAND_TBL(pgc->command_tbl);
900 if(pgc->program_map)
901 free(pgc->program_map);
902 return 0;
904 if(!ifoRead_CELL_PLAYBACK_TBL(ifofile, pgc->cell_playback,
905 pgc->nr_of_cells,
906 offset + pgc->cell_playback_offset)) {
907 ifoFree_PGC_COMMAND_TBL(pgc->command_tbl);
908 if(pgc->program_map)
909 free(pgc->program_map);
910 free(pgc->cell_playback);
911 return 0;
913 } else {
914 pgc->cell_playback = NULL;
917 if(pgc->cell_position_offset != 0 && pgc->nr_of_cells>0) {
918 pgc->cell_position = malloc(pgc->nr_of_cells * sizeof(cell_position_t));
919 if(!pgc->cell_position) {
920 ifoFree_PGC(pgc);
921 return 0;
923 if(!ifoRead_CELL_POSITION_TBL(ifofile, pgc->cell_position,
924 pgc->nr_of_cells,
925 offset + pgc->cell_position_offset)) {
926 ifoFree_PGC(pgc);
927 return 0;
929 } else {
930 pgc->cell_position = NULL;
933 return 1;
936 int ifoRead_FP_PGC(ifo_handle_t *ifofile) {
938 if(!ifofile)
939 return 0;
941 if(!ifofile->vmgi_mat)
942 return 0;
944 /* It seems that first_play_pgc is optional after all. */
945 ifofile->first_play_pgc = 0;
946 if(ifofile->vmgi_mat->first_play_pgc == 0)
947 return 1;
949 ifofile->first_play_pgc = (pgc_t *)malloc(sizeof(pgc_t));
950 if(!ifofile->first_play_pgc)
951 return 0;
953 if(!ifoRead_PGC(ifofile, ifofile->first_play_pgc,
954 ifofile->vmgi_mat->first_play_pgc)) {
955 free(ifofile->first_play_pgc);
956 ifofile->first_play_pgc = 0;
957 return 0;
960 return 1;
963 static void ifoFree_PGC(pgc_t *pgc) {
964 if(pgc) {
965 ifoFree_PGC_COMMAND_TBL(pgc->command_tbl);
966 if(pgc->program_map)
967 free(pgc->program_map);
968 if(pgc->cell_playback)
969 free(pgc->cell_playback);
970 if(pgc->cell_position)
971 free(pgc->cell_position);
975 void ifoFree_FP_PGC(ifo_handle_t *ifofile) {
976 if(!ifofile)
977 return;
979 if(ifofile->first_play_pgc) {
980 ifoFree_PGC(ifofile->first_play_pgc);
981 free(ifofile->first_play_pgc);
982 ifofile->first_play_pgc = 0;
987 int ifoRead_TT_SRPT(ifo_handle_t *ifofile) {
988 tt_srpt_t *tt_srpt;
989 int i, info_length;
991 if(!ifofile)
992 return 0;
994 if(!ifofile->vmgi_mat)
995 return 0;
997 if(ifofile->vmgi_mat->tt_srpt == 0) /* mandatory */
998 return 0;
1000 if(!DVDFileSeek_(ifofile->file, ifofile->vmgi_mat->tt_srpt * DVD_BLOCK_LEN))
1001 return 0;
1003 tt_srpt = (tt_srpt_t *)malloc(sizeof(tt_srpt_t));
1004 if(!tt_srpt)
1005 return 0;
1007 ifofile->tt_srpt = tt_srpt;
1009 if(!(DVDReadBytes(ifofile->file, tt_srpt, TT_SRPT_SIZE))) {
1010 fprintf(stderr, "libdvdread: Unable to read read TT_SRPT.\n");
1011 free(tt_srpt);
1012 return 0;
1015 B2N_16(tt_srpt->nr_of_srpts);
1016 B2N_32(tt_srpt->last_byte);
1018 info_length = tt_srpt->last_byte + 1 - TT_SRPT_SIZE;
1020 tt_srpt->title = (title_info_t *)malloc(info_length);
1021 if(!tt_srpt->title) {
1022 free(tt_srpt);
1023 ifofile->tt_srpt = 0;
1024 return 0;
1026 if(!(DVDReadBytes(ifofile->file, tt_srpt->title, info_length))) {
1027 fprintf(stderr, "libdvdread: Unable to read read TT_SRPT.\n");
1028 ifoFree_TT_SRPT(ifofile);
1029 return 0;
1032 for(i = 0; i < tt_srpt->nr_of_srpts; i++) {
1033 B2N_16(tt_srpt->title[i].nr_of_ptts);
1034 B2N_16(tt_srpt->title[i].parental_id);
1035 B2N_32(tt_srpt->title[i].title_set_sector);
1039 CHECK_ZERO(tt_srpt->zero_1);
1040 CHECK_VALUE(tt_srpt->nr_of_srpts != 0);
1041 CHECK_VALUE(tt_srpt->nr_of_srpts < 100); /* ?? */
1042 CHECK_VALUE((int)tt_srpt->nr_of_srpts * sizeof(title_info_t) <= info_length);
1044 for(i = 0; i < tt_srpt->nr_of_srpts; i++) {
1045 read_playback_type(&tt_srpt->title[i].pb_ty);
1046 CHECK_VALUE(tt_srpt->title[i].pb_ty.zero_1 == 0);
1047 CHECK_VALUE(tt_srpt->title[i].nr_of_angles != 0);
1048 CHECK_VALUE(tt_srpt->title[i].nr_of_angles < 10);
1049 /* CHECK_VALUE(tt_srpt->title[i].nr_of_ptts != 0); */
1050 /* XXX: this assertion breaks Ghostbusters: */
1051 CHECK_VALUE(tt_srpt->title[i].nr_of_ptts < 1000); /* ?? */
1052 CHECK_VALUE(tt_srpt->title[i].title_set_nr != 0);
1053 CHECK_VALUE(tt_srpt->title[i].title_set_nr < 100); /* ?? */
1054 CHECK_VALUE(tt_srpt->title[i].vts_ttn != 0);
1055 CHECK_VALUE(tt_srpt->title[i].vts_ttn < 100); /* ?? */
1056 /* CHECK_VALUE(tt_srpt->title[i].title_set_sector != 0); */
1059 /* Make this a function */
1060 #if 0
1061 if(memcmp((uint8_t *)tt_srpt->title +
1062 tt_srpt->nr_of_srpts * sizeof(title_info_t),
1063 my_friendly_zeros,
1064 info_length - tt_srpt->nr_of_srpts * sizeof(title_info_t))) {
1065 fprintf(stderr, "VMG_PTT_SRPT slack is != 0, ");
1066 hexdump((uint8_t *)tt_srpt->title +
1067 tt_srpt->nr_of_srpts * sizeof(title_info_t),
1068 info_length - tt_srpt->nr_of_srpts * sizeof(title_info_t));
1070 #endif
1072 return 1;
1076 void ifoFree_TT_SRPT(ifo_handle_t *ifofile) {
1077 if(!ifofile)
1078 return;
1080 if(ifofile->tt_srpt) {
1081 free(ifofile->tt_srpt->title);
1082 free(ifofile->tt_srpt);
1083 ifofile->tt_srpt = 0;
1088 int ifoRead_VTS_PTT_SRPT(ifo_handle_t *ifofile) {
1089 vts_ptt_srpt_t *vts_ptt_srpt;
1090 int info_length, i, j;
1091 uint32_t *data;
1093 if(!ifofile)
1094 return 0;
1096 if(!ifofile->vtsi_mat)
1097 return 0;
1099 if(ifofile->vtsi_mat->vts_ptt_srpt == 0) /* mandatory */
1100 return 0;
1102 if(!DVDFileSeek_(ifofile->file,
1103 ifofile->vtsi_mat->vts_ptt_srpt * DVD_BLOCK_LEN))
1104 return 0;
1106 vts_ptt_srpt = (vts_ptt_srpt_t *)malloc(sizeof(vts_ptt_srpt_t));
1107 if(!vts_ptt_srpt)
1108 return 0;
1110 ifofile->vts_ptt_srpt = vts_ptt_srpt;
1112 if(!(DVDReadBytes(ifofile->file, vts_ptt_srpt, VTS_PTT_SRPT_SIZE))) {
1113 fprintf(stderr, "libdvdread: Unable to read PTT search table.\n");
1114 free(vts_ptt_srpt);
1115 return 0;
1118 B2N_16(vts_ptt_srpt->nr_of_srpts);
1119 B2N_32(vts_ptt_srpt->last_byte);
1121 CHECK_ZERO(vts_ptt_srpt->zero_1);
1122 CHECK_VALUE(vts_ptt_srpt->nr_of_srpts != 0);
1123 CHECK_VALUE(vts_ptt_srpt->nr_of_srpts < 100); /* ?? */
1125 info_length = vts_ptt_srpt->last_byte + 1 - VTS_PTT_SRPT_SIZE;
1127 data = (uint32_t *)malloc(info_length);
1128 if(!data) {
1129 free(vts_ptt_srpt);
1130 ifofile->vts_ptt_srpt = 0;
1131 return 0;
1133 if(!(DVDReadBytes(ifofile->file, data, info_length))) {
1134 fprintf(stderr, "libdvdread: Unable to read PTT search table.\n");
1135 free(vts_ptt_srpt);
1136 free(data);
1137 ifofile->vts_ptt_srpt = 0;
1138 return 0;
1141 for(i = 0; i < vts_ptt_srpt->nr_of_srpts; i++) {
1142 B2N_32(data[i]);
1143 /* assert(data[i] + sizeof(ptt_info_t) <= vts_ptt_srpt->last_byte + 1);
1144 Magic Knight Rayearth Daybreak is mastered very strange and has
1145 Titles with 0 PTTs. They all have a data[i] offsets beyond the end of
1146 of the vts_ptt_srpt structure. */
1147 CHECK_VALUE(data[i] + sizeof(ptt_info_t) <= vts_ptt_srpt->last_byte + 1 + 4);
1150 vts_ptt_srpt->ttu_offset = data;
1152 vts_ptt_srpt->title = malloc(vts_ptt_srpt->nr_of_srpts * sizeof(ttu_t));
1153 if(!vts_ptt_srpt->title) {
1154 free(vts_ptt_srpt);
1155 free(data);
1156 ifofile->vts_ptt_srpt = 0;
1157 return 0;
1159 for(i = 0; i < vts_ptt_srpt->nr_of_srpts; i++) {
1160 int n;
1161 if(i < vts_ptt_srpt->nr_of_srpts - 1)
1162 n = (data[i+1] - data[i]);
1163 else
1164 n = (vts_ptt_srpt->last_byte + 1 - data[i]);
1165 /* assert(n > 0 && (n % 4) == 0);
1166 Magic Knight Rayearth Daybreak is mastered very strange and has
1167 Titles with 0 PTTs. */
1168 if(n < 0) n = 0;
1169 CHECK_VALUE(n % 4 == 0);
1171 vts_ptt_srpt->title[i].nr_of_ptts = n / 4;
1172 vts_ptt_srpt->title[i].ptt = malloc(n * sizeof(ptt_info_t));
1173 if(!vts_ptt_srpt->title[i].ptt) {
1174 for(n = 0; n < i; n++)
1175 free(vts_ptt_srpt->title[n].ptt);
1176 free(vts_ptt_srpt);
1177 free(data);
1178 ifofile->vts_ptt_srpt = 0;
1179 return 0;
1181 for(j = 0; j < vts_ptt_srpt->title[i].nr_of_ptts; j++) {
1182 /* The assert placed here because of Magic Knight Rayearth Daybreak */
1183 CHECK_VALUE(data[i] + sizeof(ptt_info_t) <= vts_ptt_srpt->last_byte + 1);
1184 vts_ptt_srpt->title[i].ptt[j].pgcn
1185 = *(uint16_t*)(((char *)data) + data[i] + 4*j - VTS_PTT_SRPT_SIZE);
1186 vts_ptt_srpt->title[i].ptt[j].pgn
1187 = *(uint16_t*)(((char *)data) + data[i] + 4*j + 2 - VTS_PTT_SRPT_SIZE);
1191 for(i = 0; i < vts_ptt_srpt->nr_of_srpts; i++) {
1192 for(j = 0; j < vts_ptt_srpt->title[i].nr_of_ptts; j++) {
1193 B2N_16(vts_ptt_srpt->title[i].ptt[j].pgcn);
1194 B2N_16(vts_ptt_srpt->title[i].ptt[j].pgn);
1198 for(i = 0; i < vts_ptt_srpt->nr_of_srpts; i++) {
1199 CHECK_VALUE(vts_ptt_srpt->title[i].nr_of_ptts < 1000); /* ?? */
1200 for(j = 0; j < vts_ptt_srpt->title[i].nr_of_ptts; j++) {
1201 CHECK_VALUE(vts_ptt_srpt->title[i].ptt[j].pgcn != 0 );
1202 CHECK_VALUE(vts_ptt_srpt->title[i].ptt[j].pgcn < 1000); /* ?? */
1203 CHECK_VALUE(vts_ptt_srpt->title[i].ptt[j].pgn != 0);
1204 CHECK_VALUE(vts_ptt_srpt->title[i].ptt[j].pgn < 100); /* ?? */
1208 return 1;
1212 void ifoFree_VTS_PTT_SRPT(ifo_handle_t *ifofile) {
1213 if(!ifofile)
1214 return;
1216 if(ifofile->vts_ptt_srpt) {
1217 int i;
1218 for(i = 0; i < ifofile->vts_ptt_srpt->nr_of_srpts; i++)
1219 free(ifofile->vts_ptt_srpt->title[i].ptt);
1220 free(ifofile->vts_ptt_srpt->ttu_offset);
1221 free(ifofile->vts_ptt_srpt->title);
1222 free(ifofile->vts_ptt_srpt);
1223 ifofile->vts_ptt_srpt = 0;
1228 int ifoRead_PTL_MAIT(ifo_handle_t *ifofile) {
1229 ptl_mait_t *ptl_mait;
1230 int info_length;
1231 unsigned int i, j;
1233 if(!ifofile)
1234 return 0;
1236 if(!ifofile->vmgi_mat)
1237 return 0;
1239 if(ifofile->vmgi_mat->ptl_mait == 0)
1240 return 1;
1242 if(!DVDFileSeek_(ifofile->file, ifofile->vmgi_mat->ptl_mait * DVD_BLOCK_LEN))
1243 return 0;
1245 ptl_mait = (ptl_mait_t *)malloc(sizeof(ptl_mait_t));
1246 if(!ptl_mait)
1247 return 0;
1249 ifofile->ptl_mait = ptl_mait;
1251 if(!(DVDReadBytes(ifofile->file, ptl_mait, PTL_MAIT_SIZE))) {
1252 free(ptl_mait);
1253 ifofile->ptl_mait = 0;
1254 return 0;
1257 B2N_16(ptl_mait->nr_of_countries);
1258 B2N_16(ptl_mait->nr_of_vtss);
1259 B2N_32(ptl_mait->last_byte);
1261 CHECK_VALUE(ptl_mait->nr_of_countries != 0);
1262 CHECK_VALUE(ptl_mait->nr_of_countries < 100); /* ?? */
1263 CHECK_VALUE(ptl_mait->nr_of_vtss != 0);
1264 CHECK_VALUE(ptl_mait->nr_of_vtss < 100); /* ?? */
1265 CHECK_VALUE(ptl_mait->nr_of_countries * PTL_MAIT_COUNTRY_SIZE
1266 <= ptl_mait->last_byte + 1 - PTL_MAIT_SIZE);
1268 info_length = ptl_mait->nr_of_countries * sizeof(ptl_mait_country_t);
1269 ptl_mait->countries = (ptl_mait_country_t *)malloc(info_length);
1270 if(!ptl_mait->countries) {
1271 free(ptl_mait);
1272 ifofile->ptl_mait = 0;
1273 return 0;
1276 for(i = 0; i < ptl_mait->nr_of_countries; i++) {
1277 if(!(DVDReadBytes(ifofile->file, &ptl_mait->countries[i], PTL_MAIT_COUNTRY_SIZE))) {
1278 fprintf(stderr, "libdvdread: Unable to read PTL_MAIT.\n");
1279 free(ptl_mait->countries);
1280 free(ptl_mait);
1281 ifofile->ptl_mait = 0;
1282 return 0;
1286 for(i = 0; i < ptl_mait->nr_of_countries; i++) {
1287 B2N_16(ptl_mait->countries[i].country_code);
1288 B2N_16(ptl_mait->countries[i].pf_ptl_mai_start_byte);
1291 for(i = 0; i < ptl_mait->nr_of_countries; i++) {
1292 CHECK_ZERO(ptl_mait->countries[i].zero_1);
1293 CHECK_ZERO(ptl_mait->countries[i].zero_2);
1294 CHECK_VALUE(ptl_mait->countries[i].pf_ptl_mai_start_byte
1295 + 8*2 * (ptl_mait->nr_of_vtss + 1) <= ptl_mait->last_byte + 1);
1298 for(i = 0; i < ptl_mait->nr_of_countries; i++) {
1299 uint16_t *pf_temp;
1301 if(!DVDFileSeek_(ifofile->file,
1302 ifofile->vmgi_mat->ptl_mait * DVD_BLOCK_LEN
1303 + ptl_mait->countries[i].pf_ptl_mai_start_byte)) {
1304 fprintf(stderr, "libdvdread: Unable to seak PTL_MAIT table.\n");
1305 free(ptl_mait->countries);
1306 free(ptl_mait);
1307 return 0;
1309 info_length = (ptl_mait->nr_of_vtss + 1) * sizeof(pf_level_t);
1310 pf_temp = (uint16_t *)malloc(info_length);
1311 if(!pf_temp) {
1312 free_ptl_mait(ptl_mait, i);
1313 return 0;
1315 if(!(DVDReadBytes(ifofile->file, pf_temp, info_length))) {
1316 fprintf(stderr, "libdvdread: Unable to read PTL_MAIT table.\n");
1317 free(pf_temp);
1318 free_ptl_mait(ptl_mait, i);
1319 return 0;
1321 for (j = 0; j < ((ptl_mait->nr_of_vtss + 1) * 8); j++) {
1322 B2N_16(pf_temp[j]);
1324 ptl_mait->countries[i].pf_ptl_mai = (pf_level_t *)malloc(info_length);
1325 if(!ptl_mait->countries[i].pf_ptl_mai) {
1326 free(pf_temp);
1327 free_ptl_mait(ptl_mait, i);
1328 return 0;
1330 { /* Transpose the array so we can use C indexing. */
1331 int level, vts;
1332 for(level = 0; level < 8; level++) {
1333 for(vts = 0; vts <= ptl_mait->nr_of_vtss; vts++) {
1334 ptl_mait->countries[i].pf_ptl_mai[vts][level] =
1335 pf_temp[(7-level)*(ptl_mait->nr_of_vtss+1) + vts];
1338 free(pf_temp);
1341 return 1;
1344 void ifoFree_PTL_MAIT(ifo_handle_t *ifofile) {
1345 unsigned int i;
1347 if(!ifofile)
1348 return;
1350 if(ifofile->ptl_mait) {
1351 for(i = 0; i < ifofile->ptl_mait->nr_of_countries; i++) {
1352 free(ifofile->ptl_mait->countries[i].pf_ptl_mai);
1354 free(ifofile->ptl_mait->countries);
1355 free(ifofile->ptl_mait);
1356 ifofile->ptl_mait = 0;
1360 int ifoRead_VTS_TMAPT(ifo_handle_t *ifofile) {
1361 vts_tmapt_t *vts_tmapt;
1362 uint32_t *vts_tmap_srp;
1363 unsigned int offset;
1364 int info_length;
1365 unsigned int i, j;
1367 if(!ifofile)
1368 return 0;
1370 if(!ifofile->vtsi_mat)
1371 return 0;
1373 if(ifofile->vtsi_mat->vts_tmapt == 0) { /* optional(?) */
1374 ifofile->vts_tmapt = NULL;
1375 fprintf(stderr,"Please send bug report - no VTS_TMAPT ?? \n");
1376 return 1;
1379 offset = ifofile->vtsi_mat->vts_tmapt * DVD_BLOCK_LEN;
1381 if(!DVDFileSeek_(ifofile->file, offset))
1382 return 0;
1384 vts_tmapt = (vts_tmapt_t *)malloc(sizeof(vts_tmapt_t));
1385 if(!vts_tmapt)
1386 return 0;
1388 ifofile->vts_tmapt = vts_tmapt;
1390 if(!(DVDReadBytes(ifofile->file, vts_tmapt, VTS_TMAPT_SIZE))) {
1391 fprintf(stderr, "libdvdread: Unable to read VTS_TMAPT.\n");
1392 free(vts_tmapt);
1393 ifofile->vts_tmapt = NULL;
1394 return 0;
1397 B2N_16(vts_tmapt->nr_of_tmaps);
1398 B2N_32(vts_tmapt->last_byte);
1400 CHECK_ZERO(vts_tmapt->zero_1);
1402 info_length = vts_tmapt->nr_of_tmaps * 4;
1404 vts_tmap_srp = (uint32_t *)malloc(info_length);
1405 if(!vts_tmap_srp) {
1406 free(vts_tmapt);
1407 ifofile->vts_tmapt = NULL;
1408 return 0;
1411 vts_tmapt->tmap_offset = vts_tmap_srp;
1413 if(!(DVDReadBytes(ifofile->file, vts_tmap_srp, info_length))) {
1414 fprintf(stderr, "libdvdread: Unable to read VTS_TMAPT.\n");
1415 free(vts_tmap_srp);
1416 free(vts_tmapt);
1417 ifofile->vts_tmapt = NULL;
1418 return 0;
1421 for (i = 0; i < vts_tmapt->nr_of_tmaps; i++) {
1422 B2N_32(vts_tmap_srp[i]);
1426 info_length = vts_tmapt->nr_of_tmaps * sizeof(vts_tmap_t);
1428 vts_tmapt->tmap = (vts_tmap_t *)malloc(info_length);
1429 if(!vts_tmapt->tmap) {
1430 free(vts_tmap_srp);
1431 free(vts_tmapt);
1432 ifofile->vts_tmapt = NULL;
1433 return 0;
1436 memset(vts_tmapt->tmap, 0, info_length); /* So ifoFree_VTS_TMAPT works. */
1438 for(i = 0; i < vts_tmapt->nr_of_tmaps; i++) {
1439 if(!DVDFileSeek_(ifofile->file, offset + vts_tmap_srp[i])) {
1440 ifoFree_VTS_TMAPT(ifofile);
1441 return 0;
1444 if(!(DVDReadBytes(ifofile->file, &vts_tmapt->tmap[i], VTS_TMAP_SIZE))) {
1445 fprintf(stderr, "libdvdread: Unable to read VTS_TMAP.\n");
1446 ifoFree_VTS_TMAPT(ifofile);
1447 return 0;
1450 B2N_16(vts_tmapt->tmap[i].nr_of_entries);
1451 CHECK_ZERO(vts_tmapt->tmap[i].zero_1);
1453 if(vts_tmapt->tmap[i].nr_of_entries == 0) { /* Early out if zero entries */
1454 vts_tmapt->tmap[i].map_ent = NULL;
1455 continue;
1458 info_length = vts_tmapt->tmap[i].nr_of_entries * sizeof(map_ent_t);
1460 vts_tmapt->tmap[i].map_ent = (map_ent_t *)malloc(info_length);
1461 if(!vts_tmapt->tmap[i].map_ent) {
1462 ifoFree_VTS_TMAPT(ifofile);
1463 return 0;
1466 if(!(DVDReadBytes(ifofile->file, vts_tmapt->tmap[i].map_ent, info_length))) {
1467 fprintf(stderr, "libdvdread: Unable to read VTS_TMAP_ENT.\n");
1468 ifoFree_VTS_TMAPT(ifofile);
1469 return 0;
1472 for(j = 0; j < vts_tmapt->tmap[i].nr_of_entries; j++)
1473 B2N_32(vts_tmapt->tmap[i].map_ent[j]);
1476 return 1;
1479 void ifoFree_VTS_TMAPT(ifo_handle_t *ifofile) {
1480 unsigned int i;
1482 if(!ifofile)
1483 return;
1485 if(ifofile->vts_tmapt) {
1486 for(i = 0; i < ifofile->vts_tmapt->nr_of_tmaps; i++)
1487 if(ifofile->vts_tmapt->tmap[i].map_ent)
1488 free(ifofile->vts_tmapt->tmap[i].map_ent);
1489 free(ifofile->vts_tmapt->tmap);
1490 free(ifofile->vts_tmapt->tmap_offset);
1491 free(ifofile->vts_tmapt);
1492 ifofile->vts_tmapt = NULL;
1497 int ifoRead_TITLE_C_ADT(ifo_handle_t *ifofile) {
1499 if(!ifofile)
1500 return 0;
1502 if(!ifofile->vtsi_mat)
1503 return 0;
1505 if(ifofile->vtsi_mat->vts_c_adt == 0) /* mandatory */
1506 return 0;
1508 ifofile->vts_c_adt = (c_adt_t *)malloc(sizeof(c_adt_t));
1509 if(!ifofile->vts_c_adt)
1510 return 0;
1512 if(!ifoRead_C_ADT_internal(ifofile, ifofile->vts_c_adt,
1513 ifofile->vtsi_mat->vts_c_adt)) {
1514 free(ifofile->vts_c_adt);
1515 ifofile->vts_c_adt = 0;
1516 return 0;
1519 return 1;
1522 int ifoRead_C_ADT(ifo_handle_t *ifofile) {
1523 unsigned int sector;
1525 if(!ifofile)
1526 return 0;
1528 if(ifofile->vmgi_mat) {
1529 if(ifofile->vmgi_mat->vmgm_c_adt == 0)
1530 return 1;
1531 sector = ifofile->vmgi_mat->vmgm_c_adt;
1532 } else if(ifofile->vtsi_mat) {
1533 if(ifofile->vtsi_mat->vtsm_c_adt == 0)
1534 return 1;
1535 sector = ifofile->vtsi_mat->vtsm_c_adt;
1536 } else {
1537 return 0;
1540 ifofile->menu_c_adt = (c_adt_t *)malloc(sizeof(c_adt_t));
1541 if(!ifofile->menu_c_adt)
1542 return 0;
1544 if(!ifoRead_C_ADT_internal(ifofile, ifofile->menu_c_adt, sector)) {
1545 free(ifofile->menu_c_adt);
1546 ifofile->menu_c_adt = 0;
1547 return 0;
1550 return 1;
1553 static int ifoRead_C_ADT_internal(ifo_handle_t *ifofile,
1554 c_adt_t *c_adt, unsigned int sector) {
1555 int i, info_length;
1557 if(!DVDFileSeek_(ifofile->file, sector * DVD_BLOCK_LEN))
1558 return 0;
1560 if(!(DVDReadBytes(ifofile->file, c_adt, C_ADT_SIZE)))
1561 return 0;
1563 B2N_16(c_adt->nr_of_vobs);
1564 B2N_32(c_adt->last_byte);
1566 info_length = c_adt->last_byte + 1 - C_ADT_SIZE;
1568 CHECK_ZERO(c_adt->zero_1);
1569 /* assert(c_adt->nr_of_vobs > 0);
1570 Magic Knight Rayearth Daybreak is mastered very strange and has
1571 Titles with a VOBS that has no cells. */
1572 CHECK_VALUE(info_length % sizeof(cell_adr_t) == 0);
1574 /* assert(info_length / sizeof(cell_adr_t) >= c_adt->nr_of_vobs);
1575 Enemy of the State region 2 (de) has Titles where nr_of_vobs field
1576 is to high, they high ones are never referenced though. */
1577 if(info_length / sizeof(cell_adr_t) < c_adt->nr_of_vobs) {
1578 fprintf(stderr, "libdvdread: *C_ADT nr_of_vobs > avaiable info entries\n");
1579 c_adt->nr_of_vobs = info_length / sizeof(cell_adr_t);
1582 c_adt->cell_adr_table = (cell_adr_t *)malloc(info_length);
1583 if(!c_adt->cell_adr_table)
1584 return 0;
1586 if(info_length &&
1587 !(DVDReadBytes(ifofile->file, c_adt->cell_adr_table, info_length))) {
1588 free(c_adt->cell_adr_table);
1589 return 0;
1592 for(i = 0; i < info_length/sizeof(cell_adr_t); i++) {
1593 B2N_16(c_adt->cell_adr_table[i].vob_id);
1594 B2N_32(c_adt->cell_adr_table[i].start_sector);
1595 B2N_32(c_adt->cell_adr_table[i].last_sector);
1597 CHECK_ZERO(c_adt->cell_adr_table[i].zero_1);
1598 CHECK_VALUE(c_adt->cell_adr_table[i].vob_id > 0);
1599 CHECK_VALUE(c_adt->cell_adr_table[i].vob_id <= c_adt->nr_of_vobs);
1600 CHECK_VALUE(c_adt->cell_adr_table[i].cell_id > 0);
1601 CHECK_VALUE(c_adt->cell_adr_table[i].start_sector <
1602 c_adt->cell_adr_table[i].last_sector);
1605 return 1;
1609 static void ifoFree_C_ADT_internal(c_adt_t *c_adt) {
1610 if(c_adt) {
1611 free(c_adt->cell_adr_table);
1612 free(c_adt);
1616 void ifoFree_C_ADT(ifo_handle_t *ifofile) {
1617 if(!ifofile)
1618 return;
1620 ifoFree_C_ADT_internal(ifofile->menu_c_adt);
1621 ifofile->menu_c_adt = 0;
1624 void ifoFree_TITLE_C_ADT(ifo_handle_t *ifofile) {
1625 if(!ifofile)
1626 return;
1628 ifoFree_C_ADT_internal(ifofile->vts_c_adt);
1629 ifofile->vts_c_adt = 0;
1632 int ifoRead_TITLE_VOBU_ADMAP(ifo_handle_t *ifofile) {
1633 if(!ifofile)
1634 return 0;
1636 if(!ifofile->vtsi_mat)
1637 return 0;
1639 if(ifofile->vtsi_mat->vts_vobu_admap == 0) /* mandatory */
1640 return 0;
1642 ifofile->vts_vobu_admap = (vobu_admap_t *)malloc(sizeof(vobu_admap_t));
1643 if(!ifofile->vts_vobu_admap)
1644 return 0;
1646 if(!ifoRead_VOBU_ADMAP_internal(ifofile, ifofile->vts_vobu_admap,
1647 ifofile->vtsi_mat->vts_vobu_admap)) {
1648 free(ifofile->vts_vobu_admap);
1649 ifofile->vts_vobu_admap = 0;
1650 return 0;
1653 return 1;
1656 int ifoRead_VOBU_ADMAP(ifo_handle_t *ifofile) {
1657 unsigned int sector;
1659 if(!ifofile)
1660 return 0;
1662 if(ifofile->vmgi_mat) {
1663 if(ifofile->vmgi_mat->vmgm_vobu_admap == 0)
1664 return 1;
1665 sector = ifofile->vmgi_mat->vmgm_vobu_admap;
1666 } else if(ifofile->vtsi_mat) {
1667 if(ifofile->vtsi_mat->vtsm_vobu_admap == 0)
1668 return 1;
1669 sector = ifofile->vtsi_mat->vtsm_vobu_admap;
1670 } else {
1671 return 0;
1674 ifofile->menu_vobu_admap = (vobu_admap_t *)malloc(sizeof(vobu_admap_t));
1675 if(!ifofile->menu_vobu_admap)
1676 return 0;
1678 if(!ifoRead_VOBU_ADMAP_internal(ifofile, ifofile->menu_vobu_admap, sector)) {
1679 free(ifofile->menu_vobu_admap);
1680 ifofile->menu_vobu_admap = 0;
1681 return 0;
1684 return 1;
1687 static int ifoRead_VOBU_ADMAP_internal(ifo_handle_t *ifofile,
1688 vobu_admap_t *vobu_admap,
1689 unsigned int sector) {
1690 unsigned int i;
1691 int info_length;
1693 if(!DVDFileSeekForce_(ifofile->file, sector * DVD_BLOCK_LEN, sector))
1694 return 0;
1696 if(!(DVDReadBytes(ifofile->file, vobu_admap, VOBU_ADMAP_SIZE)))
1697 return 0;
1699 B2N_32(vobu_admap->last_byte);
1701 info_length = vobu_admap->last_byte + 1 - VOBU_ADMAP_SIZE;
1702 /* assert(info_length > 0);
1703 Magic Knight Rayearth Daybreak is mastered very strange and has
1704 Titles with a VOBS that has no VOBUs. */
1705 CHECK_VALUE(info_length % sizeof(uint32_t) == 0);
1707 vobu_admap->vobu_start_sectors = (uint32_t *)malloc(info_length);
1708 if(!vobu_admap->vobu_start_sectors) {
1709 return 0;
1711 if(info_length &&
1712 !(DVDReadBytes(ifofile->file,
1713 vobu_admap->vobu_start_sectors, info_length))) {
1714 free(vobu_admap->vobu_start_sectors);
1715 return 0;
1718 for(i = 0; i < info_length/sizeof(uint32_t); i++)
1719 B2N_32(vobu_admap->vobu_start_sectors[i]);
1721 return 1;
1725 static void ifoFree_VOBU_ADMAP_internal(vobu_admap_t *vobu_admap) {
1726 if(vobu_admap) {
1727 free(vobu_admap->vobu_start_sectors);
1728 free(vobu_admap);
1732 void ifoFree_VOBU_ADMAP(ifo_handle_t *ifofile) {
1733 if(!ifofile)
1734 return;
1736 ifoFree_VOBU_ADMAP_internal(ifofile->menu_vobu_admap);
1737 ifofile->menu_vobu_admap = 0;
1740 void ifoFree_TITLE_VOBU_ADMAP(ifo_handle_t *ifofile) {
1741 if(!ifofile)
1742 return;
1744 ifoFree_VOBU_ADMAP_internal(ifofile->vts_vobu_admap);
1745 ifofile->vts_vobu_admap = 0;
1748 int ifoRead_PGCIT(ifo_handle_t *ifofile) {
1750 if(!ifofile)
1751 return 0;
1753 if(!ifofile->vtsi_mat)
1754 return 0;
1756 if(ifofile->vtsi_mat->vts_pgcit == 0) /* mandatory */
1757 return 0;
1759 ifofile->vts_pgcit = (pgcit_t *)malloc(sizeof(pgcit_t));
1760 if(!ifofile->vts_pgcit)
1761 return 0;
1763 if(!ifoRead_PGCIT_internal(ifofile, ifofile->vts_pgcit,
1764 ifofile->vtsi_mat->vts_pgcit * DVD_BLOCK_LEN)) {
1765 free(ifofile->vts_pgcit);
1766 ifofile->vts_pgcit = 0;
1767 return 0;
1770 return 1;
1773 static int ifoRead_PGCIT_internal(ifo_handle_t *ifofile, pgcit_t *pgcit,
1774 unsigned int offset) {
1775 int i, info_length;
1776 uint8_t *data, *ptr;
1778 if(!DVDFileSeek_(ifofile->file, offset))
1779 return 0;
1781 if(!(DVDReadBytes(ifofile->file, pgcit, PGCIT_SIZE)))
1782 return 0;
1784 B2N_16(pgcit->nr_of_pgci_srp);
1785 B2N_32(pgcit->last_byte);
1787 CHECK_ZERO(pgcit->zero_1);
1788 /* assert(pgcit->nr_of_pgci_srp != 0);
1789 Magic Knight Rayearth Daybreak is mastered very strange and has
1790 Titles with 0 PTTs. */
1791 CHECK_VALUE(pgcit->nr_of_pgci_srp < 10000); /* ?? seen max of 1338 */
1793 info_length = pgcit->nr_of_pgci_srp * PGCI_SRP_SIZE;
1794 data = malloc(info_length);
1795 if(!data)
1796 return 0;
1798 if(info_length && !(DVDReadBytes(ifofile->file, data, info_length))) {
1799 free(data);
1800 return 0;
1803 pgcit->pgci_srp = malloc(pgcit->nr_of_pgci_srp * sizeof(pgci_srp_t));
1804 if(!pgcit->pgci_srp) {
1805 free(data);
1806 return 0;
1808 ptr = data;
1809 for(i = 0; i < pgcit->nr_of_pgci_srp; i++) {
1810 memcpy(&pgcit->pgci_srp[i], ptr, PGCI_SRP_SIZE);
1811 ptr += PGCI_SRP_SIZE;
1812 read_pgci_srp(&pgcit->pgci_srp[i]);
1813 CHECK_VALUE(pgcit->pgci_srp[i].unknown1 == 0);
1815 free(data);
1817 for(i = 0; i < pgcit->nr_of_pgci_srp; i++)
1818 CHECK_VALUE(pgcit->pgci_srp[i].pgc_start_byte + PGC_SIZE <= pgcit->last_byte+1);
1820 for(i = 0; i < pgcit->nr_of_pgci_srp; i++) {
1821 pgcit->pgci_srp[i].pgc = malloc(sizeof(pgc_t));
1822 if(!pgcit->pgci_srp[i].pgc) {
1823 int j;
1824 for(j = 0; j < i; j++) {
1825 ifoFree_PGC(pgcit->pgci_srp[j].pgc);
1826 free(pgcit->pgci_srp[j].pgc);
1828 goto fail;
1830 if(!ifoRead_PGC(ifofile, pgcit->pgci_srp[i].pgc,
1831 offset + pgcit->pgci_srp[i].pgc_start_byte)) {
1832 int j;
1833 for(j = 0; j < i; j++) {
1834 ifoFree_PGC(pgcit->pgci_srp[j].pgc);
1835 free(pgcit->pgci_srp[j].pgc);
1837 goto fail;
1841 return 1;
1842 fail:
1843 free(pgcit->pgci_srp);
1844 pgcit->pgci_srp = NULL;
1845 return 0;
1848 static void ifoFree_PGCIT_internal(pgcit_t *pgcit) {
1849 if(pgcit) {
1850 int i;
1851 for(i = 0; i < pgcit->nr_of_pgci_srp; i++)
1852 ifoFree_PGC(pgcit->pgci_srp[i].pgc);
1853 free(pgcit->pgci_srp);
1857 void ifoFree_PGCIT(ifo_handle_t *ifofile) {
1858 if(!ifofile)
1859 return;
1861 if(ifofile->vts_pgcit) {
1862 ifoFree_PGCIT_internal(ifofile->vts_pgcit);
1863 free(ifofile->vts_pgcit);
1864 ifofile->vts_pgcit = 0;
1869 int ifoRead_PGCI_UT(ifo_handle_t *ifofile) {
1870 pgci_ut_t *pgci_ut;
1871 unsigned int sector;
1872 unsigned int i;
1873 int info_length;
1874 uint8_t *data, *ptr;
1876 if(!ifofile)
1877 return 0;
1879 if(ifofile->vmgi_mat) {
1880 if(ifofile->vmgi_mat->vmgm_pgci_ut == 0)
1881 return 1;
1882 sector = ifofile->vmgi_mat->vmgm_pgci_ut;
1883 } else if(ifofile->vtsi_mat) {
1884 if(ifofile->vtsi_mat->vtsm_pgci_ut == 0)
1885 return 1;
1886 sector = ifofile->vtsi_mat->vtsm_pgci_ut;
1887 } else {
1888 return 0;
1891 ifofile->pgci_ut = (pgci_ut_t *)malloc(sizeof(pgci_ut_t));
1892 if(!ifofile->pgci_ut)
1893 return 0;
1895 if(!DVDFileSeek_(ifofile->file, sector * DVD_BLOCK_LEN)) {
1896 free(ifofile->pgci_ut);
1897 ifofile->pgci_ut = 0;
1898 return 0;
1901 if(!(DVDReadBytes(ifofile->file, ifofile->pgci_ut, PGCI_UT_SIZE))) {
1902 free(ifofile->pgci_ut);
1903 ifofile->pgci_ut = 0;
1904 return 0;
1907 pgci_ut = ifofile->pgci_ut;
1909 B2N_16(pgci_ut->nr_of_lus);
1910 B2N_32(pgci_ut->last_byte);
1912 CHECK_ZERO(pgci_ut->zero_1);
1913 CHECK_VALUE(pgci_ut->nr_of_lus != 0);
1914 CHECK_VALUE(pgci_ut->nr_of_lus < 100); /* ?? 3-4 ? */
1915 CHECK_VALUE((uint32_t)pgci_ut->nr_of_lus * PGCI_LU_SIZE < pgci_ut->last_byte);
1917 info_length = pgci_ut->nr_of_lus * PGCI_LU_SIZE;
1918 data = malloc(info_length);
1919 if(!data) {
1920 free(pgci_ut);
1921 ifofile->pgci_ut = 0;
1922 return 0;
1924 if(!(DVDReadBytes(ifofile->file, data, info_length))) {
1925 free(data);
1926 free(pgci_ut);
1927 ifofile->pgci_ut = 0;
1928 return 0;
1931 pgci_ut->lu = malloc(pgci_ut->nr_of_lus * sizeof(pgci_lu_t));
1932 if(!pgci_ut->lu) {
1933 free(data);
1934 free(pgci_ut);
1935 ifofile->pgci_ut = 0;
1936 return 0;
1938 ptr = data;
1939 for(i = 0; i < pgci_ut->nr_of_lus; i++) {
1940 memcpy(&pgci_ut->lu[i], ptr, PGCI_LU_SIZE);
1941 ptr += PGCI_LU_SIZE;
1942 B2N_16(pgci_ut->lu[i].lang_code);
1943 B2N_32(pgci_ut->lu[i].lang_start_byte);
1945 free(data);
1947 for(i = 0; i < pgci_ut->nr_of_lus; i++) {
1948 /* Maybe this is only defined for v1.1 and later titles? */
1949 /* If the bits in 'lu[i].exists' are enumerated abcd efgh then:
1950 VTS_x_yy.IFO VIDEO_TS.IFO
1951 a == 0x83 "Root" 0x82 "Title"
1952 b == 0x84 "Subpicture"
1953 c == 0x85 "Audio"
1954 d == 0x86 "Angle"
1955 e == 0x87 "PTT"
1957 CHECK_VALUE((pgci_ut->lu[i].exists & 0x07) == 0);
1960 for(i = 0; i < pgci_ut->nr_of_lus; i++) {
1961 pgci_ut->lu[i].pgcit = malloc(sizeof(pgcit_t));
1962 if(!pgci_ut->lu[i].pgcit) {
1963 unsigned int j;
1964 for(j = 0; j < i; j++) {
1965 ifoFree_PGCIT_internal(pgci_ut->lu[j].pgcit);
1966 free(pgci_ut->lu[j].pgcit);
1968 free(pgci_ut->lu);
1969 free(pgci_ut);
1970 ifofile->pgci_ut = 0;
1971 return 0;
1973 if(!ifoRead_PGCIT_internal(ifofile, pgci_ut->lu[i].pgcit,
1974 sector * DVD_BLOCK_LEN
1975 + pgci_ut->lu[i].lang_start_byte)) {
1976 unsigned int j;
1977 for(j = 0; j < i; j++) {
1978 ifoFree_PGCIT_internal(pgci_ut->lu[j].pgcit);
1979 free(pgci_ut->lu[j].pgcit);
1981 free(pgci_ut->lu[i].pgcit);
1982 free(pgci_ut->lu);
1983 free(pgci_ut);
1984 ifofile->pgci_ut = 0;
1985 return 0;
1987 /* FIXME: Iterate and verify that all menus that should exists accordingly
1988 * to pgci_ut->lu[i].exists really do? */
1991 return 1;
1995 void ifoFree_PGCI_UT(ifo_handle_t *ifofile) {
1996 unsigned int i;
1998 if(!ifofile)
1999 return;
2001 if(ifofile->pgci_ut) {
2002 for(i = 0; i < ifofile->pgci_ut->nr_of_lus; i++) {
2003 ifoFree_PGCIT_internal(ifofile->pgci_ut->lu[i].pgcit);
2004 free(ifofile->pgci_ut->lu[i].pgcit);
2006 free(ifofile->pgci_ut->lu);
2007 free(ifofile->pgci_ut);
2008 ifofile->pgci_ut = 0;
2012 static int ifoRead_VTS_ATTRIBUTES(ifo_handle_t *ifofile,
2013 vts_attributes_t *vts_attributes,
2014 unsigned int offset) {
2015 unsigned int i;
2017 if(!DVDFileSeek_(ifofile->file, offset))
2018 return 0;
2020 if(!(DVDReadBytes(ifofile->file, vts_attributes, sizeof(vts_attributes_t))))
2021 return 0;
2023 read_video_attr(&vts_attributes->vtsm_vobs_attr);
2024 read_video_attr(&vts_attributes->vtstt_vobs_video_attr);
2025 read_audio_attr(&vts_attributes->vtsm_audio_attr);
2026 for(i=0; i<8; i++)
2027 read_audio_attr(&vts_attributes->vtstt_audio_attr[i]);
2028 read_subp_attr(&vts_attributes->vtsm_subp_attr);
2029 for(i=0; i<32; i++)
2030 read_subp_attr(&vts_attributes->vtstt_subp_attr[i]);
2031 B2N_32(vts_attributes->last_byte);
2032 B2N_32(vts_attributes->vts_cat);
2034 CHECK_ZERO(vts_attributes->zero_1);
2035 CHECK_ZERO(vts_attributes->zero_2);
2036 CHECK_ZERO(vts_attributes->zero_3);
2037 CHECK_ZERO(vts_attributes->zero_4);
2038 CHECK_ZERO(vts_attributes->zero_5);
2039 CHECK_ZERO(vts_attributes->zero_6);
2040 CHECK_ZERO(vts_attributes->zero_7);
2041 CHECK_VALUE(vts_attributes->nr_of_vtsm_audio_streams <= 1);
2042 CHECK_VALUE(vts_attributes->nr_of_vtsm_subp_streams <= 1);
2043 CHECK_VALUE(vts_attributes->nr_of_vtstt_audio_streams <= 8);
2044 for(i = vts_attributes->nr_of_vtstt_audio_streams; i < 8; i++)
2045 CHECK_ZERO(vts_attributes->vtstt_audio_attr[i]);
2046 CHECK_VALUE(vts_attributes->nr_of_vtstt_subp_streams <= 32);
2048 unsigned int nr_coded;
2049 CHECK_VALUE(vts_attributes->last_byte + 1 >= VTS_ATTRIBUTES_MIN_SIZE);
2050 nr_coded = (vts_attributes->last_byte + 1 - VTS_ATTRIBUTES_MIN_SIZE)/6;
2051 /* This is often nr_coded = 70, how do you know how many there really are? */
2052 if(nr_coded > 32) { /* We haven't read more from disk/file anyway */
2053 nr_coded = 32;
2055 CHECK_VALUE(vts_attributes->nr_of_vtstt_subp_streams <= nr_coded);
2056 for(i = vts_attributes->nr_of_vtstt_subp_streams; i < nr_coded; i++)
2057 CHECK_ZERO(vts_attributes->vtstt_subp_attr[i]);
2060 return 1;
2065 int ifoRead_VTS_ATRT(ifo_handle_t *ifofile) {
2066 vts_atrt_t *vts_atrt;
2067 unsigned int i, info_length, sector;
2068 uint32_t *data;
2070 if(!ifofile)
2071 return 0;
2073 if(!ifofile->vmgi_mat)
2074 return 0;
2076 if(ifofile->vmgi_mat->vts_atrt == 0) /* mandatory */
2077 return 0;
2079 sector = ifofile->vmgi_mat->vts_atrt;
2080 if(!DVDFileSeek_(ifofile->file, sector * DVD_BLOCK_LEN))
2081 return 0;
2083 vts_atrt = (vts_atrt_t *)malloc(sizeof(vts_atrt_t));
2084 if(!vts_atrt)
2085 return 0;
2087 ifofile->vts_atrt = vts_atrt;
2089 if(!(DVDReadBytes(ifofile->file, vts_atrt, VTS_ATRT_SIZE))) {
2090 free(vts_atrt);
2091 ifofile->vts_atrt = 0;
2092 return 0;
2095 B2N_16(vts_atrt->nr_of_vtss);
2096 B2N_32(vts_atrt->last_byte);
2098 CHECK_ZERO(vts_atrt->zero_1);
2099 CHECK_VALUE(vts_atrt->nr_of_vtss != 0);
2100 CHECK_VALUE(vts_atrt->nr_of_vtss < 100); /* ?? */
2101 CHECK_VALUE((uint32_t)vts_atrt->nr_of_vtss * (4 + VTS_ATTRIBUTES_MIN_SIZE) +
2102 VTS_ATRT_SIZE < vts_atrt->last_byte + 1);
2104 info_length = vts_atrt->nr_of_vtss * sizeof(uint32_t);
2105 data = (uint32_t *)malloc(info_length);
2106 if(!data) {
2107 free(vts_atrt);
2108 ifofile->vts_atrt = 0;
2109 return 0;
2112 vts_atrt->vts_atrt_offsets = data;
2114 if(!(DVDReadBytes(ifofile->file, data, info_length))) {
2115 free(data);
2116 free(vts_atrt);
2117 ifofile->vts_atrt = 0;
2118 return 0;
2121 for(i = 0; i < vts_atrt->nr_of_vtss; i++) {
2122 B2N_32(data[i]);
2123 CHECK_VALUE(data[i] + VTS_ATTRIBUTES_MIN_SIZE < vts_atrt->last_byte + 1);
2126 info_length = vts_atrt->nr_of_vtss * sizeof(vts_attributes_t);
2127 vts_atrt->vts = (vts_attributes_t *)malloc(info_length);
2128 if(!vts_atrt->vts) {
2129 free(data);
2130 free(vts_atrt);
2131 ifofile->vts_atrt = 0;
2132 return 0;
2134 for(i = 0; i < vts_atrt->nr_of_vtss; i++) {
2135 unsigned int offset = data[i];
2136 if(!ifoRead_VTS_ATTRIBUTES(ifofile, &(vts_atrt->vts[i]),
2137 (sector * DVD_BLOCK_LEN) + offset)) {
2138 free(data);
2139 free(vts_atrt);
2140 ifofile->vts_atrt = 0;
2141 return 0;
2144 /* This assert cant be in ifoRead_VTS_ATTRIBUTES */
2145 CHECK_VALUE(offset + vts_atrt->vts[i].last_byte <= vts_atrt->last_byte + 1);
2146 /* Is this check correct? */
2149 return 1;
2153 void ifoFree_VTS_ATRT(ifo_handle_t *ifofile) {
2154 if(!ifofile)
2155 return;
2157 if(ifofile->vts_atrt) {
2158 free(ifofile->vts_atrt->vts);
2159 free(ifofile->vts_atrt->vts_atrt_offsets);
2160 free(ifofile->vts_atrt);
2161 ifofile->vts_atrt = 0;
2166 int ifoRead_TXTDT_MGI(ifo_handle_t *ifofile) {
2167 txtdt_mgi_t *txtdt_mgi;
2169 if(!ifofile)
2170 return 0;
2172 if(!ifofile->vmgi_mat)
2173 return 0;
2175 /* Return successfully if there is nothing to read. */
2176 if(ifofile->vmgi_mat->txtdt_mgi == 0)
2177 return 1;
2179 if(!DVDFileSeek_(ifofile->file,
2180 ifofile->vmgi_mat->txtdt_mgi * DVD_BLOCK_LEN))
2181 return 0;
2183 txtdt_mgi = (txtdt_mgi_t *)malloc(sizeof(txtdt_mgi_t));
2184 if(!txtdt_mgi) {
2185 return 0;
2187 ifofile->txtdt_mgi = txtdt_mgi;
2189 if(!(DVDReadBytes(ifofile->file, txtdt_mgi, TXTDT_MGI_SIZE))) {
2190 fprintf(stderr, "libdvdread: Unable to read TXTDT_MGI.\n");
2191 free(txtdt_mgi);
2192 ifofile->txtdt_mgi = 0;
2193 return 0;
2196 /* fprintf(stderr, "-- Not done yet --\n"); */
2197 return 1;
2200 void ifoFree_TXTDT_MGI(ifo_handle_t *ifofile) {
2201 if(!ifofile)
2202 return;
2204 if(ifofile->txtdt_mgi) {
2205 free(ifofile->txtdt_mgi);
2206 ifofile->txtdt_mgi = 0;