Mercurial > libdvdread4.hg
annotate ifo_read.c @ 59:bfefcc426154 src
Provide BUP file support for more issues.
The BUP file is only opened when the IFO file open fails. We have a
few times where file corruption could happen and we could use the
BUP instead. This patch attempts to address this by trying to
open the BUP if there is any reported error w/ the IFO. Inspiration
for this patch came from Rich E, thanks for the detailed bug
report and attempts at using earlier patches.
author | erik |
---|---|
date | Sat, 31 Jul 2010 00:21:01 +0000 |
parents | 562a4f76fb53 |
children | eac01aeb7be5 |
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 | |
90 static void ifoFree_PGC(pgc_t *pgc); | |
91 static void ifoFree_PGC_COMMAND_TBL(pgc_command_tbl_t *cmd_tbl); | |
92 static void ifoFree_PGCIT_internal(pgcit_t *pgcit); | |
93 | |
94 static inline int DVDFileSeekForce_( dvd_file_t *dvd_file, uint32_t offset, int force_size ) { | |
95 return (DVDFileSeekForce(dvd_file, (int)offset, force_size) == (int)offset); | |
96 } | |
97 | |
98 static inline int DVDFileSeek_( dvd_file_t *dvd_file, uint32_t offset ) { | |
99 return (DVDFileSeek(dvd_file, (int)offset) == (int)offset); | |
100 } | |
101 | |
102 static void read_video_attr(video_attr_t *va) { | |
103 getbits_state_t state; | |
104 uint8_t buf[sizeof(video_attr_t)]; | |
105 | |
106 memcpy(buf, va, sizeof(video_attr_t)); | |
107 if (!dvdread_getbits_init(&state, buf)) abort(); | |
108 va->mpeg_version = dvdread_getbits(&state, 2); | |
109 va->video_format = dvdread_getbits(&state, 2); | |
110 va->display_aspect_ratio = dvdread_getbits(&state, 2); | |
111 va->permitted_df = dvdread_getbits(&state, 2); | |
112 va->line21_cc_1 = dvdread_getbits(&state, 1); | |
113 va->line21_cc_2 = dvdread_getbits(&state, 1); | |
114 va->unknown1 = dvdread_getbits(&state, 1); | |
115 va->bit_rate = dvdread_getbits(&state, 1); | |
116 va->picture_size = dvdread_getbits(&state, 2); | |
117 va->letterboxed = dvdread_getbits(&state, 1); | |
118 va->film_mode = dvdread_getbits(&state, 1); | |
119 } | |
120 | |
121 static void read_audio_attr(audio_attr_t *aa) { | |
122 getbits_state_t state; | |
123 uint8_t buf[sizeof(audio_attr_t)]; | |
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 free(pgc->command_tbl); | |
927 return 0; | |
928 } | |
929 } else { | |
930 pgc->command_tbl = NULL; | |
931 } | |
20 | 932 |
3 | 933 if(pgc->program_map_offset != 0 && pgc->nr_of_programs>0) { |
934 pgc->program_map = malloc(pgc->nr_of_programs * sizeof(pgc_program_map_t)); | |
935 if(!pgc->program_map) { | |
936 ifoFree_PGC_COMMAND_TBL(pgc->command_tbl); | |
937 return 0; | |
938 } | |
939 if(!ifoRead_PGC_PROGRAM_MAP(ifofile, pgc->program_map,pgc->nr_of_programs, | |
940 offset + pgc->program_map_offset)) { | |
941 ifoFree_PGC_COMMAND_TBL(pgc->command_tbl); | |
942 free(pgc->program_map); | |
943 return 0; | |
944 } | |
945 } else { | |
946 pgc->program_map = NULL; | |
947 } | |
20 | 948 |
3 | 949 if(pgc->cell_playback_offset != 0 && pgc->nr_of_cells>0) { |
950 pgc->cell_playback = malloc(pgc->nr_of_cells * sizeof(cell_playback_t)); | |
951 if(!pgc->cell_playback) { | |
952 ifoFree_PGC_COMMAND_TBL(pgc->command_tbl); | |
953 if(pgc->program_map) | |
26 | 954 free(pgc->program_map); |
3 | 955 return 0; |
956 } | |
20 | 957 if(!ifoRead_CELL_PLAYBACK_TBL(ifofile, pgc->cell_playback, |
26 | 958 pgc->nr_of_cells, |
3 | 959 offset + pgc->cell_playback_offset)) { |
960 ifoFree_PGC_COMMAND_TBL(pgc->command_tbl); | |
961 if(pgc->program_map) | |
26 | 962 free(pgc->program_map); |
3 | 963 free(pgc->cell_playback); |
964 return 0; | |
965 } | |
966 } else { | |
967 pgc->cell_playback = NULL; | |
968 } | |
20 | 969 |
3 | 970 if(pgc->cell_position_offset != 0 && pgc->nr_of_cells>0) { |
971 pgc->cell_position = malloc(pgc->nr_of_cells * sizeof(cell_position_t)); | |
972 if(!pgc->cell_position) { | |
973 ifoFree_PGC(pgc); | |
974 return 0; | |
975 } | |
20 | 976 if(!ifoRead_CELL_POSITION_TBL(ifofile, pgc->cell_position, |
26 | 977 pgc->nr_of_cells, |
3 | 978 offset + pgc->cell_position_offset)) { |
979 ifoFree_PGC(pgc); | |
980 return 0; | |
981 } | |
982 } else { | |
983 pgc->cell_position = NULL; | |
984 } | |
985 | |
986 return 1; | |
987 } | |
988 | |
989 int ifoRead_FP_PGC(ifo_handle_t *ifofile) { | |
990 | |
991 if(!ifofile) | |
992 return 0; | |
993 | |
994 if(!ifofile->vmgi_mat) | |
995 return 0; | |
20 | 996 |
3 | 997 /* It seems that first_play_pgc is optional after all. */ |
998 ifofile->first_play_pgc = 0; | |
999 if(ifofile->vmgi_mat->first_play_pgc == 0) | |
1000 return 1; | |
20 | 1001 |
3 | 1002 ifofile->first_play_pgc = (pgc_t *)malloc(sizeof(pgc_t)); |
1003 if(!ifofile->first_play_pgc) | |
1004 return 0; | |
20 | 1005 |
1006 if(!ifoRead_PGC(ifofile, ifofile->first_play_pgc, | |
3 | 1007 ifofile->vmgi_mat->first_play_pgc)) { |
1008 free(ifofile->first_play_pgc); | |
1009 ifofile->first_play_pgc = 0; | |
1010 return 0; | |
1011 } | |
1012 | |
1013 return 1; | |
1014 } | |
1015 | |
1016 static void ifoFree_PGC(pgc_t *pgc) { | |
1017 if(pgc) { | |
1018 ifoFree_PGC_COMMAND_TBL(pgc->command_tbl); | |
1019 if(pgc->program_map) | |
1020 free(pgc->program_map); | |
1021 if(pgc->cell_playback) | |
1022 free(pgc->cell_playback); | |
1023 if(pgc->cell_position) | |
1024 free(pgc->cell_position); | |
1025 } | |
1026 } | |
1027 | |
1028 void ifoFree_FP_PGC(ifo_handle_t *ifofile) { | |
1029 if(!ifofile) | |
1030 return; | |
20 | 1031 |
3 | 1032 if(ifofile->first_play_pgc) { |
1033 ifoFree_PGC(ifofile->first_play_pgc); | |
1034 free(ifofile->first_play_pgc); | |
1035 ifofile->first_play_pgc = 0; | |
1036 } | |
1037 } | |
1038 | |
1039 | |
1040 int ifoRead_TT_SRPT(ifo_handle_t *ifofile) { | |
1041 tt_srpt_t *tt_srpt; | |
1042 int i, info_length; | |
1043 | |
1044 if(!ifofile) | |
1045 return 0; | |
1046 | |
1047 if(!ifofile->vmgi_mat) | |
1048 return 0; | |
1049 | |
1050 if(ifofile->vmgi_mat->tt_srpt == 0) /* mandatory */ | |
1051 return 0; | |
1052 | |
1053 if(!DVDFileSeek_(ifofile->file, ifofile->vmgi_mat->tt_srpt * DVD_BLOCK_LEN)) | |
1054 return 0; | |
1055 | |
1056 tt_srpt = (tt_srpt_t *)malloc(sizeof(tt_srpt_t)); | |
1057 if(!tt_srpt) | |
1058 return 0; | |
1059 | |
1060 ifofile->tt_srpt = tt_srpt; | |
20 | 1061 |
3 | 1062 if(!(DVDReadBytes(ifofile->file, tt_srpt, TT_SRPT_SIZE))) { |
1063 fprintf(stderr, "libdvdread: Unable to read read TT_SRPT.\n"); | |
1064 free(tt_srpt); | |
1065 return 0; | |
1066 } | |
1067 | |
1068 B2N_16(tt_srpt->nr_of_srpts); | |
1069 B2N_32(tt_srpt->last_byte); | |
20 | 1070 |
3 | 1071 info_length = tt_srpt->last_byte + 1 - TT_SRPT_SIZE; |
1072 | |
20 | 1073 tt_srpt->title = (title_info_t *)malloc(info_length); |
3 | 1074 if(!tt_srpt->title) { |
1075 free(tt_srpt); | |
1076 ifofile->tt_srpt = 0; | |
1077 return 0; | |
1078 } | |
1079 if(!(DVDReadBytes(ifofile->file, tt_srpt->title, info_length))) { | |
1080 fprintf(stderr, "libdvdread: Unable to read read TT_SRPT.\n"); | |
1081 ifoFree_TT_SRPT(ifofile); | |
1082 return 0; | |
1083 } | |
1084 | |
1085 for(i = 0; i < tt_srpt->nr_of_srpts; i++) { | |
1086 B2N_16(tt_srpt->title[i].nr_of_ptts); | |
1087 B2N_16(tt_srpt->title[i].parental_id); | |
1088 B2N_32(tt_srpt->title[i].title_set_sector); | |
1089 } | |
20 | 1090 |
3 | 1091 |
1092 CHECK_ZERO(tt_srpt->zero_1); | |
1093 CHECK_VALUE(tt_srpt->nr_of_srpts != 0); | |
1094 CHECK_VALUE(tt_srpt->nr_of_srpts < 100); /* ?? */ | |
1095 CHECK_VALUE((int)tt_srpt->nr_of_srpts * sizeof(title_info_t) <= info_length); | |
20 | 1096 |
3 | 1097 for(i = 0; i < tt_srpt->nr_of_srpts; i++) { |
1098 read_playback_type(&tt_srpt->title[i].pb_ty); | |
1099 CHECK_VALUE(tt_srpt->title[i].pb_ty.zero_1 == 0); | |
1100 CHECK_VALUE(tt_srpt->title[i].nr_of_angles != 0); | |
1101 CHECK_VALUE(tt_srpt->title[i].nr_of_angles < 10); | |
1102 /* CHECK_VALUE(tt_srpt->title[i].nr_of_ptts != 0); */ | |
1103 /* XXX: this assertion breaks Ghostbusters: */ | |
1104 CHECK_VALUE(tt_srpt->title[i].nr_of_ptts < 1000); /* ?? */ | |
1105 CHECK_VALUE(tt_srpt->title[i].title_set_nr != 0); | |
1106 CHECK_VALUE(tt_srpt->title[i].title_set_nr < 100); /* ?? */ | |
1107 CHECK_VALUE(tt_srpt->title[i].vts_ttn != 0); | |
1108 CHECK_VALUE(tt_srpt->title[i].vts_ttn < 100); /* ?? */ | |
1109 /* CHECK_VALUE(tt_srpt->title[i].title_set_sector != 0); */ | |
1110 } | |
20 | 1111 |
3 | 1112 /* Make this a function */ |
1113 #if 0 | |
20 | 1114 if(memcmp((uint8_t *)tt_srpt->title + |
1115 tt_srpt->nr_of_srpts * sizeof(title_info_t), | |
1116 my_friendly_zeros, | |
3 | 1117 info_length - tt_srpt->nr_of_srpts * sizeof(title_info_t))) { |
1118 fprintf(stderr, "VMG_PTT_SRPT slack is != 0, "); | |
20 | 1119 hexdump((uint8_t *)tt_srpt->title + |
1120 tt_srpt->nr_of_srpts * sizeof(title_info_t), | |
3 | 1121 info_length - tt_srpt->nr_of_srpts * sizeof(title_info_t)); |
1122 } | |
1123 #endif | |
1124 | |
1125 return 1; | |
1126 } | |
1127 | |
1128 | |
1129 void ifoFree_TT_SRPT(ifo_handle_t *ifofile) { | |
1130 if(!ifofile) | |
1131 return; | |
20 | 1132 |
3 | 1133 if(ifofile->tt_srpt) { |
1134 free(ifofile->tt_srpt->title); | |
1135 free(ifofile->tt_srpt); | |
1136 ifofile->tt_srpt = 0; | |
1137 } | |
1138 } | |
1139 | |
1140 | |
1141 int ifoRead_VTS_PTT_SRPT(ifo_handle_t *ifofile) { | |
1142 vts_ptt_srpt_t *vts_ptt_srpt; | |
1143 int info_length, i, j; | |
1144 uint32_t *data; | |
1145 | |
1146 if(!ifofile) | |
1147 return 0; | |
20 | 1148 |
3 | 1149 if(!ifofile->vtsi_mat) |
1150 return 0; | |
1151 | |
1152 if(ifofile->vtsi_mat->vts_ptt_srpt == 0) /* mandatory */ | |
1153 return 0; | |
20 | 1154 |
3 | 1155 if(!DVDFileSeek_(ifofile->file, |
26 | 1156 ifofile->vtsi_mat->vts_ptt_srpt * DVD_BLOCK_LEN)) |
3 | 1157 return 0; |
1158 | |
1159 vts_ptt_srpt = (vts_ptt_srpt_t *)malloc(sizeof(vts_ptt_srpt_t)); | |
1160 if(!vts_ptt_srpt) | |
1161 return 0; | |
1162 | |
1163 ifofile->vts_ptt_srpt = vts_ptt_srpt; | |
1164 | |
1165 if(!(DVDReadBytes(ifofile->file, vts_ptt_srpt, VTS_PTT_SRPT_SIZE))) { | |
1166 fprintf(stderr, "libdvdread: Unable to read PTT search table.\n"); | |
1167 free(vts_ptt_srpt); | |
1168 return 0; | |
1169 } | |
1170 | |
1171 B2N_16(vts_ptt_srpt->nr_of_srpts); | |
1172 B2N_32(vts_ptt_srpt->last_byte); | |
1173 | |
1174 CHECK_ZERO(vts_ptt_srpt->zero_1); | |
1175 CHECK_VALUE(vts_ptt_srpt->nr_of_srpts != 0); | |
1176 CHECK_VALUE(vts_ptt_srpt->nr_of_srpts < 100); /* ?? */ | |
20 | 1177 |
3 | 1178 info_length = vts_ptt_srpt->last_byte + 1 - VTS_PTT_SRPT_SIZE; |
20 | 1179 |
1180 data = (uint32_t *)malloc(info_length); | |
3 | 1181 if(!data) { |
1182 free(vts_ptt_srpt); | |
1183 ifofile->vts_ptt_srpt = 0; | |
1184 return 0; | |
1185 } | |
1186 if(!(DVDReadBytes(ifofile->file, data, info_length))) { | |
1187 fprintf(stderr, "libdvdread: Unable to read PTT search table.\n"); | |
1188 free(vts_ptt_srpt); | |
1189 free(data); | |
1190 ifofile->vts_ptt_srpt = 0; | |
1191 return 0; | |
1192 } | |
1193 | |
1194 for(i = 0; i < vts_ptt_srpt->nr_of_srpts; i++) { | |
1195 B2N_32(data[i]); | |
1196 /* assert(data[i] + sizeof(ptt_info_t) <= vts_ptt_srpt->last_byte + 1); | |
20 | 1197 Magic Knight Rayearth Daybreak is mastered very strange and has |
3 | 1198 Titles with 0 PTTs. They all have a data[i] offsets beyond the end of |
1199 of the vts_ptt_srpt structure. */ | |
1200 CHECK_VALUE(data[i] + sizeof(ptt_info_t) <= vts_ptt_srpt->last_byte + 1 + 4); | |
1201 } | |
20 | 1202 |
3 | 1203 vts_ptt_srpt->ttu_offset = data; |
20 | 1204 |
3 | 1205 vts_ptt_srpt->title = malloc(vts_ptt_srpt->nr_of_srpts * sizeof(ttu_t)); |
1206 if(!vts_ptt_srpt->title) { | |
1207 free(vts_ptt_srpt); | |
1208 free(data); | |
1209 ifofile->vts_ptt_srpt = 0; | |
1210 return 0; | |
1211 } | |
1212 for(i = 0; i < vts_ptt_srpt->nr_of_srpts; i++) { | |
1213 int n; | |
1214 if(i < vts_ptt_srpt->nr_of_srpts - 1) | |
1215 n = (data[i+1] - data[i]); | |
1216 else | |
1217 n = (vts_ptt_srpt->last_byte + 1 - data[i]); | |
1218 /* assert(n > 0 && (n % 4) == 0); | |
20 | 1219 Magic Knight Rayearth Daybreak is mastered very strange and has |
3 | 1220 Titles with 0 PTTs. */ |
1221 if(n < 0) n = 0; | |
1222 CHECK_VALUE(n % 4 == 0); | |
20 | 1223 |
3 | 1224 vts_ptt_srpt->title[i].nr_of_ptts = n / 4; |
1225 vts_ptt_srpt->title[i].ptt = malloc(n * sizeof(ptt_info_t)); | |
1226 if(!vts_ptt_srpt->title[i].ptt) { | |
1227 for(n = 0; n < i; n++) | |
1228 free(vts_ptt_srpt->title[n].ptt); | |
1229 free(vts_ptt_srpt); | |
1230 free(data); | |
1231 ifofile->vts_ptt_srpt = 0; | |
1232 return 0; | |
1233 } | |
1234 for(j = 0; j < vts_ptt_srpt->title[i].nr_of_ptts; j++) { | |
1235 /* The assert placed here because of Magic Knight Rayearth Daybreak */ | |
1236 CHECK_VALUE(data[i] + sizeof(ptt_info_t) <= vts_ptt_srpt->last_byte + 1); | |
20 | 1237 vts_ptt_srpt->title[i].ptt[j].pgcn |
3 | 1238 = *(uint16_t*)(((char *)data) + data[i] + 4*j - VTS_PTT_SRPT_SIZE); |
20 | 1239 vts_ptt_srpt->title[i].ptt[j].pgn |
3 | 1240 = *(uint16_t*)(((char *)data) + data[i] + 4*j + 2 - VTS_PTT_SRPT_SIZE); |
1241 } | |
1242 } | |
20 | 1243 |
3 | 1244 for(i = 0; i < vts_ptt_srpt->nr_of_srpts; i++) { |
1245 for(j = 0; j < vts_ptt_srpt->title[i].nr_of_ptts; j++) { | |
1246 B2N_16(vts_ptt_srpt->title[i].ptt[j].pgcn); | |
1247 B2N_16(vts_ptt_srpt->title[i].ptt[j].pgn); | |
1248 } | |
1249 } | |
20 | 1250 |
3 | 1251 for(i = 0; i < vts_ptt_srpt->nr_of_srpts; i++) { |
1252 CHECK_VALUE(vts_ptt_srpt->title[i].nr_of_ptts < 1000); /* ?? */ | |
1253 for(j = 0; j < vts_ptt_srpt->title[i].nr_of_ptts; j++) { | |
1254 CHECK_VALUE(vts_ptt_srpt->title[i].ptt[j].pgcn != 0 ); | |
1255 CHECK_VALUE(vts_ptt_srpt->title[i].ptt[j].pgcn < 1000); /* ?? */ | |
1256 CHECK_VALUE(vts_ptt_srpt->title[i].ptt[j].pgn != 0); | |
1257 CHECK_VALUE(vts_ptt_srpt->title[i].ptt[j].pgn < 100); /* ?? */ | |
1258 } | |
1259 } | |
1260 | |
1261 return 1; | |
1262 } | |
1263 | |
1264 | |
1265 void ifoFree_VTS_PTT_SRPT(ifo_handle_t *ifofile) { | |
1266 if(!ifofile) | |
1267 return; | |
20 | 1268 |
3 | 1269 if(ifofile->vts_ptt_srpt) { |
1270 int i; | |
1271 for(i = 0; i < ifofile->vts_ptt_srpt->nr_of_srpts; i++) | |
1272 free(ifofile->vts_ptt_srpt->title[i].ptt); | |
1273 free(ifofile->vts_ptt_srpt->ttu_offset); | |
1274 free(ifofile->vts_ptt_srpt->title); | |
1275 free(ifofile->vts_ptt_srpt); | |
1276 ifofile->vts_ptt_srpt = 0; | |
1277 } | |
1278 } | |
1279 | |
1280 | |
1281 int ifoRead_PTL_MAIT(ifo_handle_t *ifofile) { | |
1282 ptl_mait_t *ptl_mait; | |
1283 int info_length; | |
1284 unsigned int i, j; | |
1285 | |
1286 if(!ifofile) | |
1287 return 0; | |
20 | 1288 |
3 | 1289 if(!ifofile->vmgi_mat) |
1290 return 0; | |
20 | 1291 |
3 | 1292 if(ifofile->vmgi_mat->ptl_mait == 0) |
1293 return 1; | |
1294 | |
1295 if(!DVDFileSeek_(ifofile->file, ifofile->vmgi_mat->ptl_mait * DVD_BLOCK_LEN)) | |
1296 return 0; | |
1297 | |
1298 ptl_mait = (ptl_mait_t *)malloc(sizeof(ptl_mait_t)); | |
1299 if(!ptl_mait) | |
1300 return 0; | |
1301 | |
1302 ifofile->ptl_mait = ptl_mait; | |
1303 | |
1304 if(!(DVDReadBytes(ifofile->file, ptl_mait, PTL_MAIT_SIZE))) { | |
1305 free(ptl_mait); | |
1306 ifofile->ptl_mait = 0; | |
1307 return 0; | |
1308 } | |
1309 | |
1310 B2N_16(ptl_mait->nr_of_countries); | |
1311 B2N_16(ptl_mait->nr_of_vtss); | |
1312 B2N_32(ptl_mait->last_byte); | |
20 | 1313 |
3 | 1314 CHECK_VALUE(ptl_mait->nr_of_countries != 0); |
1315 CHECK_VALUE(ptl_mait->nr_of_countries < 100); /* ?? */ | |
1316 CHECK_VALUE(ptl_mait->nr_of_vtss != 0); | |
1317 CHECK_VALUE(ptl_mait->nr_of_vtss < 100); /* ?? */ | |
20 | 1318 CHECK_VALUE(ptl_mait->nr_of_countries * PTL_MAIT_COUNTRY_SIZE |
26 | 1319 <= ptl_mait->last_byte + 1 - PTL_MAIT_SIZE); |
20 | 1320 |
3 | 1321 info_length = ptl_mait->nr_of_countries * sizeof(ptl_mait_country_t); |
1322 ptl_mait->countries = (ptl_mait_country_t *)malloc(info_length); | |
1323 if(!ptl_mait->countries) { | |
1324 free(ptl_mait); | |
1325 ifofile->ptl_mait = 0; | |
1326 return 0; | |
1327 } | |
20 | 1328 |
3 | 1329 for(i = 0; i < ptl_mait->nr_of_countries; i++) { |
1330 if(!(DVDReadBytes(ifofile->file, &ptl_mait->countries[i], PTL_MAIT_COUNTRY_SIZE))) { | |
1331 fprintf(stderr, "libdvdread: Unable to read PTL_MAIT.\n"); | |
1332 free(ptl_mait->countries); | |
1333 free(ptl_mait); | |
1334 ifofile->ptl_mait = 0; | |
1335 return 0; | |
1336 } | |
1337 } | |
1338 | |
1339 for(i = 0; i < ptl_mait->nr_of_countries; i++) { | |
1340 B2N_16(ptl_mait->countries[i].country_code); | |
1341 B2N_16(ptl_mait->countries[i].pf_ptl_mai_start_byte); | |
1342 } | |
20 | 1343 |
3 | 1344 for(i = 0; i < ptl_mait->nr_of_countries; i++) { |
1345 CHECK_ZERO(ptl_mait->countries[i].zero_1); | |
20 | 1346 CHECK_ZERO(ptl_mait->countries[i].zero_2); |
3 | 1347 CHECK_VALUE(ptl_mait->countries[i].pf_ptl_mai_start_byte |
26 | 1348 + 8*2 * (ptl_mait->nr_of_vtss + 1) <= ptl_mait->last_byte + 1); |
3 | 1349 } |
1350 | |
1351 for(i = 0; i < ptl_mait->nr_of_countries; i++) { | |
1352 uint16_t *pf_temp; | |
20 | 1353 |
1354 if(!DVDFileSeek_(ifofile->file, | |
26 | 1355 ifofile->vmgi_mat->ptl_mait * DVD_BLOCK_LEN |
3 | 1356 + ptl_mait->countries[i].pf_ptl_mai_start_byte)) { |
58 | 1357 fprintf(stderr, "libdvdread: Unable to seek PTL_MAIT table.\n"); |
3 | 1358 free(ptl_mait->countries); |
1359 free(ptl_mait); | |
1360 return 0; | |
1361 } | |
1362 info_length = (ptl_mait->nr_of_vtss + 1) * sizeof(pf_level_t); | |
1363 pf_temp = (uint16_t *)malloc(info_length); | |
1364 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
|
1365 free_ptl_mait(ptl_mait, i); |
3 | 1366 return 0; |
1367 } | |
1368 if(!(DVDReadBytes(ifofile->file, pf_temp, info_length))) { | |
27
98951f8ec89c
cosmetics: Sync indentation and similar changes from libdvdread 0.9.5.
diego
parents:
26
diff
changeset
|
1369 fprintf(stderr, "libdvdread: Unable to read PTL_MAIT table.\n"); |
98951f8ec89c
cosmetics: Sync indentation and similar changes from libdvdread 0.9.5.
diego
parents:
26
diff
changeset
|
1370 free(pf_temp); |
98951f8ec89c
cosmetics: Sync indentation and similar changes from libdvdread 0.9.5.
diego
parents:
26
diff
changeset
|
1371 free_ptl_mait(ptl_mait, i); |
98951f8ec89c
cosmetics: Sync indentation and similar changes from libdvdread 0.9.5.
diego
parents:
26
diff
changeset
|
1372 return 0; |
3 | 1373 } |
1374 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
|
1375 B2N_16(pf_temp[j]); |
3 | 1376 } |
1377 ptl_mait->countries[i].pf_ptl_mai = (pf_level_t *)malloc(info_length); | |
1378 if(!ptl_mait->countries[i].pf_ptl_mai) { | |
1379 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
|
1380 free_ptl_mait(ptl_mait, i); |
3 | 1381 return 0; |
1382 } | |
1383 { /* Transpose the array so we can use C indexing. */ | |
1384 int level, vts; | |
1385 for(level = 0; level < 8; level++) { | |
26 | 1386 for(vts = 0; vts <= ptl_mait->nr_of_vtss; vts++) { |
1387 ptl_mait->countries[i].pf_ptl_mai[vts][level] = | |
1388 pf_temp[(7-level)*(ptl_mait->nr_of_vtss+1) + vts]; | |
1389 } | |
3 | 1390 } |
1391 free(pf_temp); | |
1392 } | |
1393 } | |
1394 return 1; | |
1395 } | |
1396 | |
1397 void ifoFree_PTL_MAIT(ifo_handle_t *ifofile) { | |
1398 unsigned int i; | |
20 | 1399 |
3 | 1400 if(!ifofile) |
1401 return; | |
20 | 1402 |
3 | 1403 if(ifofile->ptl_mait) { |
1404 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
|
1405 free(ifofile->ptl_mait->countries[i].pf_ptl_mai); |
3 | 1406 } |
1407 free(ifofile->ptl_mait->countries); | |
1408 free(ifofile->ptl_mait); | |
1409 ifofile->ptl_mait = 0; | |
1410 } | |
1411 } | |
1412 | |
1413 int ifoRead_VTS_TMAPT(ifo_handle_t *ifofile) { | |
1414 vts_tmapt_t *vts_tmapt; | |
1415 uint32_t *vts_tmap_srp; | |
1416 unsigned int offset; | |
1417 int info_length; | |
1418 unsigned int i, j; | |
20 | 1419 |
3 | 1420 if(!ifofile) |
1421 return 0; | |
1422 | |
1423 if(!ifofile->vtsi_mat) | |
1424 return 0; | |
1425 | |
1426 if(ifofile->vtsi_mat->vts_tmapt == 0) { /* optional(?) */ | |
1427 ifofile->vts_tmapt = NULL; | |
1428 fprintf(stderr,"Please send bug report - no VTS_TMAPT ?? \n"); | |
1429 return 1; | |
1430 } | |
20 | 1431 |
3 | 1432 offset = ifofile->vtsi_mat->vts_tmapt * DVD_BLOCK_LEN; |
20 | 1433 |
1434 if(!DVDFileSeek_(ifofile->file, offset)) | |
3 | 1435 return 0; |
20 | 1436 |
3 | 1437 vts_tmapt = (vts_tmapt_t *)malloc(sizeof(vts_tmapt_t)); |
1438 if(!vts_tmapt) | |
1439 return 0; | |
20 | 1440 |
3 | 1441 ifofile->vts_tmapt = vts_tmapt; |
20 | 1442 |
3 | 1443 if(!(DVDReadBytes(ifofile->file, vts_tmapt, VTS_TMAPT_SIZE))) { |
1444 fprintf(stderr, "libdvdread: Unable to read VTS_TMAPT.\n"); | |
1445 free(vts_tmapt); | |
1446 ifofile->vts_tmapt = NULL; | |
1447 return 0; | |
1448 } | |
1449 | |
1450 B2N_16(vts_tmapt->nr_of_tmaps); | |
1451 B2N_32(vts_tmapt->last_byte); | |
20 | 1452 |
3 | 1453 CHECK_ZERO(vts_tmapt->zero_1); |
20 | 1454 |
3 | 1455 info_length = vts_tmapt->nr_of_tmaps * 4; |
20 | 1456 |
3 | 1457 vts_tmap_srp = (uint32_t *)malloc(info_length); |
1458 if(!vts_tmap_srp) { | |
1459 free(vts_tmapt); | |
1460 ifofile->vts_tmapt = NULL; | |
1461 return 0; | |
1462 } | |
1463 | |
1464 vts_tmapt->tmap_offset = vts_tmap_srp; | |
20 | 1465 |
3 | 1466 if(!(DVDReadBytes(ifofile->file, vts_tmap_srp, info_length))) { |
1467 fprintf(stderr, "libdvdread: Unable to read VTS_TMAPT.\n"); | |
1468 free(vts_tmap_srp); | |
1469 free(vts_tmapt); | |
1470 ifofile->vts_tmapt = NULL; | |
1471 return 0; | |
1472 } | |
1473 | |
1474 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
|
1475 B2N_32(vts_tmap_srp[i]); |
3 | 1476 } |
1477 | |
20 | 1478 |
3 | 1479 info_length = vts_tmapt->nr_of_tmaps * sizeof(vts_tmap_t); |
20 | 1480 |
3 | 1481 vts_tmapt->tmap = (vts_tmap_t *)malloc(info_length); |
1482 if(!vts_tmapt->tmap) { | |
1483 free(vts_tmap_srp); | |
1484 free(vts_tmapt); | |
1485 ifofile->vts_tmapt = NULL; | |
1486 return 0; | |
1487 } | |
1488 | |
1489 memset(vts_tmapt->tmap, 0, info_length); /* So ifoFree_VTS_TMAPT works. */ | |
20 | 1490 |
3 | 1491 for(i = 0; i < vts_tmapt->nr_of_tmaps; i++) { |
1492 if(!DVDFileSeek_(ifofile->file, offset + vts_tmap_srp[i])) { | |
1493 ifoFree_VTS_TMAPT(ifofile); | |
1494 return 0; | |
1495 } | |
1496 | |
1497 if(!(DVDReadBytes(ifofile->file, &vts_tmapt->tmap[i], VTS_TMAP_SIZE))) { | |
1498 fprintf(stderr, "libdvdread: Unable to read VTS_TMAP.\n"); | |
1499 ifoFree_VTS_TMAPT(ifofile); | |
1500 return 0; | |
1501 } | |
20 | 1502 |
3 | 1503 B2N_16(vts_tmapt->tmap[i].nr_of_entries); |
1504 CHECK_ZERO(vts_tmapt->tmap[i].zero_1); | |
20 | 1505 |
3 | 1506 if(vts_tmapt->tmap[i].nr_of_entries == 0) { /* Early out if zero entries */ |
1507 vts_tmapt->tmap[i].map_ent = NULL; | |
1508 continue; | |
1509 } | |
20 | 1510 |
3 | 1511 info_length = vts_tmapt->tmap[i].nr_of_entries * sizeof(map_ent_t); |
20 | 1512 |
3 | 1513 vts_tmapt->tmap[i].map_ent = (map_ent_t *)malloc(info_length); |
1514 if(!vts_tmapt->tmap[i].map_ent) { | |
1515 ifoFree_VTS_TMAPT(ifofile); | |
1516 return 0; | |
1517 } | |
1518 | |
1519 if(!(DVDReadBytes(ifofile->file, vts_tmapt->tmap[i].map_ent, info_length))) { | |
1520 fprintf(stderr, "libdvdread: Unable to read VTS_TMAP_ENT.\n"); | |
1521 ifoFree_VTS_TMAPT(ifofile); | |
1522 return 0; | |
1523 } | |
20 | 1524 |
3 | 1525 for(j = 0; j < vts_tmapt->tmap[i].nr_of_entries; j++) |
1526 B2N_32(vts_tmapt->tmap[i].map_ent[j]); | |
20 | 1527 } |
1528 | |
3 | 1529 return 1; |
1530 } | |
1531 | |
1532 void ifoFree_VTS_TMAPT(ifo_handle_t *ifofile) { | |
1533 unsigned int i; | |
20 | 1534 |
3 | 1535 if(!ifofile) |
1536 return; | |
20 | 1537 |
1538 if(ifofile->vts_tmapt) { | |
3 | 1539 for(i = 0; i < ifofile->vts_tmapt->nr_of_tmaps; i++) |
1540 if(ifofile->vts_tmapt->tmap[i].map_ent) | |
26 | 1541 free(ifofile->vts_tmapt->tmap[i].map_ent); |
3 | 1542 free(ifofile->vts_tmapt->tmap); |
1543 free(ifofile->vts_tmapt->tmap_offset); | |
1544 free(ifofile->vts_tmapt); | |
1545 ifofile->vts_tmapt = NULL; | |
1546 } | |
1547 } | |
1548 | |
1549 | |
1550 int ifoRead_TITLE_C_ADT(ifo_handle_t *ifofile) { | |
1551 | |
1552 if(!ifofile) | |
1553 return 0; | |
1554 | |
1555 if(!ifofile->vtsi_mat) | |
1556 return 0; | |
1557 | |
1558 if(ifofile->vtsi_mat->vts_c_adt == 0) /* mandatory */ | |
1559 return 0; | |
1560 | |
1561 ifofile->vts_c_adt = (c_adt_t *)malloc(sizeof(c_adt_t)); | |
1562 if(!ifofile->vts_c_adt) | |
1563 return 0; | |
1564 | |
20 | 1565 if(!ifoRead_C_ADT_internal(ifofile, ifofile->vts_c_adt, |
3 | 1566 ifofile->vtsi_mat->vts_c_adt)) { |
1567 free(ifofile->vts_c_adt); | |
1568 ifofile->vts_c_adt = 0; | |
1569 return 0; | |
1570 } | |
1571 | |
1572 return 1; | |
1573 } | |
1574 | |
1575 int ifoRead_C_ADT(ifo_handle_t *ifofile) { | |
1576 unsigned int sector; | |
1577 | |
1578 if(!ifofile) | |
1579 return 0; | |
20 | 1580 |
3 | 1581 if(ifofile->vmgi_mat) { |
1582 if(ifofile->vmgi_mat->vmgm_c_adt == 0) | |
1583 return 1; | |
1584 sector = ifofile->vmgi_mat->vmgm_c_adt; | |
1585 } else if(ifofile->vtsi_mat) { | |
1586 if(ifofile->vtsi_mat->vtsm_c_adt == 0) | |
1587 return 1; | |
1588 sector = ifofile->vtsi_mat->vtsm_c_adt; | |
1589 } else { | |
1590 return 0; | |
1591 } | |
20 | 1592 |
3 | 1593 ifofile->menu_c_adt = (c_adt_t *)malloc(sizeof(c_adt_t)); |
1594 if(!ifofile->menu_c_adt) | |
1595 return 0; | |
1596 | |
1597 if(!ifoRead_C_ADT_internal(ifofile, ifofile->menu_c_adt, sector)) { | |
1598 free(ifofile->menu_c_adt); | |
1599 ifofile->menu_c_adt = 0; | |
1600 return 0; | |
1601 } | |
1602 | |
1603 return 1; | |
1604 } | |
1605 | |
20 | 1606 static int ifoRead_C_ADT_internal(ifo_handle_t *ifofile, |
3 | 1607 c_adt_t *c_adt, unsigned int sector) { |
1608 int i, info_length; | |
1609 | |
1610 if(!DVDFileSeek_(ifofile->file, sector * DVD_BLOCK_LEN)) | |
1611 return 0; | |
1612 | |
1613 if(!(DVDReadBytes(ifofile->file, c_adt, C_ADT_SIZE))) | |
1614 return 0; | |
1615 | |
1616 B2N_16(c_adt->nr_of_vobs); | |
1617 B2N_32(c_adt->last_byte); | |
20 | 1618 |
3 | 1619 info_length = c_adt->last_byte + 1 - C_ADT_SIZE; |
20 | 1620 |
3 | 1621 CHECK_ZERO(c_adt->zero_1); |
20 | 1622 /* assert(c_adt->nr_of_vobs > 0); |
1623 Magic Knight Rayearth Daybreak is mastered very strange and has | |
3 | 1624 Titles with a VOBS that has no cells. */ |
1625 CHECK_VALUE(info_length % sizeof(cell_adr_t) == 0); | |
20 | 1626 |
3 | 1627 /* assert(info_length / sizeof(cell_adr_t) >= c_adt->nr_of_vobs); |
1628 Enemy of the State region 2 (de) has Titles where nr_of_vobs field | |
1629 is to high, they high ones are never referenced though. */ | |
1630 if(info_length / sizeof(cell_adr_t) < c_adt->nr_of_vobs) { | |
1631 fprintf(stderr, "libdvdread: *C_ADT nr_of_vobs > avaiable info entries\n"); | |
1632 c_adt->nr_of_vobs = info_length / sizeof(cell_adr_t); | |
1633 } | |
20 | 1634 |
3 | 1635 c_adt->cell_adr_table = (cell_adr_t *)malloc(info_length); |
1636 if(!c_adt->cell_adr_table) | |
1637 return 0; | |
1638 | |
20 | 1639 if(info_length && |
3 | 1640 !(DVDReadBytes(ifofile->file, c_adt->cell_adr_table, info_length))) { |
1641 free(c_adt->cell_adr_table); | |
1642 return 0; | |
1643 } | |
1644 | |
1645 for(i = 0; i < info_length/sizeof(cell_adr_t); i++) { | |
1646 B2N_16(c_adt->cell_adr_table[i].vob_id); | |
1647 B2N_32(c_adt->cell_adr_table[i].start_sector); | |
1648 B2N_32(c_adt->cell_adr_table[i].last_sector); | |
1649 | |
1650 CHECK_ZERO(c_adt->cell_adr_table[i].zero_1); | |
1651 CHECK_VALUE(c_adt->cell_adr_table[i].vob_id > 0); | |
1652 CHECK_VALUE(c_adt->cell_adr_table[i].vob_id <= c_adt->nr_of_vobs); | |
1653 CHECK_VALUE(c_adt->cell_adr_table[i].cell_id > 0); | |
20 | 1654 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
|
1655 c_adt->cell_adr_table[i].last_sector); |
3 | 1656 } |
1657 | |
1658 return 1; | |
1659 } | |
1660 | |
1661 | |
1662 static void ifoFree_C_ADT_internal(c_adt_t *c_adt) { | |
1663 if(c_adt) { | |
1664 free(c_adt->cell_adr_table); | |
1665 free(c_adt); | |
1666 } | |
1667 } | |
1668 | |
1669 void ifoFree_C_ADT(ifo_handle_t *ifofile) { | |
1670 if(!ifofile) | |
1671 return; | |
20 | 1672 |
3 | 1673 ifoFree_C_ADT_internal(ifofile->menu_c_adt); |
1674 ifofile->menu_c_adt = 0; | |
1675 } | |
1676 | |
1677 void ifoFree_TITLE_C_ADT(ifo_handle_t *ifofile) { | |
1678 if(!ifofile) | |
1679 return; | |
20 | 1680 |
3 | 1681 ifoFree_C_ADT_internal(ifofile->vts_c_adt); |
1682 ifofile->vts_c_adt = 0; | |
1683 } | |
1684 | |
1685 int ifoRead_TITLE_VOBU_ADMAP(ifo_handle_t *ifofile) { | |
1686 if(!ifofile) | |
1687 return 0; | |
1688 | |
1689 if(!ifofile->vtsi_mat) | |
1690 return 0; | |
20 | 1691 |
3 | 1692 if(ifofile->vtsi_mat->vts_vobu_admap == 0) /* mandatory */ |
1693 return 0; | |
20 | 1694 |
3 | 1695 ifofile->vts_vobu_admap = (vobu_admap_t *)malloc(sizeof(vobu_admap_t)); |
1696 if(!ifofile->vts_vobu_admap) | |
1697 return 0; | |
1698 | |
1699 if(!ifoRead_VOBU_ADMAP_internal(ifofile, ifofile->vts_vobu_admap, | |
1700 ifofile->vtsi_mat->vts_vobu_admap)) { | |
1701 free(ifofile->vts_vobu_admap); | |
1702 ifofile->vts_vobu_admap = 0; | |
1703 return 0; | |
1704 } | |
1705 | |
1706 return 1; | |
1707 } | |
1708 | |
1709 int ifoRead_VOBU_ADMAP(ifo_handle_t *ifofile) { | |
1710 unsigned int sector; | |
1711 | |
1712 if(!ifofile) | |
1713 return 0; | |
20 | 1714 |
3 | 1715 if(ifofile->vmgi_mat) { |
1716 if(ifofile->vmgi_mat->vmgm_vobu_admap == 0) | |
1717 return 1; | |
1718 sector = ifofile->vmgi_mat->vmgm_vobu_admap; | |
1719 } else if(ifofile->vtsi_mat) { | |
1720 if(ifofile->vtsi_mat->vtsm_vobu_admap == 0) | |
1721 return 1; | |
1722 sector = ifofile->vtsi_mat->vtsm_vobu_admap; | |
1723 } else { | |
1724 return 0; | |
1725 } | |
20 | 1726 |
3 | 1727 ifofile->menu_vobu_admap = (vobu_admap_t *)malloc(sizeof(vobu_admap_t)); |
1728 if(!ifofile->menu_vobu_admap) | |
1729 return 0; | |
20 | 1730 |
3 | 1731 if(!ifoRead_VOBU_ADMAP_internal(ifofile, ifofile->menu_vobu_admap, sector)) { |
1732 free(ifofile->menu_vobu_admap); | |
1733 ifofile->menu_vobu_admap = 0; | |
1734 return 0; | |
1735 } | |
1736 | |
1737 return 1; | |
1738 } | |
1739 | |
20 | 1740 static int ifoRead_VOBU_ADMAP_internal(ifo_handle_t *ifofile, |
1741 vobu_admap_t *vobu_admap, | |
26 | 1742 unsigned int sector) { |
3 | 1743 unsigned int i; |
1744 int info_length; | |
1745 | |
1746 if(!DVDFileSeekForce_(ifofile->file, sector * DVD_BLOCK_LEN, sector)) | |
1747 return 0; | |
1748 | |
1749 if(!(DVDReadBytes(ifofile->file, vobu_admap, VOBU_ADMAP_SIZE))) | |
1750 return 0; | |
1751 | |
1752 B2N_32(vobu_admap->last_byte); | |
20 | 1753 |
3 | 1754 info_length = vobu_admap->last_byte + 1 - VOBU_ADMAP_SIZE; |
1755 /* assert(info_length > 0); | |
20 | 1756 Magic Knight Rayearth Daybreak is mastered very strange and has |
3 | 1757 Titles with a VOBS that has no VOBUs. */ |
1758 CHECK_VALUE(info_length % sizeof(uint32_t) == 0); | |
20 | 1759 |
1760 vobu_admap->vobu_start_sectors = (uint32_t *)malloc(info_length); | |
3 | 1761 if(!vobu_admap->vobu_start_sectors) { |
1762 return 0; | |
1763 } | |
20 | 1764 if(info_length && |
1765 !(DVDReadBytes(ifofile->file, | |
26 | 1766 vobu_admap->vobu_start_sectors, info_length))) { |
3 | 1767 free(vobu_admap->vobu_start_sectors); |
1768 return 0; | |
1769 } | |
1770 | |
1771 for(i = 0; i < info_length/sizeof(uint32_t); i++) | |
1772 B2N_32(vobu_admap->vobu_start_sectors[i]); | |
1773 | |
1774 return 1; | |
1775 } | |
1776 | |
1777 | |
1778 static void ifoFree_VOBU_ADMAP_internal(vobu_admap_t *vobu_admap) { | |
1779 if(vobu_admap) { | |
1780 free(vobu_admap->vobu_start_sectors); | |
1781 free(vobu_admap); | |
1782 } | |
1783 } | |
1784 | |
1785 void ifoFree_VOBU_ADMAP(ifo_handle_t *ifofile) { | |
1786 if(!ifofile) | |
1787 return; | |
20 | 1788 |
3 | 1789 ifoFree_VOBU_ADMAP_internal(ifofile->menu_vobu_admap); |
1790 ifofile->menu_vobu_admap = 0; | |
1791 } | |
1792 | |
1793 void ifoFree_TITLE_VOBU_ADMAP(ifo_handle_t *ifofile) { | |
1794 if(!ifofile) | |
1795 return; | |
20 | 1796 |
3 | 1797 ifoFree_VOBU_ADMAP_internal(ifofile->vts_vobu_admap); |
1798 ifofile->vts_vobu_admap = 0; | |
1799 } | |
1800 | |
1801 int ifoRead_PGCIT(ifo_handle_t *ifofile) { | |
1802 | |
1803 if(!ifofile) | |
1804 return 0; | |
20 | 1805 |
3 | 1806 if(!ifofile->vtsi_mat) |
1807 return 0; | |
20 | 1808 |
3 | 1809 if(ifofile->vtsi_mat->vts_pgcit == 0) /* mandatory */ |
1810 return 0; | |
20 | 1811 |
3 | 1812 ifofile->vts_pgcit = (pgcit_t *)malloc(sizeof(pgcit_t)); |
1813 if(!ifofile->vts_pgcit) | |
1814 return 0; | |
1815 | |
20 | 1816 if(!ifoRead_PGCIT_internal(ifofile, ifofile->vts_pgcit, |
3 | 1817 ifofile->vtsi_mat->vts_pgcit * DVD_BLOCK_LEN)) { |
1818 free(ifofile->vts_pgcit); | |
1819 ifofile->vts_pgcit = 0; | |
1820 return 0; | |
1821 } | |
1822 | |
1823 return 1; | |
1824 } | |
1825 | |
20 | 1826 static int ifoRead_PGCIT_internal(ifo_handle_t *ifofile, pgcit_t *pgcit, |
3 | 1827 unsigned int offset) { |
1828 int i, info_length; | |
1829 uint8_t *data, *ptr; | |
20 | 1830 |
3 | 1831 if(!DVDFileSeek_(ifofile->file, offset)) |
1832 return 0; | |
1833 | |
1834 if(!(DVDReadBytes(ifofile->file, pgcit, PGCIT_SIZE))) | |
1835 return 0; | |
1836 | |
1837 B2N_16(pgcit->nr_of_pgci_srp); | |
1838 B2N_32(pgcit->last_byte); | |
20 | 1839 |
3 | 1840 CHECK_ZERO(pgcit->zero_1); |
1841 /* assert(pgcit->nr_of_pgci_srp != 0); | |
20 | 1842 Magic Knight Rayearth Daybreak is mastered very strange and has |
3 | 1843 Titles with 0 PTTs. */ |
1844 CHECK_VALUE(pgcit->nr_of_pgci_srp < 10000); /* ?? seen max of 1338 */ | |
20 | 1845 |
3 | 1846 info_length = pgcit->nr_of_pgci_srp * PGCI_SRP_SIZE; |
1847 data = malloc(info_length); | |
1848 if(!data) | |
1849 return 0; | |
1850 | |
1851 if(info_length && !(DVDReadBytes(ifofile->file, data, info_length))) { | |
1852 free(data); | |
1853 return 0; | |
1854 } | |
1855 | |
1856 pgcit->pgci_srp = malloc(pgcit->nr_of_pgci_srp * sizeof(pgci_srp_t)); | |
1857 if(!pgcit->pgci_srp) { | |
1858 free(data); | |
1859 return 0; | |
1860 } | |
1861 ptr = data; | |
1862 for(i = 0; i < pgcit->nr_of_pgci_srp; i++) { | |
1863 memcpy(&pgcit->pgci_srp[i], ptr, PGCI_SRP_SIZE); | |
1864 ptr += PGCI_SRP_SIZE; | |
1865 read_pgci_srp(&pgcit->pgci_srp[i]); | |
1866 CHECK_VALUE(pgcit->pgci_srp[i].unknown1 == 0); | |
1867 } | |
1868 free(data); | |
20 | 1869 |
3 | 1870 for(i = 0; i < pgcit->nr_of_pgci_srp; i++) |
1871 CHECK_VALUE(pgcit->pgci_srp[i].pgc_start_byte + PGC_SIZE <= pgcit->last_byte+1); | |
20 | 1872 |
3 | 1873 for(i = 0; i < pgcit->nr_of_pgci_srp; i++) { |
1874 pgcit->pgci_srp[i].pgc = malloc(sizeof(pgc_t)); | |
1875 if(!pgcit->pgci_srp[i].pgc) { | |
1876 int j; | |
1877 for(j = 0; j < i; j++) { | |
1878 ifoFree_PGC(pgcit->pgci_srp[j].pgc); | |
1879 free(pgcit->pgci_srp[j].pgc); | |
1880 } | |
1881 goto fail; | |
1882 } | |
20 | 1883 if(!ifoRead_PGC(ifofile, pgcit->pgci_srp[i].pgc, |
3 | 1884 offset + pgcit->pgci_srp[i].pgc_start_byte)) { |
1885 int j; | |
1886 for(j = 0; j < i; j++) { | |
1887 ifoFree_PGC(pgcit->pgci_srp[j].pgc); | |
1888 free(pgcit->pgci_srp[j].pgc); | |
1889 } | |
1890 goto fail; | |
1891 } | |
1892 } | |
1893 | |
1894 return 1; | |
1895 fail: | |
1896 free(pgcit->pgci_srp); | |
1897 pgcit->pgci_srp = NULL; | |
1898 return 0; | |
1899 } | |
1900 | |
1901 static void ifoFree_PGCIT_internal(pgcit_t *pgcit) { | |
1902 if(pgcit) { | |
1903 int i; | |
1904 for(i = 0; i < pgcit->nr_of_pgci_srp; i++) | |
1905 ifoFree_PGC(pgcit->pgci_srp[i].pgc); | |
1906 free(pgcit->pgci_srp); | |
1907 } | |
1908 } | |
1909 | |
1910 void ifoFree_PGCIT(ifo_handle_t *ifofile) { | |
1911 if(!ifofile) | |
1912 return; | |
20 | 1913 |
3 | 1914 if(ifofile->vts_pgcit) { |
1915 ifoFree_PGCIT_internal(ifofile->vts_pgcit); | |
1916 free(ifofile->vts_pgcit); | |
1917 ifofile->vts_pgcit = 0; | |
1918 } | |
1919 } | |
1920 | |
1921 | |
1922 int ifoRead_PGCI_UT(ifo_handle_t *ifofile) { | |
1923 pgci_ut_t *pgci_ut; | |
1924 unsigned int sector; | |
20 | 1925 unsigned int i; |
3 | 1926 int info_length; |
1927 uint8_t *data, *ptr; | |
1928 | |
1929 if(!ifofile) | |
1930 return 0; | |
20 | 1931 |
3 | 1932 if(ifofile->vmgi_mat) { |
1933 if(ifofile->vmgi_mat->vmgm_pgci_ut == 0) | |
1934 return 1; | |
1935 sector = ifofile->vmgi_mat->vmgm_pgci_ut; | |
1936 } else if(ifofile->vtsi_mat) { | |
1937 if(ifofile->vtsi_mat->vtsm_pgci_ut == 0) | |
1938 return 1; | |
1939 sector = ifofile->vtsi_mat->vtsm_pgci_ut; | |
1940 } else { | |
1941 return 0; | |
1942 } | |
20 | 1943 |
3 | 1944 ifofile->pgci_ut = (pgci_ut_t *)malloc(sizeof(pgci_ut_t)); |
1945 if(!ifofile->pgci_ut) | |
1946 return 0; | |
20 | 1947 |
3 | 1948 if(!DVDFileSeek_(ifofile->file, sector * DVD_BLOCK_LEN)) { |
1949 free(ifofile->pgci_ut); | |
1950 ifofile->pgci_ut = 0; | |
1951 return 0; | |
1952 } | |
20 | 1953 |
3 | 1954 if(!(DVDReadBytes(ifofile->file, ifofile->pgci_ut, PGCI_UT_SIZE))) { |
1955 free(ifofile->pgci_ut); | |
1956 ifofile->pgci_ut = 0; | |
1957 return 0; | |
1958 } | |
20 | 1959 |
3 | 1960 pgci_ut = ifofile->pgci_ut; |
20 | 1961 |
3 | 1962 B2N_16(pgci_ut->nr_of_lus); |
1963 B2N_32(pgci_ut->last_byte); | |
20 | 1964 |
3 | 1965 CHECK_ZERO(pgci_ut->zero_1); |
1966 CHECK_VALUE(pgci_ut->nr_of_lus != 0); | |
1967 CHECK_VALUE(pgci_ut->nr_of_lus < 100); /* ?? 3-4 ? */ | |
1968 CHECK_VALUE((uint32_t)pgci_ut->nr_of_lus * PGCI_LU_SIZE < pgci_ut->last_byte); | |
1969 | |
1970 info_length = pgci_ut->nr_of_lus * PGCI_LU_SIZE; | |
1971 data = malloc(info_length); | |
1972 if(!data) { | |
1973 free(pgci_ut); | |
1974 ifofile->pgci_ut = 0; | |
1975 return 0; | |
1976 } | |
1977 if(!(DVDReadBytes(ifofile->file, data, info_length))) { | |
1978 free(data); | |
1979 free(pgci_ut); | |
1980 ifofile->pgci_ut = 0; | |
1981 return 0; | |
1982 } | |
1983 | |
1984 pgci_ut->lu = malloc(pgci_ut->nr_of_lus * sizeof(pgci_lu_t)); | |
1985 if(!pgci_ut->lu) { | |
1986 free(data); | |
1987 free(pgci_ut); | |
1988 ifofile->pgci_ut = 0; | |
27
98951f8ec89c
cosmetics: Sync indentation and similar changes from libdvdread 0.9.5.
diego
parents:
26
diff
changeset
|
1989 return 0; |
3 | 1990 } |
1991 ptr = data; | |
1992 for(i = 0; i < pgci_ut->nr_of_lus; i++) { | |
1993 memcpy(&pgci_ut->lu[i], ptr, PGCI_LU_SIZE); | |
1994 ptr += PGCI_LU_SIZE; | |
20 | 1995 B2N_16(pgci_ut->lu[i].lang_code); |
1996 B2N_32(pgci_ut->lu[i].lang_start_byte); | |
3 | 1997 } |
1998 free(data); | |
20 | 1999 |
3 | 2000 for(i = 0; i < pgci_ut->nr_of_lus; i++) { |
2001 /* Maybe this is only defined for v1.1 and later titles? */ | |
2002 /* 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
|
2003 VTS_x_yy.IFO VIDEO_TS.IFO |
3 | 2004 a == 0x83 "Root" 0x82 "Title" |
2005 b == 0x84 "Subpicture" | |
2006 c == 0x85 "Audio" | |
2007 d == 0x86 "Angle" | |
2008 e == 0x87 "PTT" | |
2009 */ | |
2010 CHECK_VALUE((pgci_ut->lu[i].exists & 0x07) == 0); | |
2011 } | |
2012 | |
2013 for(i = 0; i < pgci_ut->nr_of_lus; i++) { | |
2014 pgci_ut->lu[i].pgcit = malloc(sizeof(pgcit_t)); | |
2015 if(!pgci_ut->lu[i].pgcit) { | |
2016 unsigned int j; | |
2017 for(j = 0; j < i; j++) { | |
2018 ifoFree_PGCIT_internal(pgci_ut->lu[j].pgcit); | |
2019 free(pgci_ut->lu[j].pgcit); | |
2020 } | |
2021 free(pgci_ut->lu); | |
2022 free(pgci_ut); | |
2023 ifofile->pgci_ut = 0; | |
2024 return 0; | |
2025 } | |
20 | 2026 if(!ifoRead_PGCIT_internal(ifofile, pgci_ut->lu[i].pgcit, |
2027 sector * DVD_BLOCK_LEN | |
3 | 2028 + pgci_ut->lu[i].lang_start_byte)) { |
2029 unsigned int j; | |
2030 for(j = 0; j < i; j++) { | |
2031 ifoFree_PGCIT_internal(pgci_ut->lu[j].pgcit); | |
2032 free(pgci_ut->lu[j].pgcit); | |
2033 } | |
2034 free(pgci_ut->lu[i].pgcit); | |
2035 free(pgci_ut->lu); | |
2036 free(pgci_ut); | |
2037 ifofile->pgci_ut = 0; | |
2038 return 0; | |
2039 } | |
27
98951f8ec89c
cosmetics: Sync indentation and similar changes from libdvdread 0.9.5.
diego
parents:
26
diff
changeset
|
2040 /* 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
|
2041 * to pgci_ut->lu[i].exists really do? */ |
3 | 2042 } |
2043 | |
2044 return 1; | |
2045 } | |
2046 | |
2047 | |
2048 void ifoFree_PGCI_UT(ifo_handle_t *ifofile) { | |
2049 unsigned int i; | |
2050 | |
2051 if(!ifofile) | |
2052 return; | |
20 | 2053 |
3 | 2054 if(ifofile->pgci_ut) { |
2055 for(i = 0; i < ifofile->pgci_ut->nr_of_lus; i++) { | |
2056 ifoFree_PGCIT_internal(ifofile->pgci_ut->lu[i].pgcit); | |
2057 free(ifofile->pgci_ut->lu[i].pgcit); | |
2058 } | |
2059 free(ifofile->pgci_ut->lu); | |
2060 free(ifofile->pgci_ut); | |
2061 ifofile->pgci_ut = 0; | |
2062 } | |
2063 } | |
2064 | |
20 | 2065 static int ifoRead_VTS_ATTRIBUTES(ifo_handle_t *ifofile, |
2066 vts_attributes_t *vts_attributes, | |
3 | 2067 unsigned int offset) { |
2068 unsigned int i; | |
2069 | |
2070 if(!DVDFileSeek_(ifofile->file, offset)) | |
2071 return 0; | |
2072 | |
2073 if(!(DVDReadBytes(ifofile->file, vts_attributes, sizeof(vts_attributes_t)))) | |
2074 return 0; | |
2075 | |
2076 read_video_attr(&vts_attributes->vtsm_vobs_attr); | |
2077 read_video_attr(&vts_attributes->vtstt_vobs_video_attr); | |
2078 read_audio_attr(&vts_attributes->vtsm_audio_attr); | |
2079 for(i=0; i<8; i++) | |
2080 read_audio_attr(&vts_attributes->vtstt_audio_attr[i]); | |
2081 read_subp_attr(&vts_attributes->vtsm_subp_attr); | |
2082 for(i=0; i<32; i++) | |
2083 read_subp_attr(&vts_attributes->vtstt_subp_attr[i]); | |
2084 B2N_32(vts_attributes->last_byte); | |
2085 B2N_32(vts_attributes->vts_cat); | |
20 | 2086 |
3 | 2087 CHECK_ZERO(vts_attributes->zero_1); |
2088 CHECK_ZERO(vts_attributes->zero_2); | |
2089 CHECK_ZERO(vts_attributes->zero_3); | |
2090 CHECK_ZERO(vts_attributes->zero_4); | |
2091 CHECK_ZERO(vts_attributes->zero_5); | |
2092 CHECK_ZERO(vts_attributes->zero_6); | |
2093 CHECK_ZERO(vts_attributes->zero_7); | |
2094 CHECK_VALUE(vts_attributes->nr_of_vtsm_audio_streams <= 1); | |
2095 CHECK_VALUE(vts_attributes->nr_of_vtsm_subp_streams <= 1); | |
2096 CHECK_VALUE(vts_attributes->nr_of_vtstt_audio_streams <= 8); | |
2097 for(i = vts_attributes->nr_of_vtstt_audio_streams; i < 8; i++) | |
2098 CHECK_ZERO(vts_attributes->vtstt_audio_attr[i]); | |
2099 CHECK_VALUE(vts_attributes->nr_of_vtstt_subp_streams <= 32); | |
2100 { | |
2101 unsigned int nr_coded; | |
20 | 2102 CHECK_VALUE(vts_attributes->last_byte + 1 >= VTS_ATTRIBUTES_MIN_SIZE); |
3 | 2103 nr_coded = (vts_attributes->last_byte + 1 - VTS_ATTRIBUTES_MIN_SIZE)/6; |
2104 /* This is often nr_coded = 70, how do you know how many there really are? */ | |
2105 if(nr_coded > 32) { /* We haven't read more from disk/file anyway */ | |
2106 nr_coded = 32; | |
2107 } | |
2108 CHECK_VALUE(vts_attributes->nr_of_vtstt_subp_streams <= nr_coded); | |
2109 for(i = vts_attributes->nr_of_vtstt_subp_streams; i < nr_coded; i++) | |
2110 CHECK_ZERO(vts_attributes->vtstt_subp_attr[i]); | |
2111 } | |
2112 | |
2113 return 1; | |
2114 } | |
2115 | |
2116 | |
2117 | |
2118 int ifoRead_VTS_ATRT(ifo_handle_t *ifofile) { | |
2119 vts_atrt_t *vts_atrt; | |
2120 unsigned int i, info_length, sector; | |
2121 uint32_t *data; | |
2122 | |
2123 if(!ifofile) | |
2124 return 0; | |
20 | 2125 |
3 | 2126 if(!ifofile->vmgi_mat) |
2127 return 0; | |
20 | 2128 |
3 | 2129 if(ifofile->vmgi_mat->vts_atrt == 0) /* mandatory */ |
2130 return 0; | |
20 | 2131 |
3 | 2132 sector = ifofile->vmgi_mat->vts_atrt; |
2133 if(!DVDFileSeek_(ifofile->file, sector * DVD_BLOCK_LEN)) | |
2134 return 0; | |
2135 | |
2136 vts_atrt = (vts_atrt_t *)malloc(sizeof(vts_atrt_t)); | |
2137 if(!vts_atrt) | |
2138 return 0; | |
2139 | |
2140 ifofile->vts_atrt = vts_atrt; | |
20 | 2141 |
3 | 2142 if(!(DVDReadBytes(ifofile->file, vts_atrt, VTS_ATRT_SIZE))) { |
2143 free(vts_atrt); | |
2144 ifofile->vts_atrt = 0; | |
2145 return 0; | |
2146 } | |
2147 | |
2148 B2N_16(vts_atrt->nr_of_vtss); | |
2149 B2N_32(vts_atrt->last_byte); | |
2150 | |
2151 CHECK_ZERO(vts_atrt->zero_1); | |
2152 CHECK_VALUE(vts_atrt->nr_of_vtss != 0); | |
2153 CHECK_VALUE(vts_atrt->nr_of_vtss < 100); /* ?? */ | |
20 | 2154 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
|
2155 VTS_ATRT_SIZE < vts_atrt->last_byte + 1); |
3 | 2156 |
2157 info_length = vts_atrt->nr_of_vtss * sizeof(uint32_t); | |
2158 data = (uint32_t *)malloc(info_length); | |
2159 if(!data) { | |
2160 free(vts_atrt); | |
2161 ifofile->vts_atrt = 0; | |
2162 return 0; | |
2163 } | |
2164 | |
20 | 2165 vts_atrt->vts_atrt_offsets = data; |
3 | 2166 |
2167 if(!(DVDReadBytes(ifofile->file, data, info_length))) { | |
2168 free(data); | |
2169 free(vts_atrt); | |
2170 ifofile->vts_atrt = 0; | |
2171 return 0; | |
2172 } | |
20 | 2173 |
3 | 2174 for(i = 0; i < vts_atrt->nr_of_vtss; i++) { |
2175 B2N_32(data[i]); | |
2176 CHECK_VALUE(data[i] + VTS_ATTRIBUTES_MIN_SIZE < vts_atrt->last_byte + 1); | |
2177 } | |
20 | 2178 |
3 | 2179 info_length = vts_atrt->nr_of_vtss * sizeof(vts_attributes_t); |
2180 vts_atrt->vts = (vts_attributes_t *)malloc(info_length); | |
2181 if(!vts_atrt->vts) { | |
2182 free(data); | |
2183 free(vts_atrt); | |
2184 ifofile->vts_atrt = 0; | |
2185 return 0; | |
2186 } | |
2187 for(i = 0; i < vts_atrt->nr_of_vtss; i++) { | |
2188 unsigned int offset = data[i]; | |
2189 if(!ifoRead_VTS_ATTRIBUTES(ifofile, &(vts_atrt->vts[i]), | |
2190 (sector * DVD_BLOCK_LEN) + offset)) { | |
2191 free(data); | |
2192 free(vts_atrt); | |
2193 ifofile->vts_atrt = 0; | |
2194 return 0; | |
2195 } | |
2196 | |
2197 /* This assert cant be in ifoRead_VTS_ATTRIBUTES */ | |
2198 CHECK_VALUE(offset + vts_atrt->vts[i].last_byte <= vts_atrt->last_byte + 1); | |
2199 /* Is this check correct? */ | |
2200 } | |
2201 | |
2202 return 1; | |
2203 } | |
2204 | |
2205 | |
2206 void ifoFree_VTS_ATRT(ifo_handle_t *ifofile) { | |
2207 if(!ifofile) | |
2208 return; | |
20 | 2209 |
3 | 2210 if(ifofile->vts_atrt) { |
2211 free(ifofile->vts_atrt->vts); | |
2212 free(ifofile->vts_atrt->vts_atrt_offsets); | |
2213 free(ifofile->vts_atrt); | |
2214 ifofile->vts_atrt = 0; | |
2215 } | |
2216 } | |
2217 | |
2218 | |
2219 int ifoRead_TXTDT_MGI(ifo_handle_t *ifofile) { | |
2220 txtdt_mgi_t *txtdt_mgi; | |
2221 | |
2222 if(!ifofile) | |
2223 return 0; | |
20 | 2224 |
3 | 2225 if(!ifofile->vmgi_mat) |
2226 return 0; | |
20 | 2227 |
2228 /* Return successfully if there is nothing to read. */ | |
3 | 2229 if(ifofile->vmgi_mat->txtdt_mgi == 0) |
2230 return 1; | |
2231 | |
20 | 2232 if(!DVDFileSeek_(ifofile->file, |
26 | 2233 ifofile->vmgi_mat->txtdt_mgi * DVD_BLOCK_LEN)) |
3 | 2234 return 0; |
20 | 2235 |
3 | 2236 txtdt_mgi = (txtdt_mgi_t *)malloc(sizeof(txtdt_mgi_t)); |
2237 if(!txtdt_mgi) { | |
2238 return 0; | |
2239 } | |
2240 ifofile->txtdt_mgi = txtdt_mgi; | |
2241 | |
2242 if(!(DVDReadBytes(ifofile->file, txtdt_mgi, TXTDT_MGI_SIZE))) { | |
2243 fprintf(stderr, "libdvdread: Unable to read TXTDT_MGI.\n"); | |
2244 free(txtdt_mgi); | |
2245 ifofile->txtdt_mgi = 0; | |
2246 return 0; | |
2247 } | |
2248 | |
2249 /* fprintf(stderr, "-- Not done yet --\n"); */ | |
2250 return 1; | |
2251 } | |
2252 | |
2253 void ifoFree_TXTDT_MGI(ifo_handle_t *ifofile) { | |
2254 if(!ifofile) | |
2255 return; | |
20 | 2256 |
3 | 2257 if(ifofile->txtdt_mgi) { |
2258 free(ifofile->txtdt_mgi); | |
2259 ifofile->txtdt_mgi = 0; | |
2260 } | |
2261 } |