~ubuntu-branches/ubuntu/saucy/libdvdread/saucy

« back to all changes in this revision

Viewing changes to .pc/debian-changes-4.2.0-1ubuntu1/src/ifo_read.c

  • Committer: Package Import Robot
  • Author(s): Bryce Harrington
  • Date: 2011-12-07 18:34:56 UTC
  • Revision ID: package-import@ubuntu.com-20111207183456-96hkz4o43c8xr2a1
Tags: 4.2.0-1ubuntu2
* Remove extraneous debian-changes-4.2.0-1ubuntu1 being automatically
  generated by the packaging which reverts the Ubuntu changes.
  (LP: #869003)
* Disable hurd.patch; causes FTBFS on AMD64 due to undefined
  get_current_dir_name().

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