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