~ubuntu-branches/ubuntu/raring/libdvdread/raring-proposed

« back to all changes in this revision

Viewing changes to .pc/07-vts-tmapt.patch/src/ifo_read.c

  • Committer: Package Import Robot
  • Author(s): Vibhav Pant
  • Date: 2012-12-15 17:06:42 UTC
  • mfrom: (1.3.2) (3.2.15 sid)
  • Revision ID: package-import@ubuntu.com-20121215170642-q0h4cc4r2mchkgcl
Tags: 4.2.0+20121016-1ubuntu1
* Merge from Debian unstable (LP: #1090692).  Remaining changes:
  - Re-add missing install-css.sh.
  - debian/control: add Suggests for install-css.sh on debhelper,
    fakeroot, and build-essential.
  - debian/rules: install install-css.sh, leave perms executable.

Show diffs side-by-side

added added

removed removed

Lines of Context:
1
 
/*
2
 
 * Copyright (C) 2000, 2001, 2002, 2003
3
 
 *               Björn Englund <d4bjorn@dtek.chalmers.se>,
4
 
 *               Håkan Hjort <d95hjort@dtek.chalmers.se>
5
 
 *
6
 
 * This file is part of libdvdread.
7
 
 *
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.
12
 
 *
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.
17
 
 *
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.
21
 
 */
22
 
 
23
 
#include "config.h"
24
 
 
25
 
#include <stdio.h>
26
 
#include <stdlib.h>
27
 
#include <inttypes.h>
28
 
#include <string.h>
29
 
 
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"
36
 
 
37
 
#ifndef DVD_BLOCK_LEN
38
 
#define DVD_BLOCK_LEN 2048
39
 
#endif
40
 
 
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);                            \
46
 
  }
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");                                              \
55
 
  }
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
61
 
 
62
 
 
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);
89
 
 
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);
93
 
 
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);
96
 
}
97
 
 
98
 
static inline int DVDFileSeek_( dvd_file_t *dvd_file, uint32_t offset ) {
99
 
  return (DVDFileSeek(dvd_file, (int)offset) == (int)offset);
100
 
}
101
 
 
102
 
static void read_video_attr(video_attr_t *va) {
103
 
  getbits_state_t state;
104
 
  uint8_t buf[sizeof(video_attr_t)];
105
 
 
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);
119
 
}
120
 
 
121
 
static void read_audio_attr(audio_attr_t *aa) {
122
 
  getbits_state_t state;
123
 
  uint8_t buf[sizeof(audio_attr_t)];
124
 
 
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);
144
 
}
145
 
 
146
 
static void read_multichannel_ext(multichannel_ext_t *me) {
147
 
  getbits_state_t state;
148
 
  uint8_t buf[sizeof(multichannel_ext_t)];
149
 
 
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);
171
 
}
172
 
 
173
 
static void read_subp_attr(subp_attr_t *sa) {
174
 
  getbits_state_t state;
175
 
  uint8_t buf[sizeof(subp_attr_t)];
176
 
 
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);
186
 
}
187
 
 
188
 
static void read_user_ops(user_ops_t *uo) {
189
 
  getbits_state_t state;
190
 
  uint8_t buf[sizeof(user_ops_t)];
191
 
 
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);
220
 
}
221
 
 
222
 
static void read_pgci_srp(pgci_srp_t *ps) {
223
 
  getbits_state_t state;
224
 
  uint8_t buf[sizeof(pgci_srp_t)];
225
 
 
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);
234
 
}
235
 
 
236
 
static void read_cell_playback(cell_playback_t *cp) {
237
 
  getbits_state_t state;
238
 
  uint8_t buf[sizeof(cell_playback_t)];
239
 
 
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);
253
 
 
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);
258
 
 
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);
263
 
}
264
 
 
265
 
static void read_playback_type(playback_type_t *pt) {
266
 
  getbits_state_t state;
267
 
  uint8_t buf[sizeof(playback_type_t)];
268
 
 
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);
279
 
}
280
 
 
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);
285
 
 
286
 
  free(ptl_mait->countries);
287
 
  free(ptl_mait);
288
 
}
289
 
 
290
 
ifo_handle_t *ifoOpen(dvd_reader_t *dvd, int title) {
291
 
  ifo_handle_t *ifofile;
292
 
  int bup_file_opened = 0;
293
 
  char ifo_filename[13];
294
 
 
295
 
  ifofile = (ifo_handle_t *)malloc(sizeof(ifo_handle_t));
296
 
  if(!ifofile)
297
 
    return NULL;
298
 
 
299
 
  memset(ifofile, 0, sizeof(ifo_handle_t));
300
 
 
301
 
  ifofile->file = DVDOpenFile(dvd, title, DVD_READ_INFO_FILE);
302
 
  if(!ifofile->file) { /* Failed to open IFO, try to open BUP */
303
 
    ifofile->file = DVDOpenFile(dvd, title, DVD_READ_INFO_BACKUP_FILE);
304
 
    bup_file_opened = 1;
305
 
  }
306
 
 
307
 
  if (title)
308
 
    snprintf(ifo_filename, 12, "VTS_%02d_0.%s", title, bup_file_opened ? "BUP" : "IFO");
309
 
  else
310
 
    snprintf(ifo_filename, 12, "VIDEO_TS.%s", bup_file_opened ? "BUP" : "IFO");
311
 
 
312
 
  ifo_filename[12] = '\0';
313
 
 
314
 
  if(!ifofile->file) {
315
 
    fprintf(stderr, "libdvdread: Can't open file %s.\n", ifo_filename);
316
 
    free(ifofile);
317
 
    return NULL;
318
 
  }
319
 
 
320
 
  /* First check if this is a VMGI file. */
321
 
  if(ifoRead_VMG(ifofile)) {
322
 
 
323
 
    /* These are both mandatory. */
324
 
    if(!ifoRead_FP_PGC(ifofile) || !ifoRead_TT_SRPT(ifofile))
325
 
      goto ifoOpen_try_bup;
326
 
 
327
 
    ifoRead_PGCI_UT(ifofile);
328
 
    ifoRead_PTL_MAIT(ifofile);
329
 
 
330
 
    /* This is also mandatory. */
331
 
    if(!ifoRead_VTS_ATRT(ifofile))
332
 
      goto ifoOpen_try_bup;
333
 
 
334
 
    ifoRead_TXTDT_MGI(ifofile);
335
 
    ifoRead_C_ADT(ifofile);
336
 
    ifoRead_VOBU_ADMAP(ifofile);
337
 
 
338
 
    return ifofile;
339
 
  }
340
 
 
341
 
  if(ifoRead_VTS(ifofile)) {
342
 
 
343
 
    if(!ifoRead_VTS_PTT_SRPT(ifofile) || !ifoRead_PGCIT(ifofile))
344
 
      goto ifoOpen_try_bup;
345
 
 
346
 
    ifoRead_PGCI_UT(ifofile);
347
 
    ifoRead_VTS_TMAPT(ifofile);
348
 
    ifoRead_C_ADT(ifofile);
349
 
    ifoRead_VOBU_ADMAP(ifofile);
350
 
 
351
 
    if(!ifoRead_TITLE_C_ADT(ifofile) || !ifoRead_TITLE_VOBU_ADMAP(ifofile))
352
 
      goto ifoOpen_try_bup;
353
 
 
354
 
    return ifofile;
355
 
  }
356
 
 
357
 
ifoOpen_try_bup:
358
 
  if (bup_file_opened)
359
 
    goto ifoOpen_fail;
360
 
 
361
 
  /* Try BUP instead */
362
 
  ifoClose(ifofile);
363
 
 
364
 
  ifofile = (ifo_handle_t *)malloc(sizeof(ifo_handle_t));
365
 
  if(!ifofile)
366
 
    return NULL;
367
 
 
368
 
  memset(ifofile, 0, sizeof(ifo_handle_t));
369
 
  ifofile->file = DVDOpenFile(dvd, title, DVD_READ_INFO_BACKUP_FILE);
370
 
 
371
 
  if (title)
372
 
    snprintf(ifo_filename, 12, "VTS_%02d_0.BUP", title);
373
 
  else
374
 
    strncpy(ifo_filename, "VIDEO_TS.BUP", 12);
375
 
 
376
 
  if (!ifofile->file) {
377
 
    fprintf(stderr, "libdvdread: Can't open file %s.\n", ifo_filename);
378
 
    free(ifofile);
379
 
    return NULL;
380
 
  }
381
 
  bup_file_opened = 1;
382
 
 
383
 
  /* First check if this is a VMGI file. */
384
 
  if(ifoRead_VMG(ifofile)) {
385
 
 
386
 
    /* These are both mandatory. */
387
 
    if(!ifoRead_FP_PGC(ifofile) || !ifoRead_TT_SRPT(ifofile))
388
 
      goto ifoOpen_fail;
389
 
 
390
 
    ifoRead_PGCI_UT(ifofile);
391
 
    ifoRead_PTL_MAIT(ifofile);
392
 
 
393
 
    /* This is also mandatory. */
394
 
    if(!ifoRead_VTS_ATRT(ifofile))
395
 
      goto ifoOpen_fail;
396
 
 
397
 
    ifoRead_TXTDT_MGI(ifofile);
398
 
    ifoRead_C_ADT(ifofile);
399
 
    ifoRead_VOBU_ADMAP(ifofile);
400
 
 
401
 
    return ifofile;
402
 
  }
403
 
 
404
 
  if(ifoRead_VTS(ifofile)) {
405
 
 
406
 
    if(!ifoRead_VTS_PTT_SRPT(ifofile) || !ifoRead_PGCIT(ifofile))
407
 
      goto ifoOpen_fail;
408
 
 
409
 
    ifoRead_PGCI_UT(ifofile);
410
 
    ifoRead_VTS_TMAPT(ifofile);
411
 
    ifoRead_C_ADT(ifofile);
412
 
    ifoRead_VOBU_ADMAP(ifofile);
413
 
 
414
 
    if(!ifoRead_TITLE_C_ADT(ifofile) || !ifoRead_TITLE_VOBU_ADMAP(ifofile))
415
 
      goto ifoOpen_fail;
416
 
 
417
 
    return ifofile;
418
 
  }
419
 
 
420
 
ifoOpen_fail:
421
 
  fprintf(stderr, "libdvdread: Invalid IFO for title %d (%s).\n", title, ifo_filename);
422
 
  ifoClose(ifofile);
423
 
  return NULL;
424
 
}
425
 
 
426
 
 
427
 
ifo_handle_t *ifoOpenVMGI(dvd_reader_t *dvd) {
428
 
  ifo_handle_t *ifofile;
429
 
 
430
 
  ifofile = (ifo_handle_t *)malloc(sizeof(ifo_handle_t));
431
 
  if(!ifofile)
432
 
    return NULL;
433
 
 
434
 
  memset(ifofile, 0, sizeof(ifo_handle_t));
435
 
 
436
 
  ifofile->file = DVDOpenFile(dvd, 0, DVD_READ_INFO_FILE);
437
 
  if(!ifofile->file) /* Should really catch any error and try to fallback */
438
 
    ifofile->file = DVDOpenFile(dvd, 0, DVD_READ_INFO_BACKUP_FILE);
439
 
  if(!ifofile->file) {
440
 
    fprintf(stderr, "libdvdread: Can't open file VIDEO_TS.IFO.\n");
441
 
    free(ifofile);
442
 
    return NULL;
443
 
  }
444
 
 
445
 
  if(ifoRead_VMG(ifofile))
446
 
    return ifofile;
447
 
 
448
 
  fprintf(stderr, "libdvdread,ifoOpenVMGI(): Invalid main menu IFO (VIDEO_TS.IFO).\n");
449
 
  ifoClose(ifofile);
450
 
  return NULL;
451
 
}
452
 
 
453
 
 
454
 
ifo_handle_t *ifoOpenVTSI(dvd_reader_t *dvd, int title) {
455
 
  ifo_handle_t *ifofile;
456
 
 
457
 
  ifofile = (ifo_handle_t *)malloc(sizeof(ifo_handle_t));
458
 
  if(!ifofile)
459
 
    return NULL;
460
 
 
461
 
  memset(ifofile, 0, sizeof(ifo_handle_t));
462
 
 
463
 
  if(title <= 0 || title > 99) {
464
 
    fprintf(stderr, "libdvdread: ifoOpenVTSI invalid title (%d).\n", title);
465
 
    free(ifofile);
466
 
    return NULL;
467
 
  }
468
 
 
469
 
  ifofile->file = DVDOpenFile(dvd, title, DVD_READ_INFO_FILE);
470
 
  if(!ifofile->file) /* Should really catch any error and try to fallback */
471
 
    ifofile->file = DVDOpenFile(dvd, title, DVD_READ_INFO_BACKUP_FILE);
472
 
  if(!ifofile->file) {
473
 
    fprintf(stderr, "libdvdread: Can't open file VTS_%02d_0.IFO.\n", title);
474
 
    free(ifofile);
475
 
    return NULL;
476
 
  }
477
 
 
478
 
  if(ifoRead_VTS(ifofile) && ifofile->vtsi_mat)
479
 
    return ifofile;
480
 
 
481
 
  fprintf(stderr, "libdvdread: Invalid IFO for title %d (VTS_%02d_0.IFO).\n",
482
 
          title, title);
483
 
  ifoClose(ifofile);
484
 
  return NULL;
485
 
}
486
 
 
487
 
 
488
 
void ifoClose(ifo_handle_t *ifofile) {
489
 
  if(!ifofile)
490
 
    return;
491
 
 
492
 
  ifoFree_VOBU_ADMAP(ifofile);
493
 
  ifoFree_TITLE_VOBU_ADMAP(ifofile);
494
 
  ifoFree_C_ADT(ifofile);
495
 
  ifoFree_TITLE_C_ADT(ifofile);
496
 
  ifoFree_TXTDT_MGI(ifofile);
497
 
  ifoFree_VTS_ATRT(ifofile);
498
 
  ifoFree_PTL_MAIT(ifofile);
499
 
  ifoFree_PGCI_UT(ifofile);
500
 
  ifoFree_TT_SRPT(ifofile);
501
 
  ifoFree_FP_PGC(ifofile);
502
 
  ifoFree_PGCIT(ifofile);
503
 
  ifoFree_VTS_PTT_SRPT(ifofile);
504
 
  ifoFree_VTS_TMAPT(ifofile);
505
 
 
506
 
  if(ifofile->vmgi_mat)
507
 
    free(ifofile->vmgi_mat);
508
 
 
509
 
  if(ifofile->vtsi_mat)
510
 
    free(ifofile->vtsi_mat);
511
 
 
512
 
  DVDCloseFile(ifofile->file);
513
 
  ifofile->file = 0;
514
 
  free(ifofile);
515
 
  ifofile = 0;
516
 
}
517
 
 
518
 
 
519
 
static int ifoRead_VMG(ifo_handle_t *ifofile) {
520
 
  vmgi_mat_t *vmgi_mat;
521
 
 
522
 
  vmgi_mat = (vmgi_mat_t *)malloc(sizeof(vmgi_mat_t));
523
 
  if(!vmgi_mat)
524
 
    return 0;
525
 
 
526
 
  ifofile->vmgi_mat = vmgi_mat;
527
 
 
528
 
  if(!DVDFileSeek_(ifofile->file, 0)) {
529
 
    free(ifofile->vmgi_mat);
530
 
    ifofile->vmgi_mat = 0;
531
 
    return 0;
532
 
  }
533
 
 
534
 
  if(!DVDReadBytes(ifofile->file, vmgi_mat, sizeof(vmgi_mat_t))) {
535
 
    free(ifofile->vmgi_mat);
536
 
    ifofile->vmgi_mat = 0;
537
 
    return 0;
538
 
  }
539
 
 
540
 
  if(strncmp("DVDVIDEO-VMG", vmgi_mat->vmg_identifier, 12) != 0) {
541
 
    free(ifofile->vmgi_mat);
542
 
    ifofile->vmgi_mat = 0;
543
 
    return 0;
544
 
  }
545
 
 
546
 
  B2N_32(vmgi_mat->vmg_last_sector);
547
 
  B2N_32(vmgi_mat->vmgi_last_sector);
548
 
  B2N_32(vmgi_mat->vmg_category);
549
 
  B2N_16(vmgi_mat->vmg_nr_of_volumes);
550
 
  B2N_16(vmgi_mat->vmg_this_volume_nr);
551
 
  B2N_16(vmgi_mat->vmg_nr_of_title_sets);
552
 
  B2N_64(vmgi_mat->vmg_pos_code);
553
 
  B2N_32(vmgi_mat->vmgi_last_byte);
554
 
  B2N_32(vmgi_mat->first_play_pgc);
555
 
  B2N_32(vmgi_mat->vmgm_vobs);
556
 
  B2N_32(vmgi_mat->tt_srpt);
557
 
  B2N_32(vmgi_mat->vmgm_pgci_ut);
558
 
  B2N_32(vmgi_mat->ptl_mait);
559
 
  B2N_32(vmgi_mat->vts_atrt);
560
 
  B2N_32(vmgi_mat->txtdt_mgi);
561
 
  B2N_32(vmgi_mat->vmgm_c_adt);
562
 
  B2N_32(vmgi_mat->vmgm_vobu_admap);
563
 
  read_video_attr(&vmgi_mat->vmgm_video_attr);
564
 
  read_audio_attr(&vmgi_mat->vmgm_audio_attr);
565
 
  read_subp_attr(&vmgi_mat->vmgm_subp_attr);
566
 
 
567
 
 
568
 
  CHECK_ZERO(vmgi_mat->zero_1);
569
 
  CHECK_ZERO(vmgi_mat->zero_2);
570
 
  CHECK_ZERO(vmgi_mat->zero_3);
571
 
  CHECK_ZERO(vmgi_mat->zero_4);
572
 
  CHECK_ZERO(vmgi_mat->zero_5);
573
 
  CHECK_ZERO(vmgi_mat->zero_6);
574
 
  CHECK_ZERO(vmgi_mat->zero_7);
575
 
  CHECK_ZERO(vmgi_mat->zero_8);
576
 
  CHECK_ZERO(vmgi_mat->zero_9);
577
 
  CHECK_ZERO(vmgi_mat->zero_10);
578
 
  CHECK_VALUE(vmgi_mat->vmg_last_sector != 0);
579
 
  CHECK_VALUE(vmgi_mat->vmgi_last_sector != 0);
580
 
  CHECK_VALUE(vmgi_mat->vmgi_last_sector * 2 <= vmgi_mat->vmg_last_sector);
581
 
  CHECK_VALUE(vmgi_mat->vmgi_last_sector * 2 <= vmgi_mat->vmg_last_sector);
582
 
  CHECK_VALUE(vmgi_mat->vmg_nr_of_volumes != 0);
583
 
  CHECK_VALUE(vmgi_mat->vmg_this_volume_nr != 0);
584
 
  CHECK_VALUE(vmgi_mat->vmg_this_volume_nr <= vmgi_mat->vmg_nr_of_volumes);
585
 
  CHECK_VALUE(vmgi_mat->disc_side == 1 || vmgi_mat->disc_side == 2);
586
 
  CHECK_VALUE(vmgi_mat->vmg_nr_of_title_sets != 0);
587
 
  CHECK_VALUE(vmgi_mat->vmgi_last_byte >= 341);
588
 
  CHECK_VALUE(vmgi_mat->vmgi_last_byte / DVD_BLOCK_LEN <=
589
 
              vmgi_mat->vmgi_last_sector);
590
 
  /* It seems that first_play_pgc is optional. */
591
 
  CHECK_VALUE(vmgi_mat->first_play_pgc < vmgi_mat->vmgi_last_byte);
592
 
  CHECK_VALUE(vmgi_mat->vmgm_vobs == 0 ||
593
 
              (vmgi_mat->vmgm_vobs > vmgi_mat->vmgi_last_sector &&
594
 
               vmgi_mat->vmgm_vobs < vmgi_mat->vmg_last_sector));
595
 
  CHECK_VALUE(vmgi_mat->tt_srpt <= vmgi_mat->vmgi_last_sector);
596
 
  CHECK_VALUE(vmgi_mat->vmgm_pgci_ut <= vmgi_mat->vmgi_last_sector);
597
 
  CHECK_VALUE(vmgi_mat->ptl_mait <= vmgi_mat->vmgi_last_sector);
598
 
  CHECK_VALUE(vmgi_mat->vts_atrt <= vmgi_mat->vmgi_last_sector);
599
 
  CHECK_VALUE(vmgi_mat->txtdt_mgi <= vmgi_mat->vmgi_last_sector);
600
 
  CHECK_VALUE(vmgi_mat->vmgm_c_adt <= vmgi_mat->vmgi_last_sector);
601
 
  CHECK_VALUE(vmgi_mat->vmgm_vobu_admap <= vmgi_mat->vmgi_last_sector);
602
 
 
603
 
  CHECK_VALUE(vmgi_mat->nr_of_vmgm_audio_streams <= 1);
604
 
  CHECK_VALUE(vmgi_mat->nr_of_vmgm_subp_streams <= 1);
605
 
 
606
 
  return 1;
607
 
}
608
 
 
609
 
 
610
 
static int ifoRead_VTS(ifo_handle_t *ifofile) {
611
 
  vtsi_mat_t *vtsi_mat;
612
 
  int i;
613
 
 
614
 
  vtsi_mat = (vtsi_mat_t *)malloc(sizeof(vtsi_mat_t));
615
 
  if(!vtsi_mat)
616
 
    return 0;
617
 
 
618
 
  ifofile->vtsi_mat = vtsi_mat;
619
 
 
620
 
  if(!DVDFileSeek_(ifofile->file, 0)) {
621
 
    free(ifofile->vtsi_mat);
622
 
    ifofile->vtsi_mat = NULL;
623
 
    return 0;
624
 
  }
625
 
 
626
 
  if(!(DVDReadBytes(ifofile->file, vtsi_mat, sizeof(vtsi_mat_t)))) {
627
 
    free(ifofile->vtsi_mat);
628
 
    ifofile->vtsi_mat = NULL;
629
 
    return 0;
630
 
  }
631
 
 
632
 
  if(strncmp("DVDVIDEO-VTS", vtsi_mat->vts_identifier, 12) != 0) {
633
 
    free(ifofile->vtsi_mat);
634
 
    ifofile->vtsi_mat = NULL;
635
 
    return 0;
636
 
  }
637
 
 
638
 
  read_video_attr(&vtsi_mat->vtsm_video_attr);
639
 
  read_video_attr(&vtsi_mat->vts_video_attr);
640
 
  read_audio_attr(&vtsi_mat->vtsm_audio_attr);
641
 
  for(i=0; i<8; i++)
642
 
    read_audio_attr(&vtsi_mat->vts_audio_attr[i]);
643
 
  read_subp_attr(&vtsi_mat->vtsm_subp_attr);
644
 
  for(i=0; i<32; i++)
645
 
    read_subp_attr(&vtsi_mat->vts_subp_attr[i]);
646
 
  B2N_32(vtsi_mat->vts_last_sector);
647
 
  B2N_32(vtsi_mat->vtsi_last_sector);
648
 
  B2N_32(vtsi_mat->vts_category);
649
 
  B2N_32(vtsi_mat->vtsi_last_byte);
650
 
  B2N_32(vtsi_mat->vtsm_vobs);
651
 
  B2N_32(vtsi_mat->vtstt_vobs);
652
 
  B2N_32(vtsi_mat->vts_ptt_srpt);
653
 
  B2N_32(vtsi_mat->vts_pgcit);
654
 
  B2N_32(vtsi_mat->vtsm_pgci_ut);
655
 
  B2N_32(vtsi_mat->vts_tmapt);
656
 
  B2N_32(vtsi_mat->vtsm_c_adt);
657
 
  B2N_32(vtsi_mat->vtsm_vobu_admap);
658
 
  B2N_32(vtsi_mat->vts_c_adt);
659
 
  B2N_32(vtsi_mat->vts_vobu_admap);
660
 
 
661
 
 
662
 
  CHECK_ZERO(vtsi_mat->zero_1);
663
 
  CHECK_ZERO(vtsi_mat->zero_2);
664
 
  CHECK_ZERO(vtsi_mat->zero_3);
665
 
  CHECK_ZERO(vtsi_mat->zero_4);
666
 
  CHECK_ZERO(vtsi_mat->zero_5);
667
 
  CHECK_ZERO(vtsi_mat->zero_6);
668
 
  CHECK_ZERO(vtsi_mat->zero_7);
669
 
  CHECK_ZERO(vtsi_mat->zero_8);
670
 
  CHECK_ZERO(vtsi_mat->zero_9);
671
 
  CHECK_ZERO(vtsi_mat->zero_10);
672
 
  CHECK_ZERO(vtsi_mat->zero_11);
673
 
  CHECK_ZERO(vtsi_mat->zero_12);
674
 
  CHECK_ZERO(vtsi_mat->zero_13);
675
 
  CHECK_ZERO(vtsi_mat->zero_14);
676
 
  CHECK_ZERO(vtsi_mat->zero_15);
677
 
  CHECK_ZERO(vtsi_mat->zero_16);
678
 
  CHECK_ZERO(vtsi_mat->zero_17);
679
 
  CHECK_ZERO(vtsi_mat->zero_18);
680
 
  CHECK_ZERO(vtsi_mat->zero_19);
681
 
  CHECK_ZERO(vtsi_mat->zero_20);
682
 
  CHECK_ZERO(vtsi_mat->zero_21);
683
 
  CHECK_VALUE(vtsi_mat->vtsi_last_sector*2 <= vtsi_mat->vts_last_sector);
684
 
  CHECK_VALUE(vtsi_mat->vtsi_last_byte/DVD_BLOCK_LEN <= vtsi_mat->vtsi_last_sector);
685
 
  CHECK_VALUE(vtsi_mat->vtsm_vobs == 0 ||
686
 
              (vtsi_mat->vtsm_vobs > vtsi_mat->vtsi_last_sector &&
687
 
               vtsi_mat->vtsm_vobs < vtsi_mat->vts_last_sector));
688
 
  CHECK_VALUE(vtsi_mat->vtstt_vobs == 0 ||
689
 
              (vtsi_mat->vtstt_vobs > vtsi_mat->vtsi_last_sector &&
690
 
               vtsi_mat->vtstt_vobs < vtsi_mat->vts_last_sector));
691
 
  CHECK_VALUE(vtsi_mat->vts_ptt_srpt <= vtsi_mat->vtsi_last_sector);
692
 
  CHECK_VALUE(vtsi_mat->vts_pgcit <= vtsi_mat->vtsi_last_sector);
693
 
  CHECK_VALUE(vtsi_mat->vtsm_pgci_ut <= vtsi_mat->vtsi_last_sector);
694
 
  CHECK_VALUE(vtsi_mat->vts_tmapt <= vtsi_mat->vtsi_last_sector);
695
 
  CHECK_VALUE(vtsi_mat->vtsm_c_adt <= vtsi_mat->vtsi_last_sector);
696
 
  CHECK_VALUE(vtsi_mat->vtsm_vobu_admap <= vtsi_mat->vtsi_last_sector);
697
 
  CHECK_VALUE(vtsi_mat->vts_c_adt <= vtsi_mat->vtsi_last_sector);
698
 
  CHECK_VALUE(vtsi_mat->vts_vobu_admap <= vtsi_mat->vtsi_last_sector);
699
 
 
700
 
  CHECK_VALUE(vtsi_mat->nr_of_vtsm_audio_streams <= 1);
701
 
  CHECK_VALUE(vtsi_mat->nr_of_vtsm_subp_streams <= 1);
702
 
 
703
 
  CHECK_VALUE(vtsi_mat->nr_of_vts_audio_streams <= 8);
704
 
  for(i = vtsi_mat->nr_of_vts_audio_streams; i < 8; i++)
705
 
    CHECK_ZERO(vtsi_mat->vts_audio_attr[i]);
706
 
 
707
 
  CHECK_VALUE(vtsi_mat->nr_of_vts_subp_streams <= 32);
708
 
  for(i = vtsi_mat->nr_of_vts_subp_streams; i < 32; i++)
709
 
    CHECK_ZERO(vtsi_mat->vts_subp_attr[i]);
710
 
 
711
 
  for(i = 0; i < 8; i++) {
712
 
    read_multichannel_ext(&vtsi_mat->vts_mu_audio_attr[i]);
713
 
    CHECK_ZERO0(vtsi_mat->vts_mu_audio_attr[i].zero1);
714
 
    CHECK_ZERO0(vtsi_mat->vts_mu_audio_attr[i].zero2);
715
 
    CHECK_ZERO0(vtsi_mat->vts_mu_audio_attr[i].zero3);
716
 
    CHECK_ZERO0(vtsi_mat->vts_mu_audio_attr[i].zero4);
717
 
    CHECK_ZERO0(vtsi_mat->vts_mu_audio_attr[i].zero5);
718
 
    CHECK_ZERO(vtsi_mat->vts_mu_audio_attr[i].zero6);
719
 
  }
720
 
 
721
 
  return 1;
722
 
}
723
 
 
724
 
 
725
 
static int ifoRead_PGC_COMMAND_TBL(ifo_handle_t *ifofile,
726
 
                                   pgc_command_tbl_t *cmd_tbl,
727
 
                                   unsigned int offset) {
728
 
 
729
 
  memset(cmd_tbl, 0, sizeof(pgc_command_tbl_t));
730
 
 
731
 
  if(!DVDFileSeek_(ifofile->file, offset))
732
 
    return 0;
733
 
 
734
 
  if(!(DVDReadBytes(ifofile->file, cmd_tbl, PGC_COMMAND_TBL_SIZE)))
735
 
    return 0;
736
 
 
737
 
  B2N_16(cmd_tbl->nr_of_pre);
738
 
  B2N_16(cmd_tbl->nr_of_post);
739
 
  B2N_16(cmd_tbl->nr_of_cell);
740
 
 
741
 
  CHECK_VALUE(cmd_tbl->nr_of_pre + cmd_tbl->nr_of_post + cmd_tbl->nr_of_cell<= 255);
742
 
 
743
 
  if(cmd_tbl->nr_of_pre != 0) {
744
 
    unsigned int pre_cmds_size  = cmd_tbl->nr_of_pre * COMMAND_DATA_SIZE;
745
 
    cmd_tbl->pre_cmds = (vm_cmd_t *)malloc(pre_cmds_size);
746
 
    if(!cmd_tbl->pre_cmds)
747
 
      return 0;
748
 
 
749
 
    if(!(DVDReadBytes(ifofile->file, cmd_tbl->pre_cmds, pre_cmds_size))) {
750
 
      free(cmd_tbl->pre_cmds);
751
 
      return 0;
752
 
    }
753
 
  }
754
 
 
755
 
  if(cmd_tbl->nr_of_post != 0) {
756
 
    unsigned int post_cmds_size = cmd_tbl->nr_of_post * COMMAND_DATA_SIZE;
757
 
    cmd_tbl->post_cmds = (vm_cmd_t *)malloc(post_cmds_size);
758
 
    if(!cmd_tbl->post_cmds) {
759
 
      if(cmd_tbl->pre_cmds)
760
 
        free(cmd_tbl->pre_cmds);
761
 
      return 0;
762
 
    }
763
 
    if(!(DVDReadBytes(ifofile->file, cmd_tbl->post_cmds, post_cmds_size))) {
764
 
      if(cmd_tbl->pre_cmds)
765
 
        free(cmd_tbl->pre_cmds);
766
 
      free(cmd_tbl->post_cmds);
767
 
      return 0;
768
 
    }
769
 
  }
770
 
 
771
 
  if(cmd_tbl->nr_of_cell != 0) {
772
 
    unsigned int cell_cmds_size = cmd_tbl->nr_of_cell * COMMAND_DATA_SIZE;
773
 
    cmd_tbl->cell_cmds = (vm_cmd_t *)malloc(cell_cmds_size);
774
 
    if(!cmd_tbl->cell_cmds) {
775
 
      if(cmd_tbl->pre_cmds)
776
 
        free(cmd_tbl->pre_cmds);
777
 
      if(cmd_tbl->post_cmds)
778
 
        free(cmd_tbl->post_cmds);
779
 
      return 0;
780
 
    }
781
 
    if(!(DVDReadBytes(ifofile->file, cmd_tbl->cell_cmds, cell_cmds_size))) {
782
 
      if(cmd_tbl->pre_cmds)
783
 
        free(cmd_tbl->pre_cmds);
784
 
      if(cmd_tbl->post_cmds)
785
 
        free(cmd_tbl->post_cmds);
786
 
      free(cmd_tbl->cell_cmds);
787
 
      return 0;
788
 
    }
789
 
  }
790
 
 
791
 
  /*
792
 
   * Make a run over all the commands and see that we can interpret them all?
793
 
   */
794
 
  return 1;
795
 
}
796
 
 
797
 
 
798
 
static void ifoFree_PGC_COMMAND_TBL(pgc_command_tbl_t *cmd_tbl) {
799
 
  if(cmd_tbl) {
800
 
    if(cmd_tbl->nr_of_pre && cmd_tbl->pre_cmds)
801
 
      free(cmd_tbl->pre_cmds);
802
 
    if(cmd_tbl->nr_of_post && cmd_tbl->post_cmds)
803
 
      free(cmd_tbl->post_cmds);
804
 
    if(cmd_tbl->nr_of_cell && cmd_tbl->cell_cmds)
805
 
      free(cmd_tbl->cell_cmds);
806
 
    free(cmd_tbl);
807
 
  }
808
 
}
809
 
 
810
 
static int ifoRead_PGC_PROGRAM_MAP(ifo_handle_t *ifofile,
811
 
                                   pgc_program_map_t *program_map,
812
 
                                   unsigned int nr, unsigned int offset) {
813
 
  unsigned int size = nr * sizeof(pgc_program_map_t);
814
 
 
815
 
  if(!DVDFileSeek_(ifofile->file, offset))
816
 
    return 0;
817
 
 
818
 
  if(!(DVDReadBytes(ifofile->file, program_map, size)))
819
 
    return 0;
820
 
 
821
 
  return 1;
822
 
}
823
 
 
824
 
static int ifoRead_CELL_PLAYBACK_TBL(ifo_handle_t *ifofile,
825
 
                                     cell_playback_t *cell_playback,
826
 
                                     unsigned int nr, unsigned int offset) {
827
 
  unsigned int i;
828
 
  unsigned int size = nr * sizeof(cell_playback_t);
829
 
 
830
 
  if(!DVDFileSeek_(ifofile->file, offset))
831
 
    return 0;
832
 
 
833
 
  if(!(DVDReadBytes(ifofile->file, cell_playback, size)))
834
 
    return 0;
835
 
 
836
 
  for(i = 0; i < nr; i++) {
837
 
    read_cell_playback(&cell_playback[i]);
838
 
    /* Changed < to <= because this was false in the movie 'Pi'. */
839
 
    CHECK_VALUE(cell_playback[i].last_vobu_start_sector <=
840
 
                cell_playback[i].last_sector);
841
 
    CHECK_VALUE(cell_playback[i].first_sector <=
842
 
                cell_playback[i].last_vobu_start_sector);
843
 
  }
844
 
 
845
 
  return 1;
846
 
}
847
 
 
848
 
 
849
 
static int ifoRead_CELL_POSITION_TBL(ifo_handle_t *ifofile,
850
 
                                     cell_position_t *cell_position,
851
 
                                     unsigned int nr, unsigned int offset) {
852
 
  unsigned int i;
853
 
  unsigned int size = nr * sizeof(cell_position_t);
854
 
 
855
 
  if(!DVDFileSeek_(ifofile->file, offset))
856
 
    return 0;
857
 
 
858
 
  if(!(DVDReadBytes(ifofile->file, cell_position, size)))
859
 
    return 0;
860
 
 
861
 
  for(i = 0; i < nr; i++) {
862
 
    B2N_16(cell_position[i].vob_id_nr);
863
 
    CHECK_ZERO(cell_position[i].zero_1);
864
 
  }
865
 
 
866
 
  return 1;
867
 
}
868
 
 
869
 
static int ifoRead_PGC(ifo_handle_t *ifofile, pgc_t *pgc, unsigned int offset) {
870
 
  unsigned int i;
871
 
 
872
 
  if(!DVDFileSeek_(ifofile->file, offset))
873
 
    return 0;
874
 
 
875
 
  if(!(DVDReadBytes(ifofile->file, pgc, PGC_SIZE)))
876
 
    return 0;
877
 
 
878
 
  read_user_ops(&pgc->prohibited_ops);
879
 
  B2N_16(pgc->next_pgc_nr);
880
 
  B2N_16(pgc->prev_pgc_nr);
881
 
  B2N_16(pgc->goup_pgc_nr);
882
 
  B2N_16(pgc->command_tbl_offset);
883
 
  B2N_16(pgc->program_map_offset);
884
 
  B2N_16(pgc->cell_playback_offset);
885
 
  B2N_16(pgc->cell_position_offset);
886
 
 
887
 
  for(i = 0; i < 8; i++)
888
 
    B2N_16(pgc->audio_control[i]);
889
 
  for(i = 0; i < 32; i++)
890
 
    B2N_32(pgc->subp_control[i]);
891
 
  for(i = 0; i < 16; i++)
892
 
    B2N_32(pgc->palette[i]);
893
 
 
894
 
  CHECK_ZERO(pgc->zero_1);
895
 
  CHECK_VALUE(pgc->nr_of_programs <= pgc->nr_of_cells);
896
 
 
897
 
  /* verify time (look at print_time) */
898
 
  for(i = 0; i < 8; i++)
899
 
    if(!(pgc->audio_control[i] & 0x8000)) /* The 'is present' bit */
900
 
      CHECK_ZERO(pgc->audio_control[i]);
901
 
  for(i = 0; i < 32; i++)
902
 
    if(!(pgc->subp_control[i] & 0x80000000)) /* The 'is present' bit */
903
 
      CHECK_ZERO(pgc->subp_control[i]);
904
 
 
905
 
  /* Check that time is 0:0:0:0 also if nr_of_programs == 0 */
906
 
  if(pgc->nr_of_programs == 0) {
907
 
    CHECK_ZERO(pgc->still_time);
908
 
    CHECK_ZERO(pgc->pg_playback_mode); /* ?? */
909
 
    CHECK_VALUE(pgc->program_map_offset == 0);
910
 
    CHECK_VALUE(pgc->cell_playback_offset == 0);
911
 
    CHECK_VALUE(pgc->cell_position_offset == 0);
912
 
  } else {
913
 
    CHECK_VALUE(pgc->program_map_offset != 0);
914
 
    CHECK_VALUE(pgc->cell_playback_offset != 0);
915
 
    CHECK_VALUE(pgc->cell_position_offset != 0);
916
 
  }
917
 
 
918
 
  if(pgc->command_tbl_offset != 0) {
919
 
    pgc->command_tbl = malloc(sizeof(pgc_command_tbl_t));
920
 
    if(!pgc->command_tbl)
921
 
      return 0;
922
 
 
923
 
    if(!ifoRead_PGC_COMMAND_TBL(ifofile, pgc->command_tbl,
924
 
                                offset + pgc->command_tbl_offset)) {
925
 
      free(pgc->command_tbl);
926
 
      return 0;
927
 
    }
928
 
  } else {
929
 
    pgc->command_tbl = NULL;
930
 
  }
931
 
 
932
 
  if(pgc->program_map_offset != 0 && pgc->nr_of_programs>0) {
933
 
    pgc->program_map = malloc(pgc->nr_of_programs * sizeof(pgc_program_map_t));
934
 
    if(!pgc->program_map) {
935
 
      ifoFree_PGC_COMMAND_TBL(pgc->command_tbl);
936
 
      return 0;
937
 
    }
938
 
    if(!ifoRead_PGC_PROGRAM_MAP(ifofile, pgc->program_map,pgc->nr_of_programs,
939
 
                                offset + pgc->program_map_offset)) {
940
 
      ifoFree_PGC_COMMAND_TBL(pgc->command_tbl);
941
 
      free(pgc->program_map);
942
 
      return 0;
943
 
    }
944
 
  } else {
945
 
    pgc->program_map = NULL;
946
 
  }
947
 
 
948
 
  if(pgc->cell_playback_offset != 0 && pgc->nr_of_cells>0) {
949
 
    pgc->cell_playback = malloc(pgc->nr_of_cells * sizeof(cell_playback_t));
950
 
    if(!pgc->cell_playback) {
951
 
      ifoFree_PGC_COMMAND_TBL(pgc->command_tbl);
952
 
      if(pgc->program_map)
953
 
        free(pgc->program_map);
954
 
      return 0;
955
 
    }
956
 
    if(!ifoRead_CELL_PLAYBACK_TBL(ifofile, pgc->cell_playback,
957
 
                                  pgc->nr_of_cells,
958
 
                                  offset + pgc->cell_playback_offset)) {
959
 
      ifoFree_PGC_COMMAND_TBL(pgc->command_tbl);
960
 
      if(pgc->program_map)
961
 
        free(pgc->program_map);
962
 
      free(pgc->cell_playback);
963
 
      return 0;
964
 
    }
965
 
  } else {
966
 
    pgc->cell_playback = NULL;
967
 
  }
968
 
 
969
 
  if(pgc->cell_position_offset != 0 && pgc->nr_of_cells>0) {
970
 
    pgc->cell_position = malloc(pgc->nr_of_cells * sizeof(cell_position_t));
971
 
    if(!pgc->cell_position) {
972
 
      ifoFree_PGC(pgc);
973
 
      return 0;
974
 
    }
975
 
    if(!ifoRead_CELL_POSITION_TBL(ifofile, pgc->cell_position,
976
 
                                  pgc->nr_of_cells,
977
 
                                  offset + pgc->cell_position_offset)) {
978
 
      ifoFree_PGC(pgc);
979
 
      return 0;
980
 
    }
981
 
  } else {
982
 
    pgc->cell_position = NULL;
983
 
  }
984
 
 
985
 
  return 1;
986
 
}
987
 
 
988
 
int ifoRead_FP_PGC(ifo_handle_t *ifofile) {
989
 
 
990
 
  if(!ifofile)
991
 
    return 0;
992
 
 
993
 
  if(!ifofile->vmgi_mat)
994
 
    return 0;
995
 
 
996
 
  /* It seems that first_play_pgc is optional after all. */
997
 
  ifofile->first_play_pgc = 0;
998
 
  if(ifofile->vmgi_mat->first_play_pgc == 0)
999
 
    return 1;
1000
 
 
1001
 
  ifofile->first_play_pgc = (pgc_t *)malloc(sizeof(pgc_t));
1002
 
  if(!ifofile->first_play_pgc)
1003
 
    return 0;
1004
 
 
1005
 
  if(!ifoRead_PGC(ifofile, ifofile->first_play_pgc,
1006
 
                  ifofile->vmgi_mat->first_play_pgc)) {
1007
 
    free(ifofile->first_play_pgc);
1008
 
    ifofile->first_play_pgc = 0;
1009
 
    return 0;
1010
 
  }
1011
 
 
1012
 
  return 1;
1013
 
}
1014
 
 
1015
 
static void ifoFree_PGC(pgc_t *pgc) {
1016
 
  if(pgc) {
1017
 
    ifoFree_PGC_COMMAND_TBL(pgc->command_tbl);
1018
 
    if(pgc->program_map)
1019
 
      free(pgc->program_map);
1020
 
    if(pgc->cell_playback)
1021
 
      free(pgc->cell_playback);
1022
 
    if(pgc->cell_position)
1023
 
      free(pgc->cell_position);
1024
 
  }
1025
 
}
1026
 
 
1027
 
void ifoFree_FP_PGC(ifo_handle_t *ifofile) {
1028
 
  if(!ifofile)
1029
 
    return;
1030
 
 
1031
 
  if(ifofile->first_play_pgc) {
1032
 
    ifoFree_PGC(ifofile->first_play_pgc);
1033
 
    free(ifofile->first_play_pgc);
1034
 
    ifofile->first_play_pgc = 0;
1035
 
  }
1036
 
}
1037
 
 
1038
 
 
1039
 
int ifoRead_TT_SRPT(ifo_handle_t *ifofile) {
1040
 
  tt_srpt_t *tt_srpt;
1041
 
  int i, info_length;
1042
 
 
1043
 
  if(!ifofile)
1044
 
    return 0;
1045
 
 
1046
 
  if(!ifofile->vmgi_mat)
1047
 
    return 0;
1048
 
 
1049
 
  if(ifofile->vmgi_mat->tt_srpt == 0) /* mandatory */
1050
 
    return 0;
1051
 
 
1052
 
  if(!DVDFileSeek_(ifofile->file, ifofile->vmgi_mat->tt_srpt * DVD_BLOCK_LEN))
1053
 
    return 0;
1054
 
 
1055
 
  tt_srpt = (tt_srpt_t *)malloc(sizeof(tt_srpt_t));
1056
 
  if(!tt_srpt)
1057
 
    return 0;
1058
 
 
1059
 
  ifofile->tt_srpt = tt_srpt;
1060
 
 
1061
 
  if(!(DVDReadBytes(ifofile->file, tt_srpt, TT_SRPT_SIZE))) {
1062
 
    fprintf(stderr, "libdvdread: Unable to read read TT_SRPT.\n");
1063
 
    free(tt_srpt);
1064
 
    return 0;
1065
 
  }
1066
 
 
1067
 
  B2N_16(tt_srpt->nr_of_srpts);
1068
 
  B2N_32(tt_srpt->last_byte);
1069
 
 
1070
 
  info_length = tt_srpt->last_byte + 1 - TT_SRPT_SIZE;
1071
 
 
1072
 
  tt_srpt->title = (title_info_t *)malloc(info_length);
1073
 
  if(!tt_srpt->title) {
1074
 
    free(tt_srpt);
1075
 
    ifofile->tt_srpt = 0;
1076
 
    return 0;
1077
 
  }
1078
 
  if(!(DVDReadBytes(ifofile->file, tt_srpt->title, info_length))) {
1079
 
    fprintf(stderr, "libdvdread: Unable to read read TT_SRPT.\n");
1080
 
    ifoFree_TT_SRPT(ifofile);
1081
 
    return 0;
1082
 
  }
1083
 
 
1084
 
  for(i =  0; i < tt_srpt->nr_of_srpts; i++) {
1085
 
    B2N_16(tt_srpt->title[i].nr_of_ptts);
1086
 
    B2N_16(tt_srpt->title[i].parental_id);
1087
 
    B2N_32(tt_srpt->title[i].title_set_sector);
1088
 
  }
1089
 
 
1090
 
 
1091
 
  CHECK_ZERO(tt_srpt->zero_1);
1092
 
  CHECK_VALUE(tt_srpt->nr_of_srpts != 0);
1093
 
  CHECK_VALUE(tt_srpt->nr_of_srpts < 100); /* ?? */
1094
 
  CHECK_VALUE((int)tt_srpt->nr_of_srpts * sizeof(title_info_t) <= info_length);
1095
 
 
1096
 
  for(i = 0; i < tt_srpt->nr_of_srpts; i++) {
1097
 
    read_playback_type(&tt_srpt->title[i].pb_ty);
1098
 
    CHECK_VALUE(tt_srpt->title[i].pb_ty.zero_1 == 0);
1099
 
    CHECK_VALUE(tt_srpt->title[i].nr_of_angles != 0);
1100
 
    CHECK_VALUE(tt_srpt->title[i].nr_of_angles < 10);
1101
 
    /* CHECK_VALUE(tt_srpt->title[i].nr_of_ptts != 0); */
1102
 
    /* XXX: this assertion breaks Ghostbusters: */
1103
 
    CHECK_VALUE(tt_srpt->title[i].nr_of_ptts < 1000); /* ?? */
1104
 
    CHECK_VALUE(tt_srpt->title[i].title_set_nr != 0);
1105
 
    CHECK_VALUE(tt_srpt->title[i].title_set_nr < 100); /* ?? */
1106
 
    CHECK_VALUE(tt_srpt->title[i].vts_ttn != 0);
1107
 
    CHECK_VALUE(tt_srpt->title[i].vts_ttn < 100); /* ?? */
1108
 
    /* CHECK_VALUE(tt_srpt->title[i].title_set_sector != 0); */
1109
 
  }
1110
 
 
1111
 
  /* Make this a function */
1112
 
#if 0
1113
 
  if(memcmp((uint8_t *)tt_srpt->title +
1114
 
            tt_srpt->nr_of_srpts * sizeof(title_info_t),
1115
 
            my_friendly_zeros,
1116
 
            info_length - tt_srpt->nr_of_srpts * sizeof(title_info_t))) {
1117
 
    fprintf(stderr, "VMG_PTT_SRPT slack is != 0, ");
1118
 
    hexdump((uint8_t *)tt_srpt->title +
1119
 
            tt_srpt->nr_of_srpts * sizeof(title_info_t),
1120
 
            info_length - tt_srpt->nr_of_srpts * sizeof(title_info_t));
1121
 
  }
1122
 
#endif
1123
 
 
1124
 
  return 1;
1125
 
}
1126
 
 
1127
 
 
1128
 
void ifoFree_TT_SRPT(ifo_handle_t *ifofile) {
1129
 
  if(!ifofile)
1130
 
    return;
1131
 
 
1132
 
  if(ifofile->tt_srpt) {
1133
 
    free(ifofile->tt_srpt->title);
1134
 
    free(ifofile->tt_srpt);
1135
 
    ifofile->tt_srpt = 0;
1136
 
  }
1137
 
}
1138
 
 
1139
 
 
1140
 
int ifoRead_VTS_PTT_SRPT(ifo_handle_t *ifofile) {
1141
 
  vts_ptt_srpt_t *vts_ptt_srpt = NULL;
1142
 
  int info_length, i, j;
1143
 
  uint32_t *data = NULL;
1144
 
 
1145
 
  if(!ifofile)
1146
 
    return 0;
1147
 
 
1148
 
  if(!ifofile->vtsi_mat)
1149
 
    return 0;
1150
 
 
1151
 
  if(ifofile->vtsi_mat->vts_ptt_srpt == 0) /* mandatory */
1152
 
    return 0;
1153
 
 
1154
 
  if(!DVDFileSeek_(ifofile->file,
1155
 
                   ifofile->vtsi_mat->vts_ptt_srpt * DVD_BLOCK_LEN))
1156
 
    return 0;
1157
 
 
1158
 
  vts_ptt_srpt = malloc(sizeof(vts_ptt_srpt_t));
1159
 
  if(!vts_ptt_srpt)
1160
 
    return 0;
1161
 
 
1162
 
  vts_ptt_srpt->title = NULL;
1163
 
  ifofile->vts_ptt_srpt = vts_ptt_srpt;
1164
 
 
1165
 
  if(!(DVDReadBytes(ifofile->file, vts_ptt_srpt, VTS_PTT_SRPT_SIZE))) {
1166
 
    fprintf(stderr, "libdvdread: Unable to read PTT search table.\n");
1167
 
    goto fail;
1168
 
  }
1169
 
 
1170
 
  B2N_16(vts_ptt_srpt->nr_of_srpts);
1171
 
  B2N_32(vts_ptt_srpt->last_byte);
1172
 
 
1173
 
  CHECK_ZERO(vts_ptt_srpt->zero_1);
1174
 
  CHECK_VALUE(vts_ptt_srpt->nr_of_srpts != 0);
1175
 
  CHECK_VALUE(vts_ptt_srpt->nr_of_srpts < 100); /* ?? */
1176
 
 
1177
 
  info_length = vts_ptt_srpt->last_byte + 1 - VTS_PTT_SRPT_SIZE;
1178
 
  data = malloc(info_length);
1179
 
  if(!data)
1180
 
    goto fail;
1181
 
 
1182
 
  if(!(DVDReadBytes(ifofile->file, data, info_length))) {
1183
 
    fprintf(stderr, "libdvdread: Unable to read PTT search table.\n");
1184
 
    goto fail;
1185
 
  }
1186
 
 
1187
 
  if(vts_ptt_srpt->nr_of_srpts > info_length / sizeof(*data)) {
1188
 
    fprintf(stderr, "libdvdread: PTT search table too small.\n");
1189
 
    goto fail;
1190
 
  }
1191
 
  for(i = 0; i < vts_ptt_srpt->nr_of_srpts; i++) {
1192
 
    /* Transformers 3 has PTT start bytes that point outside the SRPT PTT */
1193
 
    uint32_t start = data[i];
1194
 
    B2N_32(start);
1195
 
    if(start + sizeof(ptt_info_t) > vts_ptt_srpt->last_byte + 1) {
1196
 
      /* don't mess with any bytes beyond the end of the allocation */
1197
 
      vts_ptt_srpt->nr_of_srpts = i;
1198
 
      break;
1199
 
    }
1200
 
    data[i] = start;
1201
 
    /* assert(data[i] + sizeof(ptt_info_t) <= vts_ptt_srpt->last_byte + 1);
1202
 
       Magic Knight Rayearth Daybreak is mastered very strange and has
1203
 
       Titles with 0 PTTs. They all have a data[i] offsets beyond the end of
1204
 
       of the vts_ptt_srpt structure. */
1205
 
    CHECK_VALUE(data[i] + sizeof(ptt_info_t) <= vts_ptt_srpt->last_byte + 1 + 4);
1206
 
  }
1207
 
 
1208
 
  vts_ptt_srpt->ttu_offset = data;
1209
 
 
1210
 
  vts_ptt_srpt->title = malloc(vts_ptt_srpt->nr_of_srpts * sizeof(ttu_t));
1211
 
  if(!vts_ptt_srpt->title)
1212
 
    goto fail;
1213
 
 
1214
 
  for(i = 0; i < vts_ptt_srpt->nr_of_srpts; i++) {
1215
 
    int n;
1216
 
    if(i < vts_ptt_srpt->nr_of_srpts - 1)
1217
 
      n = (data[i+1] - data[i]);
1218
 
    else
1219
 
      n = (vts_ptt_srpt->last_byte + 1 - data[i]);
1220
 
 
1221
 
    /* assert(n > 0 && (n % 4) == 0);
1222
 
       Magic Knight Rayearth Daybreak is mastered very strange and has
1223
 
       Titles with 0 PTTs. */
1224
 
    if(n < 0) n = 0;
1225
 
 
1226
 
    CHECK_VALUE(n % 4 == 0);
1227
 
 
1228
 
    vts_ptt_srpt->title[i].nr_of_ptts = n / 4;
1229
 
    vts_ptt_srpt->title[i].ptt = malloc(n * sizeof(ptt_info_t));
1230
 
    if(!vts_ptt_srpt->title[i].ptt) {
1231
 
      for(n = 0; n < i; n++)
1232
 
        free(vts_ptt_srpt->title[n].ptt);
1233
 
 
1234
 
      goto fail;
1235
 
    }
1236
 
    for(j = 0; j < vts_ptt_srpt->title[i].nr_of_ptts; j++) {
1237
 
      /* The assert placed here because of Magic Knight Rayearth Daybreak */
1238
 
      CHECK_VALUE(data[i] + sizeof(ptt_info_t) <= vts_ptt_srpt->last_byte + 1);
1239
 
      vts_ptt_srpt->title[i].ptt[j].pgcn
1240
 
        = *(uint16_t*)(((char *)data) + data[i] + 4*j - VTS_PTT_SRPT_SIZE);
1241
 
      vts_ptt_srpt->title[i].ptt[j].pgn
1242
 
        = *(uint16_t*)(((char *)data) + data[i] + 4*j + 2 - VTS_PTT_SRPT_SIZE);
1243
 
    }
1244
 
  }
1245
 
 
1246
 
  for(i = 0; i < vts_ptt_srpt->nr_of_srpts; i++) {
1247
 
    for(j = 0; j < vts_ptt_srpt->title[i].nr_of_ptts; j++) {
1248
 
      B2N_16(vts_ptt_srpt->title[i].ptt[j].pgcn);
1249
 
      B2N_16(vts_ptt_srpt->title[i].ptt[j].pgn);
1250
 
    }
1251
 
  }
1252
 
 
1253
 
  for(i = 0; i < vts_ptt_srpt->nr_of_srpts; i++) {
1254
 
    CHECK_VALUE(vts_ptt_srpt->title[i].nr_of_ptts < 1000); /* ?? */
1255
 
    for(j = 0; j < vts_ptt_srpt->title[i].nr_of_ptts; j++) {
1256
 
      CHECK_VALUE(vts_ptt_srpt->title[i].ptt[j].pgcn != 0 );
1257
 
      CHECK_VALUE(vts_ptt_srpt->title[i].ptt[j].pgcn < 1000); /* ?? */
1258
 
      CHECK_VALUE(vts_ptt_srpt->title[i].ptt[j].pgn != 0);
1259
 
      CHECK_VALUE(vts_ptt_srpt->title[i].ptt[j].pgn < 100); /* ?? */
1260
 
    }
1261
 
  }
1262
 
 
1263
 
  return 1;
1264
 
 
1265
 
fail:
1266
 
  free(data);
1267
 
  ifofile->vts_ptt_srpt = 0;
1268
 
  free(vts_ptt_srpt->title);
1269
 
  free(vts_ptt_srpt);
1270
 
  return 0;
1271
 
}
1272
 
 
1273
 
 
1274
 
void ifoFree_VTS_PTT_SRPT(ifo_handle_t *ifofile) {
1275
 
  if(!ifofile)
1276
 
    return;
1277
 
 
1278
 
  if(ifofile->vts_ptt_srpt) {
1279
 
    int i;
1280
 
    for(i = 0; i < ifofile->vts_ptt_srpt->nr_of_srpts; i++)
1281
 
      free(ifofile->vts_ptt_srpt->title[i].ptt);
1282
 
    free(ifofile->vts_ptt_srpt->ttu_offset);
1283
 
    free(ifofile->vts_ptt_srpt->title);
1284
 
    free(ifofile->vts_ptt_srpt);
1285
 
    ifofile->vts_ptt_srpt = 0;
1286
 
  }
1287
 
}
1288
 
 
1289
 
 
1290
 
int ifoRead_PTL_MAIT(ifo_handle_t *ifofile) {
1291
 
  ptl_mait_t *ptl_mait;
1292
 
  int info_length;
1293
 
  unsigned int i, j;
1294
 
 
1295
 
  if(!ifofile)
1296
 
    return 0;
1297
 
 
1298
 
  if(!ifofile->vmgi_mat)
1299
 
    return 0;
1300
 
 
1301
 
  if(ifofile->vmgi_mat->ptl_mait == NULL)
1302
 
    return 1;
1303
 
 
1304
 
  if(!DVDFileSeek_(ifofile->file, ifofile->vmgi_mat->ptl_mait * DVD_BLOCK_LEN))
1305
 
    return 0;
1306
 
 
1307
 
  ptl_mait = (ptl_mait_t *)malloc(sizeof(ptl_mait_t));
1308
 
  if(!ptl_mait)
1309
 
    return 0;
1310
 
 
1311
 
  ifofile->ptl_mait = ptl_mait;
1312
 
 
1313
 
  if(!(DVDReadBytes(ifofile->file, ptl_mait, PTL_MAIT_SIZE))) {
1314
 
    free(ptl_mait);
1315
 
    ifofile->ptl_mait = NULL;
1316
 
    return 0;
1317
 
  }
1318
 
 
1319
 
  B2N_16(ptl_mait->nr_of_countries);
1320
 
  B2N_16(ptl_mait->nr_of_vtss);
1321
 
  B2N_32(ptl_mait->last_byte);
1322
 
 
1323
 
  CHECK_VALUE(ptl_mait->nr_of_countries != 0);
1324
 
  CHECK_VALUE(ptl_mait->nr_of_countries < 100); /* ?? */
1325
 
  CHECK_VALUE(ptl_mait->nr_of_vtss != 0);
1326
 
  CHECK_VALUE(ptl_mait->nr_of_vtss < 100); /* ?? */
1327
 
  CHECK_VALUE(ptl_mait->nr_of_countries * PTL_MAIT_COUNTRY_SIZE
1328
 
              <= ptl_mait->last_byte + 1 - PTL_MAIT_SIZE);
1329
 
 
1330
 
  info_length = ptl_mait->nr_of_countries * sizeof(ptl_mait_country_t);
1331
 
  ptl_mait->countries = (ptl_mait_country_t *)malloc(info_length);
1332
 
  if(!ptl_mait->countries) {
1333
 
    free(ptl_mait);
1334
 
    ifofile->ptl_mait = NULL;
1335
 
    return 0;
1336
 
  }
1337
 
  for(i = 0; i < ptl_mait->nr_of_countries; i++) {
1338
 
    ptl_mait->countries[i].pf_ptl_mai = NULL;
1339
 
  }
1340
 
 
1341
 
  for(i = 0; i < ptl_mait->nr_of_countries; i++) {
1342
 
    if(!(DVDReadBytes(ifofile->file, &ptl_mait->countries[i], PTL_MAIT_COUNTRY_SIZE))) {
1343
 
      fprintf(stderr, "libdvdread: Unable to read PTL_MAIT.\n");
1344
 
      free(ptl_mait->countries);
1345
 
      free(ptl_mait);
1346
 
      ifofile->ptl_mait = NULL;
1347
 
      return 0;
1348
 
    }
1349
 
  }
1350
 
 
1351
 
  for(i = 0; i < ptl_mait->nr_of_countries; i++) {
1352
 
    B2N_16(ptl_mait->countries[i].country_code);
1353
 
    B2N_16(ptl_mait->countries[i].pf_ptl_mai_start_byte);
1354
 
  }
1355
 
 
1356
 
  for(i = 0; i < ptl_mait->nr_of_countries; i++) {
1357
 
    CHECK_ZERO(ptl_mait->countries[i].zero_1);
1358
 
    CHECK_ZERO(ptl_mait->countries[i].zero_2);
1359
 
    CHECK_VALUE(ptl_mait->countries[i].pf_ptl_mai_start_byte
1360
 
                + sizeof(pf_level_t) * (ptl_mait->nr_of_vtss + 1) <= ptl_mait->last_byte + 1);
1361
 
  }
1362
 
 
1363
 
  for(i = 0; i < ptl_mait->nr_of_countries; i++) {
1364
 
    uint16_t *pf_temp;
1365
 
 
1366
 
    if(!DVDFileSeek_(ifofile->file,
1367
 
                     ifofile->vmgi_mat->ptl_mait * DVD_BLOCK_LEN
1368
 
                     + ptl_mait->countries[i].pf_ptl_mai_start_byte)) {
1369
 
      fprintf(stderr, "libdvdread: Unable to seek PTL_MAIT table at index %d.\n",i);
1370
 
      free(ptl_mait->countries);
1371
 
      free(ptl_mait);
1372
 
      ifofile->ptl_mait = NULL;
1373
 
      return 0;
1374
 
    }
1375
 
    info_length = (ptl_mait->nr_of_vtss + 1) * sizeof(pf_level_t);
1376
 
    pf_temp = (uint16_t *)malloc(info_length);
1377
 
    if(!pf_temp) {
1378
 
      free_ptl_mait(ptl_mait, i);
1379
 
      ifofile->ptl_mait = NULL;
1380
 
      return 0;
1381
 
    }
1382
 
    memset(pf_temp, 0, info_length);
1383
 
    if(!(DVDReadBytes(ifofile->file, pf_temp, info_length))) {
1384
 
      fprintf(stderr, "libdvdread: Unable to read PTL_MAIT table at index %d.\n",i);
1385
 
      free(pf_temp);
1386
 
      free_ptl_mait(ptl_mait, i);
1387
 
      ifofile->ptl_mait = NULL;
1388
 
      return 0;
1389
 
    }
1390
 
    for (j = 0; j < ((ptl_mait->nr_of_vtss + 1) * 8); j++) {
1391
 
      B2N_16(pf_temp[j]);
1392
 
    }
1393
 
    ptl_mait->countries[i].pf_ptl_mai = (pf_level_t *)malloc(info_length);
1394
 
    if(!ptl_mait->countries[i].pf_ptl_mai) {
1395
 
      free(pf_temp);
1396
 
      free_ptl_mait(ptl_mait, i);
1397
 
      ifofile->ptl_mait = NULL;
1398
 
      return 0;
1399
 
    }
1400
 
    { /* Transpose the array so we can use C indexing. */
1401
 
      int level, vts;
1402
 
      for(level = 0; level < PTL_MAIT_NUM_LEVEL; level++) {
1403
 
        for(vts = 0; vts <= ptl_mait->nr_of_vtss; vts++) {
1404
 
          ptl_mait->countries[i].pf_ptl_mai[vts][level] =
1405
 
            pf_temp[(7-level)*(ptl_mait->nr_of_vtss+1) + vts];
1406
 
        }
1407
 
      }
1408
 
      free(pf_temp);
1409
 
    }
1410
 
  }
1411
 
  return 1;
1412
 
}
1413
 
 
1414
 
void ifoFree_PTL_MAIT(ifo_handle_t *ifofile) {
1415
 
  unsigned int i;
1416
 
 
1417
 
  if(!ifofile)
1418
 
    return;
1419
 
 
1420
 
  if(ifofile->ptl_mait) {
1421
 
    for(i = 0; i < ifofile->ptl_mait->nr_of_countries; i++) {
1422
 
      free(ifofile->ptl_mait->countries[i].pf_ptl_mai);
1423
 
    }
1424
 
    free(ifofile->ptl_mait->countries);
1425
 
    free(ifofile->ptl_mait);
1426
 
    ifofile->ptl_mait = NULL;
1427
 
  }
1428
 
}
1429
 
 
1430
 
int ifoRead_VTS_TMAPT(ifo_handle_t *ifofile) {
1431
 
  vts_tmapt_t *vts_tmapt;
1432
 
  uint32_t *vts_tmap_srp;
1433
 
  unsigned int offset;
1434
 
  int info_length;
1435
 
  unsigned int i, j;
1436
 
 
1437
 
  if(!ifofile)
1438
 
    return 0;
1439
 
 
1440
 
  if(!ifofile->vtsi_mat)
1441
 
    return 0;
1442
 
 
1443
 
  if(ifofile->vtsi_mat->vts_tmapt == 0) { /* optional(?) */
1444
 
    ifofile->vts_tmapt = NULL;
1445
 
    fprintf(stderr,"Please send bug report - no VTS_TMAPT ?? \n");
1446
 
    return 1;
1447
 
  }
1448
 
 
1449
 
  offset = ifofile->vtsi_mat->vts_tmapt * DVD_BLOCK_LEN;
1450
 
 
1451
 
  if(!DVDFileSeek_(ifofile->file, offset))
1452
 
    return 0;
1453
 
 
1454
 
  vts_tmapt = (vts_tmapt_t *)malloc(sizeof(vts_tmapt_t));
1455
 
  if(!vts_tmapt)
1456
 
    return 0;
1457
 
 
1458
 
  ifofile->vts_tmapt = vts_tmapt;
1459
 
 
1460
 
  if(!(DVDReadBytes(ifofile->file, vts_tmapt, VTS_TMAPT_SIZE))) {
1461
 
    fprintf(stderr, "libdvdread: Unable to read VTS_TMAPT.\n");
1462
 
    free(vts_tmapt);
1463
 
    ifofile->vts_tmapt = NULL;
1464
 
    return 0;
1465
 
  }
1466
 
 
1467
 
  B2N_16(vts_tmapt->nr_of_tmaps);
1468
 
  B2N_32(vts_tmapt->last_byte);
1469
 
 
1470
 
  CHECK_ZERO(vts_tmapt->zero_1);
1471
 
 
1472
 
  info_length = vts_tmapt->nr_of_tmaps * 4;
1473
 
 
1474
 
  vts_tmap_srp = (uint32_t *)malloc(info_length);
1475
 
  if(!vts_tmap_srp) {
1476
 
    free(vts_tmapt);
1477
 
    ifofile->vts_tmapt = NULL;
1478
 
    return 0;
1479
 
  }
1480
 
 
1481
 
  vts_tmapt->tmap_offset = vts_tmap_srp;
1482
 
 
1483
 
  if(!(DVDReadBytes(ifofile->file, vts_tmap_srp, info_length))) {
1484
 
    fprintf(stderr, "libdvdread: Unable to read VTS_TMAPT.\n");
1485
 
    free(vts_tmap_srp);
1486
 
    free(vts_tmapt);
1487
 
    ifofile->vts_tmapt = NULL;
1488
 
    return 0;
1489
 
  }
1490
 
 
1491
 
  for (i = 0; i < vts_tmapt->nr_of_tmaps; i++) {
1492
 
    B2N_32(vts_tmap_srp[i]);
1493
 
  }
1494
 
 
1495
 
 
1496
 
  info_length = vts_tmapt->nr_of_tmaps * sizeof(vts_tmap_t);
1497
 
 
1498
 
  vts_tmapt->tmap = (vts_tmap_t *)malloc(info_length);
1499
 
  if(!vts_tmapt->tmap) {
1500
 
    free(vts_tmap_srp);
1501
 
    free(vts_tmapt);
1502
 
    ifofile->vts_tmapt = NULL;
1503
 
    return 0;
1504
 
  }
1505
 
 
1506
 
  memset(vts_tmapt->tmap, 0, info_length); /* So ifoFree_VTS_TMAPT works. */
1507
 
 
1508
 
  for(i = 0; i < vts_tmapt->nr_of_tmaps; i++) {
1509
 
    if(!DVDFileSeek_(ifofile->file, offset + vts_tmap_srp[i])) {
1510
 
      ifoFree_VTS_TMAPT(ifofile);
1511
 
      return 0;
1512
 
    }
1513
 
 
1514
 
    if(!(DVDReadBytes(ifofile->file, &vts_tmapt->tmap[i], VTS_TMAP_SIZE))) {
1515
 
      fprintf(stderr, "libdvdread: Unable to read VTS_TMAP.\n");
1516
 
      ifoFree_VTS_TMAPT(ifofile);
1517
 
      return 0;
1518
 
    }
1519
 
 
1520
 
    B2N_16(vts_tmapt->tmap[i].nr_of_entries);
1521
 
    CHECK_ZERO(vts_tmapt->tmap[i].zero_1);
1522
 
 
1523
 
    if(vts_tmapt->tmap[i].nr_of_entries == 0) { /* Early out if zero entries */
1524
 
      vts_tmapt->tmap[i].map_ent = NULL;
1525
 
      continue;
1526
 
    }
1527
 
 
1528
 
    info_length = vts_tmapt->tmap[i].nr_of_entries * sizeof(map_ent_t);
1529
 
 
1530
 
    vts_tmapt->tmap[i].map_ent = (map_ent_t *)malloc(info_length);
1531
 
    if(!vts_tmapt->tmap[i].map_ent) {
1532
 
      ifoFree_VTS_TMAPT(ifofile);
1533
 
      return 0;
1534
 
    }
1535
 
 
1536
 
    if(!(DVDReadBytes(ifofile->file, vts_tmapt->tmap[i].map_ent, info_length))) {
1537
 
      fprintf(stderr, "libdvdread: Unable to read VTS_TMAP_ENT.\n");
1538
 
      ifoFree_VTS_TMAPT(ifofile);
1539
 
      return 0;
1540
 
    }
1541
 
 
1542
 
    for(j = 0; j < vts_tmapt->tmap[i].nr_of_entries; j++)
1543
 
      B2N_32(vts_tmapt->tmap[i].map_ent[j]);
1544
 
  }
1545
 
 
1546
 
  return 1;
1547
 
}
1548
 
 
1549
 
void ifoFree_VTS_TMAPT(ifo_handle_t *ifofile) {
1550
 
  unsigned int i;
1551
 
 
1552
 
  if(!ifofile)
1553
 
    return;
1554
 
 
1555
 
  if(ifofile->vts_tmapt) {
1556
 
    for(i = 0; i < ifofile->vts_tmapt->nr_of_tmaps; i++)
1557
 
      if(ifofile->vts_tmapt->tmap[i].map_ent)
1558
 
        free(ifofile->vts_tmapt->tmap[i].map_ent);
1559
 
    free(ifofile->vts_tmapt->tmap);
1560
 
    free(ifofile->vts_tmapt->tmap_offset);
1561
 
    free(ifofile->vts_tmapt);
1562
 
    ifofile->vts_tmapt = NULL;
1563
 
  }
1564
 
}
1565
 
 
1566
 
 
1567
 
int ifoRead_TITLE_C_ADT(ifo_handle_t *ifofile) {
1568
 
 
1569
 
  if(!ifofile)
1570
 
    return 0;
1571
 
 
1572
 
  if(!ifofile->vtsi_mat)
1573
 
    return 0;
1574
 
 
1575
 
  if(ifofile->vtsi_mat->vts_c_adt == 0) /* mandatory */
1576
 
    return 0;
1577
 
 
1578
 
  ifofile->vts_c_adt = (c_adt_t *)malloc(sizeof(c_adt_t));
1579
 
  if(!ifofile->vts_c_adt)
1580
 
    return 0;
1581
 
 
1582
 
  if(!ifoRead_C_ADT_internal(ifofile, ifofile->vts_c_adt,
1583
 
                             ifofile->vtsi_mat->vts_c_adt)) {
1584
 
    free(ifofile->vts_c_adt);
1585
 
    ifofile->vts_c_adt = 0;
1586
 
    return 0;
1587
 
  }
1588
 
 
1589
 
  return 1;
1590
 
}
1591
 
 
1592
 
int ifoRead_C_ADT(ifo_handle_t *ifofile) {
1593
 
  unsigned int sector;
1594
 
 
1595
 
  if(!ifofile)
1596
 
    return 0;
1597
 
 
1598
 
  if(ifofile->vmgi_mat) {
1599
 
    if(ifofile->vmgi_mat->vmgm_c_adt == 0)
1600
 
      return 1;
1601
 
    sector = ifofile->vmgi_mat->vmgm_c_adt;
1602
 
  } else if(ifofile->vtsi_mat) {
1603
 
    if(ifofile->vtsi_mat->vtsm_c_adt == 0)
1604
 
      return 1;
1605
 
    sector = ifofile->vtsi_mat->vtsm_c_adt;
1606
 
  } else {
1607
 
    return 0;
1608
 
  }
1609
 
 
1610
 
  ifofile->menu_c_adt = (c_adt_t *)malloc(sizeof(c_adt_t));
1611
 
  if(!ifofile->menu_c_adt)
1612
 
    return 0;
1613
 
 
1614
 
  if(!ifoRead_C_ADT_internal(ifofile, ifofile->menu_c_adt, sector)) {
1615
 
    free(ifofile->menu_c_adt);
1616
 
    ifofile->menu_c_adt = 0;
1617
 
    return 0;
1618
 
  }
1619
 
 
1620
 
  return 1;
1621
 
}
1622
 
 
1623
 
static int ifoRead_C_ADT_internal(ifo_handle_t *ifofile,
1624
 
                                  c_adt_t *c_adt, unsigned int sector) {
1625
 
  int i, info_length;
1626
 
 
1627
 
  if(!DVDFileSeek_(ifofile->file, sector * DVD_BLOCK_LEN))
1628
 
    return 0;
1629
 
 
1630
 
  if(!(DVDReadBytes(ifofile->file, c_adt, C_ADT_SIZE)))
1631
 
    return 0;
1632
 
 
1633
 
  B2N_16(c_adt->nr_of_vobs);
1634
 
  B2N_32(c_adt->last_byte);
1635
 
 
1636
 
  info_length = c_adt->last_byte + 1 - C_ADT_SIZE;
1637
 
 
1638
 
  CHECK_ZERO(c_adt->zero_1);
1639
 
  /* assert(c_adt->nr_of_vobs > 0);
1640
 
     Magic Knight Rayearth Daybreak is mastered very strange and has
1641
 
     Titles with a VOBS that has no cells. */
1642
 
  CHECK_VALUE(info_length % sizeof(cell_adr_t) == 0);
1643
 
 
1644
 
  /* assert(info_length / sizeof(cell_adr_t) >= c_adt->nr_of_vobs);
1645
 
     Enemy of the State region 2 (de) has Titles where nr_of_vobs field
1646
 
     is to high, they high ones are never referenced though. */
1647
 
  if(info_length / sizeof(cell_adr_t) < c_adt->nr_of_vobs) {
1648
 
    fprintf(stderr, "libdvdread: *C_ADT nr_of_vobs > available info entries\n");
1649
 
    c_adt->nr_of_vobs = info_length / sizeof(cell_adr_t);
1650
 
  }
1651
 
 
1652
 
  c_adt->cell_adr_table = (cell_adr_t *)malloc(info_length);
1653
 
  if(!c_adt->cell_adr_table)
1654
 
    return 0;
1655
 
 
1656
 
  if(info_length &&
1657
 
     !(DVDReadBytes(ifofile->file, c_adt->cell_adr_table, info_length))) {
1658
 
    free(c_adt->cell_adr_table);
1659
 
    return 0;
1660
 
  }
1661
 
 
1662
 
  for(i = 0; i < info_length/sizeof(cell_adr_t); i++) {
1663
 
    B2N_16(c_adt->cell_adr_table[i].vob_id);
1664
 
    B2N_32(c_adt->cell_adr_table[i].start_sector);
1665
 
    B2N_32(c_adt->cell_adr_table[i].last_sector);
1666
 
 
1667
 
    CHECK_ZERO(c_adt->cell_adr_table[i].zero_1);
1668
 
    CHECK_VALUE(c_adt->cell_adr_table[i].vob_id > 0);
1669
 
    CHECK_VALUE(c_adt->cell_adr_table[i].vob_id <= c_adt->nr_of_vobs);
1670
 
    CHECK_VALUE(c_adt->cell_adr_table[i].cell_id > 0);
1671
 
    CHECK_VALUE(c_adt->cell_adr_table[i].start_sector <
1672
 
                c_adt->cell_adr_table[i].last_sector);
1673
 
  }
1674
 
 
1675
 
  return 1;
1676
 
}
1677
 
 
1678
 
 
1679
 
static void ifoFree_C_ADT_internal(c_adt_t *c_adt) {
1680
 
  if(c_adt) {
1681
 
    free(c_adt->cell_adr_table);
1682
 
    free(c_adt);
1683
 
  }
1684
 
}
1685
 
 
1686
 
void ifoFree_C_ADT(ifo_handle_t *ifofile) {
1687
 
  if(!ifofile)
1688
 
    return;
1689
 
 
1690
 
  ifoFree_C_ADT_internal(ifofile->menu_c_adt);
1691
 
  ifofile->menu_c_adt = 0;
1692
 
}
1693
 
 
1694
 
void ifoFree_TITLE_C_ADT(ifo_handle_t *ifofile) {
1695
 
  if(!ifofile)
1696
 
    return;
1697
 
 
1698
 
  ifoFree_C_ADT_internal(ifofile->vts_c_adt);
1699
 
  ifofile->vts_c_adt = 0;
1700
 
}
1701
 
 
1702
 
int ifoRead_TITLE_VOBU_ADMAP(ifo_handle_t *ifofile) {
1703
 
  if(!ifofile)
1704
 
    return 0;
1705
 
 
1706
 
  if(!ifofile->vtsi_mat)
1707
 
    return 0;
1708
 
 
1709
 
  if(ifofile->vtsi_mat->vts_vobu_admap == 0) /* mandatory */
1710
 
    return 0;
1711
 
 
1712
 
  ifofile->vts_vobu_admap = (vobu_admap_t *)malloc(sizeof(vobu_admap_t));
1713
 
  if(!ifofile->vts_vobu_admap)
1714
 
    return 0;
1715
 
 
1716
 
  if(!ifoRead_VOBU_ADMAP_internal(ifofile, ifofile->vts_vobu_admap,
1717
 
                                  ifofile->vtsi_mat->vts_vobu_admap)) {
1718
 
    free(ifofile->vts_vobu_admap);
1719
 
    ifofile->vts_vobu_admap = 0;
1720
 
    return 0;
1721
 
  }
1722
 
 
1723
 
  return 1;
1724
 
}
1725
 
 
1726
 
int ifoRead_VOBU_ADMAP(ifo_handle_t *ifofile) {
1727
 
  unsigned int sector;
1728
 
 
1729
 
  if(!ifofile)
1730
 
    return 0;
1731
 
 
1732
 
  if(ifofile->vmgi_mat) {
1733
 
    if(ifofile->vmgi_mat->vmgm_vobu_admap == 0)
1734
 
      return 1;
1735
 
    sector = ifofile->vmgi_mat->vmgm_vobu_admap;
1736
 
  } else if(ifofile->vtsi_mat) {
1737
 
    if(ifofile->vtsi_mat->vtsm_vobu_admap == 0)
1738
 
      return 1;
1739
 
    sector = ifofile->vtsi_mat->vtsm_vobu_admap;
1740
 
  } else {
1741
 
    return 0;
1742
 
  }
1743
 
 
1744
 
  ifofile->menu_vobu_admap = (vobu_admap_t *)malloc(sizeof(vobu_admap_t));
1745
 
  if(!ifofile->menu_vobu_admap)
1746
 
    return 0;
1747
 
 
1748
 
  if(!ifoRead_VOBU_ADMAP_internal(ifofile, ifofile->menu_vobu_admap, sector)) {
1749
 
    free(ifofile->menu_vobu_admap);
1750
 
    ifofile->menu_vobu_admap = 0;
1751
 
    return 0;
1752
 
  }
1753
 
 
1754
 
  return 1;
1755
 
}
1756
 
 
1757
 
static int ifoRead_VOBU_ADMAP_internal(ifo_handle_t *ifofile,
1758
 
                                       vobu_admap_t *vobu_admap,
1759
 
                                       unsigned int sector) {
1760
 
  unsigned int i;
1761
 
  int info_length;
1762
 
 
1763
 
  if(!DVDFileSeekForce_(ifofile->file, sector * DVD_BLOCK_LEN, sector))
1764
 
    return 0;
1765
 
 
1766
 
  if(!(DVDReadBytes(ifofile->file, vobu_admap, VOBU_ADMAP_SIZE)))
1767
 
    return 0;
1768
 
 
1769
 
  B2N_32(vobu_admap->last_byte);
1770
 
 
1771
 
  info_length = vobu_admap->last_byte + 1 - VOBU_ADMAP_SIZE;
1772
 
  /* assert(info_length > 0);
1773
 
     Magic Knight Rayearth Daybreak is mastered very strange and has
1774
 
     Titles with a VOBS that has no VOBUs. */
1775
 
  CHECK_VALUE(info_length % sizeof(uint32_t) == 0);
1776
 
 
1777
 
  vobu_admap->vobu_start_sectors = (uint32_t *)malloc(info_length);
1778
 
  if(!vobu_admap->vobu_start_sectors) {
1779
 
    return 0;
1780
 
  }
1781
 
  if(info_length &&
1782
 
     !(DVDReadBytes(ifofile->file,
1783
 
                    vobu_admap->vobu_start_sectors, info_length))) {
1784
 
    free(vobu_admap->vobu_start_sectors);
1785
 
    return 0;
1786
 
  }
1787
 
 
1788
 
  for(i = 0; i < info_length/sizeof(uint32_t); i++)
1789
 
    B2N_32(vobu_admap->vobu_start_sectors[i]);
1790
 
 
1791
 
  return 1;
1792
 
}
1793
 
 
1794
 
 
1795
 
static void ifoFree_VOBU_ADMAP_internal(vobu_admap_t *vobu_admap) {
1796
 
  if(vobu_admap) {
1797
 
    free(vobu_admap->vobu_start_sectors);
1798
 
    free(vobu_admap);
1799
 
  }
1800
 
}
1801
 
 
1802
 
void ifoFree_VOBU_ADMAP(ifo_handle_t *ifofile) {
1803
 
  if(!ifofile)
1804
 
    return;
1805
 
 
1806
 
  ifoFree_VOBU_ADMAP_internal(ifofile->menu_vobu_admap);
1807
 
  ifofile->menu_vobu_admap = 0;
1808
 
}
1809
 
 
1810
 
void ifoFree_TITLE_VOBU_ADMAP(ifo_handle_t *ifofile) {
1811
 
  if(!ifofile)
1812
 
    return;
1813
 
 
1814
 
  ifoFree_VOBU_ADMAP_internal(ifofile->vts_vobu_admap);
1815
 
  ifofile->vts_vobu_admap = 0;
1816
 
}
1817
 
 
1818
 
int ifoRead_PGCIT(ifo_handle_t *ifofile) {
1819
 
 
1820
 
  if(!ifofile)
1821
 
    return 0;
1822
 
 
1823
 
  if(!ifofile->vtsi_mat)
1824
 
    return 0;
1825
 
 
1826
 
  if(ifofile->vtsi_mat->vts_pgcit == 0) /* mandatory */
1827
 
    return 0;
1828
 
 
1829
 
  ifofile->vts_pgcit = (pgcit_t *)malloc(sizeof(pgcit_t));
1830
 
  if(!ifofile->vts_pgcit)
1831
 
    return 0;
1832
 
 
1833
 
  if(!ifoRead_PGCIT_internal(ifofile, ifofile->vts_pgcit,
1834
 
                             ifofile->vtsi_mat->vts_pgcit * DVD_BLOCK_LEN)) {
1835
 
    free(ifofile->vts_pgcit);
1836
 
    ifofile->vts_pgcit = 0;
1837
 
    return 0;
1838
 
  }
1839
 
 
1840
 
  return 1;
1841
 
}
1842
 
 
1843
 
static int ifoRead_PGCIT_internal(ifo_handle_t *ifofile, pgcit_t *pgcit,
1844
 
                                  unsigned int offset) {
1845
 
  int i, info_length;
1846
 
  uint8_t *data, *ptr;
1847
 
 
1848
 
  if(!DVDFileSeek_(ifofile->file, offset))
1849
 
    return 0;
1850
 
 
1851
 
  if(!(DVDReadBytes(ifofile->file, pgcit, PGCIT_SIZE)))
1852
 
    return 0;
1853
 
 
1854
 
  B2N_16(pgcit->nr_of_pgci_srp);
1855
 
  B2N_32(pgcit->last_byte);
1856
 
 
1857
 
  CHECK_ZERO(pgcit->zero_1);
1858
 
  /* assert(pgcit->nr_of_pgci_srp != 0);
1859
 
     Magic Knight Rayearth Daybreak is mastered very strange and has
1860
 
     Titles with 0 PTTs. */
1861
 
  CHECK_VALUE(pgcit->nr_of_pgci_srp < 10000); /* ?? seen max of 1338 */
1862
 
 
1863
 
  info_length = pgcit->nr_of_pgci_srp * PGCI_SRP_SIZE;
1864
 
  data = malloc(info_length);
1865
 
  if(!data)
1866
 
    return 0;
1867
 
 
1868
 
  if(info_length && !(DVDReadBytes(ifofile->file, data, info_length))) {
1869
 
    free(data);
1870
 
    return 0;
1871
 
  }
1872
 
 
1873
 
  pgcit->pgci_srp = malloc(pgcit->nr_of_pgci_srp * sizeof(pgci_srp_t));
1874
 
  if(!pgcit->pgci_srp) {
1875
 
    free(data);
1876
 
    return 0;
1877
 
  }
1878
 
  ptr = data;
1879
 
  for(i = 0; i < pgcit->nr_of_pgci_srp; i++) {
1880
 
    memcpy(&pgcit->pgci_srp[i], ptr, PGCI_SRP_SIZE);
1881
 
    ptr += PGCI_SRP_SIZE;
1882
 
    read_pgci_srp(&pgcit->pgci_srp[i]);
1883
 
    CHECK_VALUE(pgcit->pgci_srp[i].unknown1 == 0);
1884
 
  }
1885
 
  free(data);
1886
 
 
1887
 
  for(i = 0; i < pgcit->nr_of_pgci_srp; i++)
1888
 
    CHECK_VALUE(pgcit->pgci_srp[i].pgc_start_byte + PGC_SIZE <= pgcit->last_byte+1);
1889
 
 
1890
 
  for(i = 0; i < pgcit->nr_of_pgci_srp; i++) {
1891
 
    pgcit->pgci_srp[i].pgc = malloc(sizeof(pgc_t));
1892
 
    if(!pgcit->pgci_srp[i].pgc) {
1893
 
      int j;
1894
 
      for(j = 0; j < i; j++) {
1895
 
        ifoFree_PGC(pgcit->pgci_srp[j].pgc);
1896
 
        free(pgcit->pgci_srp[j].pgc);
1897
 
      }
1898
 
      goto fail;
1899
 
    }
1900
 
    if(!ifoRead_PGC(ifofile, pgcit->pgci_srp[i].pgc,
1901
 
                    offset + pgcit->pgci_srp[i].pgc_start_byte)) {
1902
 
      int j;
1903
 
      for(j = 0; j < i; j++) {
1904
 
        ifoFree_PGC(pgcit->pgci_srp[j].pgc);
1905
 
        free(pgcit->pgci_srp[j].pgc);
1906
 
      }
1907
 
      free(pgcit->pgci_srp[i].pgc);
1908
 
      goto fail;
1909
 
    }
1910
 
  }
1911
 
 
1912
 
  return 1;
1913
 
fail:
1914
 
  free(pgcit->pgci_srp);
1915
 
  pgcit->pgci_srp = NULL;
1916
 
  return 0;
1917
 
}
1918
 
 
1919
 
static void ifoFree_PGCIT_internal(pgcit_t *pgcit) {
1920
 
  if(pgcit) {
1921
 
    int i;
1922
 
    for(i = 0; i < pgcit->nr_of_pgci_srp; i++)
1923
 
    {
1924
 
      ifoFree_PGC(pgcit->pgci_srp[i].pgc);
1925
 
      free(pgcit->pgci_srp[i].pgc);
1926
 
    }
1927
 
    free(pgcit->pgci_srp);
1928
 
  }
1929
 
}
1930
 
 
1931
 
void ifoFree_PGCIT(ifo_handle_t *ifofile) {
1932
 
  if(!ifofile)
1933
 
    return;
1934
 
 
1935
 
  if(ifofile->vts_pgcit) {
1936
 
    ifoFree_PGCIT_internal(ifofile->vts_pgcit);
1937
 
    free(ifofile->vts_pgcit);
1938
 
    ifofile->vts_pgcit = 0;
1939
 
  }
1940
 
}
1941
 
 
1942
 
 
1943
 
int ifoRead_PGCI_UT(ifo_handle_t *ifofile) {
1944
 
  pgci_ut_t *pgci_ut;
1945
 
  unsigned int sector;
1946
 
  unsigned int i;
1947
 
  int info_length;
1948
 
  uint8_t *data, *ptr;
1949
 
 
1950
 
  if(!ifofile)
1951
 
    return 0;
1952
 
 
1953
 
  if(ifofile->vmgi_mat) {
1954
 
    if(ifofile->vmgi_mat->vmgm_pgci_ut == 0)
1955
 
      return 1;
1956
 
    sector = ifofile->vmgi_mat->vmgm_pgci_ut;
1957
 
  } else if(ifofile->vtsi_mat) {
1958
 
    if(ifofile->vtsi_mat->vtsm_pgci_ut == 0)
1959
 
      return 1;
1960
 
    sector = ifofile->vtsi_mat->vtsm_pgci_ut;
1961
 
  } else {
1962
 
    return 0;
1963
 
  }
1964
 
 
1965
 
  ifofile->pgci_ut = (pgci_ut_t *)malloc(sizeof(pgci_ut_t));
1966
 
  if(!ifofile->pgci_ut)
1967
 
    return 0;
1968
 
 
1969
 
  if(!DVDFileSeek_(ifofile->file, sector * DVD_BLOCK_LEN)) {
1970
 
    free(ifofile->pgci_ut);
1971
 
    ifofile->pgci_ut = 0;
1972
 
    return 0;
1973
 
  }
1974
 
 
1975
 
  if(!(DVDReadBytes(ifofile->file, ifofile->pgci_ut, PGCI_UT_SIZE))) {
1976
 
    free(ifofile->pgci_ut);
1977
 
    ifofile->pgci_ut = 0;
1978
 
    return 0;
1979
 
  }
1980
 
 
1981
 
  pgci_ut = ifofile->pgci_ut;
1982
 
 
1983
 
  B2N_16(pgci_ut->nr_of_lus);
1984
 
  B2N_32(pgci_ut->last_byte);
1985
 
 
1986
 
  CHECK_ZERO(pgci_ut->zero_1);
1987
 
  CHECK_VALUE(pgci_ut->nr_of_lus != 0);
1988
 
  CHECK_VALUE(pgci_ut->nr_of_lus < 100); /* ?? 3-4 ? */
1989
 
  CHECK_VALUE((uint32_t)pgci_ut->nr_of_lus * PGCI_LU_SIZE < pgci_ut->last_byte);
1990
 
 
1991
 
  info_length = pgci_ut->nr_of_lus * PGCI_LU_SIZE;
1992
 
  data = malloc(info_length);
1993
 
  if(!data) {
1994
 
    free(pgci_ut);
1995
 
    ifofile->pgci_ut = 0;
1996
 
    return 0;
1997
 
  }
1998
 
  if(!(DVDReadBytes(ifofile->file, data, info_length))) {
1999
 
    free(data);
2000
 
    free(pgci_ut);
2001
 
    ifofile->pgci_ut = 0;
2002
 
    return 0;
2003
 
  }
2004
 
 
2005
 
  pgci_ut->lu = malloc(pgci_ut->nr_of_lus * sizeof(pgci_lu_t));
2006
 
  if(!pgci_ut->lu) {
2007
 
    free(data);
2008
 
    free(pgci_ut);
2009
 
    ifofile->pgci_ut = 0;
2010
 
    return 0;
2011
 
  }
2012
 
  ptr = data;
2013
 
  for(i = 0; i < pgci_ut->nr_of_lus; i++) {
2014
 
    memcpy(&pgci_ut->lu[i], ptr, PGCI_LU_SIZE);
2015
 
    ptr += PGCI_LU_SIZE;
2016
 
    B2N_16(pgci_ut->lu[i].lang_code);
2017
 
    B2N_32(pgci_ut->lu[i].lang_start_byte);
2018
 
  }
2019
 
  free(data);
2020
 
 
2021
 
  for(i = 0; i < pgci_ut->nr_of_lus; i++) {
2022
 
    /* Maybe this is only defined for v1.1 and later titles? */
2023
 
    /* If the bits in 'lu[i].exists' are enumerated abcd efgh then:
2024
 
       VTS_x_yy.IFO        VIDEO_TS.IFO
2025
 
       a == 0x83 "Root"         0x82 "Title"
2026
 
       b == 0x84 "Subpicture"
2027
 
       c == 0x85 "Audio"
2028
 
       d == 0x86 "Angle"
2029
 
       e == 0x87 "PTT"
2030
 
    */
2031
 
    CHECK_VALUE((pgci_ut->lu[i].exists & 0x07) == 0);
2032
 
  }
2033
 
 
2034
 
  for(i = 0; i < pgci_ut->nr_of_lus; i++) {
2035
 
    pgci_ut->lu[i].pgcit = malloc(sizeof(pgcit_t));
2036
 
    if(!pgci_ut->lu[i].pgcit) {
2037
 
      unsigned int j;
2038
 
      for(j = 0; j < i; j++) {
2039
 
        ifoFree_PGCIT_internal(pgci_ut->lu[j].pgcit);
2040
 
        free(pgci_ut->lu[j].pgcit);
2041
 
      }
2042
 
      free(pgci_ut->lu);
2043
 
      free(pgci_ut);
2044
 
      ifofile->pgci_ut = 0;
2045
 
      return 0;
2046
 
    }
2047
 
    if(!ifoRead_PGCIT_internal(ifofile, pgci_ut->lu[i].pgcit,
2048
 
                               sector * DVD_BLOCK_LEN
2049
 
                               + pgci_ut->lu[i].lang_start_byte)) {
2050
 
      unsigned int j;
2051
 
      for(j = 0; j < i; j++) {
2052
 
        ifoFree_PGCIT_internal(pgci_ut->lu[j].pgcit);
2053
 
        free(pgci_ut->lu[j].pgcit);
2054
 
      }
2055
 
      free(pgci_ut->lu[i].pgcit);
2056
 
      free(pgci_ut->lu);
2057
 
      free(pgci_ut);
2058
 
      ifofile->pgci_ut = 0;
2059
 
      return 0;
2060
 
    }
2061
 
    /* FIXME: Iterate and verify that all menus that should exists accordingly
2062
 
     * to pgci_ut->lu[i].exists really do? */
2063
 
  }
2064
 
 
2065
 
  return 1;
2066
 
}
2067
 
 
2068
 
 
2069
 
void ifoFree_PGCI_UT(ifo_handle_t *ifofile) {
2070
 
  unsigned int i;
2071
 
 
2072
 
  if(!ifofile)
2073
 
    return;
2074
 
 
2075
 
  if(ifofile->pgci_ut) {
2076
 
    for(i = 0; i < ifofile->pgci_ut->nr_of_lus; i++) {
2077
 
      ifoFree_PGCIT_internal(ifofile->pgci_ut->lu[i].pgcit);
2078
 
      free(ifofile->pgci_ut->lu[i].pgcit);
2079
 
    }
2080
 
    free(ifofile->pgci_ut->lu);
2081
 
    free(ifofile->pgci_ut);
2082
 
    ifofile->pgci_ut = 0;
2083
 
  }
2084
 
}
2085
 
 
2086
 
static int ifoRead_VTS_ATTRIBUTES(ifo_handle_t *ifofile,
2087
 
                                  vts_attributes_t *vts_attributes,
2088
 
                                  unsigned int offset) {
2089
 
  unsigned int i;
2090
 
 
2091
 
  if(!DVDFileSeek_(ifofile->file, offset))
2092
 
    return 0;
2093
 
 
2094
 
  if(!(DVDReadBytes(ifofile->file, vts_attributes, sizeof(vts_attributes_t))))
2095
 
    return 0;
2096
 
 
2097
 
  read_video_attr(&vts_attributes->vtsm_vobs_attr);
2098
 
  read_video_attr(&vts_attributes->vtstt_vobs_video_attr);
2099
 
  read_audio_attr(&vts_attributes->vtsm_audio_attr);
2100
 
  for(i=0; i<8; i++)
2101
 
    read_audio_attr(&vts_attributes->vtstt_audio_attr[i]);
2102
 
  read_subp_attr(&vts_attributes->vtsm_subp_attr);
2103
 
  for(i=0; i<32; i++)
2104
 
    read_subp_attr(&vts_attributes->vtstt_subp_attr[i]);
2105
 
  B2N_32(vts_attributes->last_byte);
2106
 
  B2N_32(vts_attributes->vts_cat);
2107
 
 
2108
 
  CHECK_ZERO(vts_attributes->zero_1);
2109
 
  CHECK_ZERO(vts_attributes->zero_2);
2110
 
  CHECK_ZERO(vts_attributes->zero_3);
2111
 
  CHECK_ZERO(vts_attributes->zero_4);
2112
 
  CHECK_ZERO(vts_attributes->zero_5);
2113
 
  CHECK_ZERO(vts_attributes->zero_6);
2114
 
  CHECK_ZERO(vts_attributes->zero_7);
2115
 
  CHECK_VALUE(vts_attributes->nr_of_vtsm_audio_streams <= 1);
2116
 
  CHECK_VALUE(vts_attributes->nr_of_vtsm_subp_streams <= 1);
2117
 
  CHECK_VALUE(vts_attributes->nr_of_vtstt_audio_streams <= 8);
2118
 
  for(i = vts_attributes->nr_of_vtstt_audio_streams; i < 8; i++)
2119
 
    CHECK_ZERO(vts_attributes->vtstt_audio_attr[i]);
2120
 
  CHECK_VALUE(vts_attributes->nr_of_vtstt_subp_streams <= 32);
2121
 
  {
2122
 
    unsigned int nr_coded;
2123
 
    CHECK_VALUE(vts_attributes->last_byte + 1 >= VTS_ATTRIBUTES_MIN_SIZE);
2124
 
    nr_coded = (vts_attributes->last_byte + 1 - VTS_ATTRIBUTES_MIN_SIZE)/6;
2125
 
    /* This is often nr_coded = 70, how do you know how many there really are? */
2126
 
    if(nr_coded > 32) { /* We haven't read more from disk/file anyway */
2127
 
      nr_coded = 32;
2128
 
    }
2129
 
    CHECK_VALUE(vts_attributes->nr_of_vtstt_subp_streams <= nr_coded);
2130
 
    for(i = vts_attributes->nr_of_vtstt_subp_streams; i < nr_coded; i++)
2131
 
      CHECK_ZERO(vts_attributes->vtstt_subp_attr[i]);
2132
 
  }
2133
 
 
2134
 
  return 1;
2135
 
}
2136
 
 
2137
 
 
2138
 
 
2139
 
int ifoRead_VTS_ATRT(ifo_handle_t *ifofile) {
2140
 
  vts_atrt_t *vts_atrt;
2141
 
  unsigned int i, info_length, sector;
2142
 
  uint32_t *data;
2143
 
 
2144
 
  if(!ifofile)
2145
 
    return 0;
2146
 
 
2147
 
  if(!ifofile->vmgi_mat)
2148
 
    return 0;
2149
 
 
2150
 
  if(ifofile->vmgi_mat->vts_atrt == 0) /* mandatory */
2151
 
    return 0;
2152
 
 
2153
 
  sector = ifofile->vmgi_mat->vts_atrt;
2154
 
  if(!DVDFileSeek_(ifofile->file, sector * DVD_BLOCK_LEN))
2155
 
    return 0;
2156
 
 
2157
 
  vts_atrt = (vts_atrt_t *)malloc(sizeof(vts_atrt_t));
2158
 
  if(!vts_atrt)
2159
 
    return 0;
2160
 
 
2161
 
  ifofile->vts_atrt = vts_atrt;
2162
 
 
2163
 
  if(!(DVDReadBytes(ifofile->file, vts_atrt, VTS_ATRT_SIZE))) {
2164
 
    free(vts_atrt);
2165
 
    ifofile->vts_atrt = 0;
2166
 
    return 0;
2167
 
  }
2168
 
 
2169
 
  B2N_16(vts_atrt->nr_of_vtss);
2170
 
  B2N_32(vts_atrt->last_byte);
2171
 
 
2172
 
  CHECK_ZERO(vts_atrt->zero_1);
2173
 
  CHECK_VALUE(vts_atrt->nr_of_vtss != 0);
2174
 
  CHECK_VALUE(vts_atrt->nr_of_vtss < 100); /* ?? */
2175
 
  CHECK_VALUE((uint32_t)vts_atrt->nr_of_vtss * (4 + VTS_ATTRIBUTES_MIN_SIZE) +
2176
 
              VTS_ATRT_SIZE < vts_atrt->last_byte + 1);
2177
 
 
2178
 
  info_length = vts_atrt->nr_of_vtss * sizeof(uint32_t);
2179
 
  data = (uint32_t *)malloc(info_length);
2180
 
  if(!data) {
2181
 
    free(vts_atrt);
2182
 
    ifofile->vts_atrt = 0;
2183
 
    return 0;
2184
 
  }
2185
 
 
2186
 
  vts_atrt->vts_atrt_offsets = data;
2187
 
 
2188
 
  if(!(DVDReadBytes(ifofile->file, data, info_length))) {
2189
 
    free(data);
2190
 
    free(vts_atrt);
2191
 
    ifofile->vts_atrt = 0;
2192
 
    return 0;
2193
 
  }
2194
 
 
2195
 
  for(i = 0; i < vts_atrt->nr_of_vtss; i++) {
2196
 
    B2N_32(data[i]);
2197
 
    CHECK_VALUE(data[i] + VTS_ATTRIBUTES_MIN_SIZE < vts_atrt->last_byte + 1);
2198
 
  }
2199
 
 
2200
 
  info_length = vts_atrt->nr_of_vtss * sizeof(vts_attributes_t);
2201
 
  vts_atrt->vts = (vts_attributes_t *)malloc(info_length);
2202
 
  if(!vts_atrt->vts) {
2203
 
    free(data);
2204
 
    free(vts_atrt);
2205
 
    ifofile->vts_atrt = 0;
2206
 
    return 0;
2207
 
  }
2208
 
  for(i = 0; i < vts_atrt->nr_of_vtss; i++) {
2209
 
    unsigned int offset = data[i];
2210
 
    if(!ifoRead_VTS_ATTRIBUTES(ifofile, &(vts_atrt->vts[i]),
2211
 
                               (sector * DVD_BLOCK_LEN) + offset)) {
2212
 
      free(data);
2213
 
      free(vts_atrt);
2214
 
      ifofile->vts_atrt = 0;
2215
 
      return 0;
2216
 
    }
2217
 
 
2218
 
    /* This assert cant be in ifoRead_VTS_ATTRIBUTES */
2219
 
    CHECK_VALUE(offset + vts_atrt->vts[i].last_byte <= vts_atrt->last_byte + 1);
2220
 
    /* Is this check correct? */
2221
 
  }
2222
 
 
2223
 
  return 1;
2224
 
}
2225
 
 
2226
 
 
2227
 
void ifoFree_VTS_ATRT(ifo_handle_t *ifofile) {
2228
 
  if(!ifofile)
2229
 
    return;
2230
 
 
2231
 
  if(ifofile->vts_atrt) {
2232
 
    free(ifofile->vts_atrt->vts);
2233
 
    free(ifofile->vts_atrt->vts_atrt_offsets);
2234
 
    free(ifofile->vts_atrt);
2235
 
    ifofile->vts_atrt = 0;
2236
 
  }
2237
 
}
2238
 
 
2239
 
 
2240
 
int ifoRead_TXTDT_MGI(ifo_handle_t *ifofile) {
2241
 
  txtdt_mgi_t *txtdt_mgi;
2242
 
 
2243
 
  if(!ifofile)
2244
 
    return 0;
2245
 
 
2246
 
  if(!ifofile->vmgi_mat)
2247
 
    return 0;
2248
 
 
2249
 
  /* Return successfully if there is nothing to read. */
2250
 
  if(ifofile->vmgi_mat->txtdt_mgi == 0)
2251
 
    return 1;
2252
 
 
2253
 
  if(!DVDFileSeek_(ifofile->file,
2254
 
                   ifofile->vmgi_mat->txtdt_mgi * DVD_BLOCK_LEN))
2255
 
    return 0;
2256
 
 
2257
 
  txtdt_mgi = (txtdt_mgi_t *)malloc(sizeof(txtdt_mgi_t));
2258
 
  if(!txtdt_mgi) {
2259
 
    return 0;
2260
 
  }
2261
 
  ifofile->txtdt_mgi = txtdt_mgi;
2262
 
 
2263
 
  if(!(DVDReadBytes(ifofile->file, txtdt_mgi, TXTDT_MGI_SIZE))) {
2264
 
    fprintf(stderr, "libdvdread: Unable to read TXTDT_MGI.\n");
2265
 
    free(txtdt_mgi);
2266
 
    ifofile->txtdt_mgi = 0;
2267
 
    return 0;
2268
 
  }
2269
 
 
2270
 
  /* fprintf(stderr, "-- Not done yet --\n"); */
2271
 
  return 1;
2272
 
}
2273
 
 
2274
 
void ifoFree_TXTDT_MGI(ifo_handle_t *ifofile) {
2275
 
  if(!ifofile)
2276
 
    return;
2277
 
 
2278
 
  if(ifofile->txtdt_mgi) {
2279
 
    free(ifofile->txtdt_mgi);
2280
 
    ifofile->txtdt_mgi = 0;
2281
 
  }
2282
 
}