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