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