Mercurial > libdvdread4.hg
annotate ifo_read.c @ 64:70c34d162e6e src
Replaces the hard-coded values
The parental management structure has ratings levels. The size
of the bit mask is constant but magic values were being used
instead of named constants. This commit changes them to named
constants. This is based on a patch submitted by Frederic Marchal,
fmarchal at perso dot be. Thanks for this tidy cleanup.
author | erik |
---|---|
date | Sun, 30 Jan 2011 23:44:13 +0000 |
parents | 46c05a214511 |
children | fb0ccb03eb7d |
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 } | |
63 | 1328 for(i = 0; i < ptl_mait->nr_of_countries; i++) { |
1329 ptl_mait->countries[i].pf_ptl_mai = NULL; | |
1330 } | |
20 | 1331 |
3 | 1332 for(i = 0; i < ptl_mait->nr_of_countries; i++) { |
1333 if(!(DVDReadBytes(ifofile->file, &ptl_mait->countries[i], PTL_MAIT_COUNTRY_SIZE))) { | |
1334 fprintf(stderr, "libdvdread: Unable to read PTL_MAIT.\n"); | |
1335 free(ptl_mait->countries); | |
1336 free(ptl_mait); | |
1337 ifofile->ptl_mait = 0; | |
1338 return 0; | |
1339 } | |
1340 } | |
1341 | |
1342 for(i = 0; i < ptl_mait->nr_of_countries; i++) { | |
1343 B2N_16(ptl_mait->countries[i].country_code); | |
1344 B2N_16(ptl_mait->countries[i].pf_ptl_mai_start_byte); | |
1345 } | |
20 | 1346 |
3 | 1347 for(i = 0; i < ptl_mait->nr_of_countries; i++) { |
1348 CHECK_ZERO(ptl_mait->countries[i].zero_1); | |
20 | 1349 CHECK_ZERO(ptl_mait->countries[i].zero_2); |
3 | 1350 CHECK_VALUE(ptl_mait->countries[i].pf_ptl_mai_start_byte |
64 | 1351 + sizeof(pf_level_t) * (ptl_mait->nr_of_vtss + 1) <= ptl_mait->last_byte + 1); |
3 | 1352 } |
1353 | |
1354 for(i = 0; i < ptl_mait->nr_of_countries; i++) { | |
1355 uint16_t *pf_temp; | |
20 | 1356 |
1357 if(!DVDFileSeek_(ifofile->file, | |
26 | 1358 ifofile->vmgi_mat->ptl_mait * DVD_BLOCK_LEN |
3 | 1359 + ptl_mait->countries[i].pf_ptl_mai_start_byte)) { |
58 | 1360 fprintf(stderr, "libdvdread: Unable to seek PTL_MAIT table.\n"); |
3 | 1361 free(ptl_mait->countries); |
1362 free(ptl_mait); | |
63 | 1363 ifofile->ptl_mait = NULL; |
3 | 1364 return 0; |
1365 } | |
1366 info_length = (ptl_mait->nr_of_vtss + 1) * sizeof(pf_level_t); | |
1367 pf_temp = (uint16_t *)malloc(info_length); | |
1368 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
|
1369 free_ptl_mait(ptl_mait, i); |
63 | 1370 ifofile->ptl_mait = NULL; |
3 | 1371 return 0; |
1372 } | |
1373 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
|
1374 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
|
1375 free(pf_temp); |
98951f8ec89c
cosmetics: Sync indentation and similar changes from libdvdread 0.9.5.
diego
parents:
26
diff
changeset
|
1376 free_ptl_mait(ptl_mait, i); |
63 | 1377 ifofile->ptl_mait = NULL; |
27
98951f8ec89c
cosmetics: Sync indentation and similar changes from libdvdread 0.9.5.
diego
parents:
26
diff
changeset
|
1378 return 0; |
3 | 1379 } |
1380 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
|
1381 B2N_16(pf_temp[j]); |
3 | 1382 } |
1383 ptl_mait->countries[i].pf_ptl_mai = (pf_level_t *)malloc(info_length); | |
1384 if(!ptl_mait->countries[i].pf_ptl_mai) { | |
1385 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
|
1386 free_ptl_mait(ptl_mait, i); |
63 | 1387 ifofile->ptl_mait = NULL; |
3 | 1388 return 0; |
1389 } | |
1390 { /* Transpose the array so we can use C indexing. */ | |
1391 int level, vts; | |
64 | 1392 for(level = 0; level < PTL_MAIT_NUM_LEVEL; level++) { |
26 | 1393 for(vts = 0; vts <= ptl_mait->nr_of_vtss; vts++) { |
1394 ptl_mait->countries[i].pf_ptl_mai[vts][level] = | |
1395 pf_temp[(7-level)*(ptl_mait->nr_of_vtss+1) + vts]; | |
1396 } | |
3 | 1397 } |
1398 free(pf_temp); | |
1399 } | |
1400 } | |
1401 return 1; | |
1402 } | |
1403 | |
1404 void ifoFree_PTL_MAIT(ifo_handle_t *ifofile) { | |
1405 unsigned int i; | |
20 | 1406 |
3 | 1407 if(!ifofile) |
1408 return; | |
20 | 1409 |
3 | 1410 if(ifofile->ptl_mait) { |
1411 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
|
1412 free(ifofile->ptl_mait->countries[i].pf_ptl_mai); |
3 | 1413 } |
1414 free(ifofile->ptl_mait->countries); | |
1415 free(ifofile->ptl_mait); | |
1416 ifofile->ptl_mait = 0; | |
1417 } | |
1418 } | |
1419 | |
1420 int ifoRead_VTS_TMAPT(ifo_handle_t *ifofile) { | |
1421 vts_tmapt_t *vts_tmapt; | |
1422 uint32_t *vts_tmap_srp; | |
1423 unsigned int offset; | |
1424 int info_length; | |
1425 unsigned int i, j; | |
20 | 1426 |
3 | 1427 if(!ifofile) |
1428 return 0; | |
1429 | |
1430 if(!ifofile->vtsi_mat) | |
1431 return 0; | |
1432 | |
1433 if(ifofile->vtsi_mat->vts_tmapt == 0) { /* optional(?) */ | |
1434 ifofile->vts_tmapt = NULL; | |
1435 fprintf(stderr,"Please send bug report - no VTS_TMAPT ?? \n"); | |
1436 return 1; | |
1437 } | |
20 | 1438 |
3 | 1439 offset = ifofile->vtsi_mat->vts_tmapt * DVD_BLOCK_LEN; |
20 | 1440 |
1441 if(!DVDFileSeek_(ifofile->file, offset)) | |
3 | 1442 return 0; |
20 | 1443 |
3 | 1444 vts_tmapt = (vts_tmapt_t *)malloc(sizeof(vts_tmapt_t)); |
1445 if(!vts_tmapt) | |
1446 return 0; | |
20 | 1447 |
3 | 1448 ifofile->vts_tmapt = vts_tmapt; |
20 | 1449 |
3 | 1450 if(!(DVDReadBytes(ifofile->file, vts_tmapt, VTS_TMAPT_SIZE))) { |
1451 fprintf(stderr, "libdvdread: Unable to read VTS_TMAPT.\n"); | |
1452 free(vts_tmapt); | |
1453 ifofile->vts_tmapt = NULL; | |
1454 return 0; | |
1455 } | |
1456 | |
1457 B2N_16(vts_tmapt->nr_of_tmaps); | |
1458 B2N_32(vts_tmapt->last_byte); | |
20 | 1459 |
3 | 1460 CHECK_ZERO(vts_tmapt->zero_1); |
20 | 1461 |
3 | 1462 info_length = vts_tmapt->nr_of_tmaps * 4; |
20 | 1463 |
3 | 1464 vts_tmap_srp = (uint32_t *)malloc(info_length); |
1465 if(!vts_tmap_srp) { | |
1466 free(vts_tmapt); | |
1467 ifofile->vts_tmapt = NULL; | |
1468 return 0; | |
1469 } | |
1470 | |
1471 vts_tmapt->tmap_offset = vts_tmap_srp; | |
20 | 1472 |
3 | 1473 if(!(DVDReadBytes(ifofile->file, vts_tmap_srp, info_length))) { |
1474 fprintf(stderr, "libdvdread: Unable to read VTS_TMAPT.\n"); | |
1475 free(vts_tmap_srp); | |
1476 free(vts_tmapt); | |
1477 ifofile->vts_tmapt = NULL; | |
1478 return 0; | |
1479 } | |
1480 | |
1481 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
|
1482 B2N_32(vts_tmap_srp[i]); |
3 | 1483 } |
1484 | |
20 | 1485 |
3 | 1486 info_length = vts_tmapt->nr_of_tmaps * sizeof(vts_tmap_t); |
20 | 1487 |
3 | 1488 vts_tmapt->tmap = (vts_tmap_t *)malloc(info_length); |
1489 if(!vts_tmapt->tmap) { | |
1490 free(vts_tmap_srp); | |
1491 free(vts_tmapt); | |
1492 ifofile->vts_tmapt = NULL; | |
1493 return 0; | |
1494 } | |
1495 | |
1496 memset(vts_tmapt->tmap, 0, info_length); /* So ifoFree_VTS_TMAPT works. */ | |
20 | 1497 |
3 | 1498 for(i = 0; i < vts_tmapt->nr_of_tmaps; i++) { |
1499 if(!DVDFileSeek_(ifofile->file, offset + vts_tmap_srp[i])) { | |
1500 ifoFree_VTS_TMAPT(ifofile); | |
1501 return 0; | |
1502 } | |
1503 | |
1504 if(!(DVDReadBytes(ifofile->file, &vts_tmapt->tmap[i], VTS_TMAP_SIZE))) { | |
1505 fprintf(stderr, "libdvdread: Unable to read VTS_TMAP.\n"); | |
1506 ifoFree_VTS_TMAPT(ifofile); | |
1507 return 0; | |
1508 } | |
20 | 1509 |
3 | 1510 B2N_16(vts_tmapt->tmap[i].nr_of_entries); |
1511 CHECK_ZERO(vts_tmapt->tmap[i].zero_1); | |
20 | 1512 |
3 | 1513 if(vts_tmapt->tmap[i].nr_of_entries == 0) { /* Early out if zero entries */ |
1514 vts_tmapt->tmap[i].map_ent = NULL; | |
1515 continue; | |
1516 } | |
20 | 1517 |
3 | 1518 info_length = vts_tmapt->tmap[i].nr_of_entries * sizeof(map_ent_t); |
20 | 1519 |
3 | 1520 vts_tmapt->tmap[i].map_ent = (map_ent_t *)malloc(info_length); |
1521 if(!vts_tmapt->tmap[i].map_ent) { | |
1522 ifoFree_VTS_TMAPT(ifofile); | |
1523 return 0; | |
1524 } | |
1525 | |
1526 if(!(DVDReadBytes(ifofile->file, vts_tmapt->tmap[i].map_ent, info_length))) { | |
1527 fprintf(stderr, "libdvdread: Unable to read VTS_TMAP_ENT.\n"); | |
1528 ifoFree_VTS_TMAPT(ifofile); | |
1529 return 0; | |
1530 } | |
20 | 1531 |
3 | 1532 for(j = 0; j < vts_tmapt->tmap[i].nr_of_entries; j++) |
1533 B2N_32(vts_tmapt->tmap[i].map_ent[j]); | |
20 | 1534 } |
1535 | |
3 | 1536 return 1; |
1537 } | |
1538 | |
1539 void ifoFree_VTS_TMAPT(ifo_handle_t *ifofile) { | |
1540 unsigned int i; | |
20 | 1541 |
3 | 1542 if(!ifofile) |
1543 return; | |
20 | 1544 |
1545 if(ifofile->vts_tmapt) { | |
3 | 1546 for(i = 0; i < ifofile->vts_tmapt->nr_of_tmaps; i++) |
1547 if(ifofile->vts_tmapt->tmap[i].map_ent) | |
26 | 1548 free(ifofile->vts_tmapt->tmap[i].map_ent); |
3 | 1549 free(ifofile->vts_tmapt->tmap); |
1550 free(ifofile->vts_tmapt->tmap_offset); | |
1551 free(ifofile->vts_tmapt); | |
1552 ifofile->vts_tmapt = NULL; | |
1553 } | |
1554 } | |
1555 | |
1556 | |
1557 int ifoRead_TITLE_C_ADT(ifo_handle_t *ifofile) { | |
1558 | |
1559 if(!ifofile) | |
1560 return 0; | |
1561 | |
1562 if(!ifofile->vtsi_mat) | |
1563 return 0; | |
1564 | |
1565 if(ifofile->vtsi_mat->vts_c_adt == 0) /* mandatory */ | |
1566 return 0; | |
1567 | |
1568 ifofile->vts_c_adt = (c_adt_t *)malloc(sizeof(c_adt_t)); | |
1569 if(!ifofile->vts_c_adt) | |
1570 return 0; | |
1571 | |
20 | 1572 if(!ifoRead_C_ADT_internal(ifofile, ifofile->vts_c_adt, |
3 | 1573 ifofile->vtsi_mat->vts_c_adt)) { |
1574 free(ifofile->vts_c_adt); | |
1575 ifofile->vts_c_adt = 0; | |
1576 return 0; | |
1577 } | |
1578 | |
1579 return 1; | |
1580 } | |
1581 | |
1582 int ifoRead_C_ADT(ifo_handle_t *ifofile) { | |
1583 unsigned int sector; | |
1584 | |
1585 if(!ifofile) | |
1586 return 0; | |
20 | 1587 |
3 | 1588 if(ifofile->vmgi_mat) { |
1589 if(ifofile->vmgi_mat->vmgm_c_adt == 0) | |
1590 return 1; | |
1591 sector = ifofile->vmgi_mat->vmgm_c_adt; | |
1592 } else if(ifofile->vtsi_mat) { | |
1593 if(ifofile->vtsi_mat->vtsm_c_adt == 0) | |
1594 return 1; | |
1595 sector = ifofile->vtsi_mat->vtsm_c_adt; | |
1596 } else { | |
1597 return 0; | |
1598 } | |
20 | 1599 |
3 | 1600 ifofile->menu_c_adt = (c_adt_t *)malloc(sizeof(c_adt_t)); |
1601 if(!ifofile->menu_c_adt) | |
1602 return 0; | |
1603 | |
1604 if(!ifoRead_C_ADT_internal(ifofile, ifofile->menu_c_adt, sector)) { | |
1605 free(ifofile->menu_c_adt); | |
1606 ifofile->menu_c_adt = 0; | |
1607 return 0; | |
1608 } | |
1609 | |
1610 return 1; | |
1611 } | |
1612 | |
20 | 1613 static int ifoRead_C_ADT_internal(ifo_handle_t *ifofile, |
3 | 1614 c_adt_t *c_adt, unsigned int sector) { |
1615 int i, info_length; | |
1616 | |
1617 if(!DVDFileSeek_(ifofile->file, sector * DVD_BLOCK_LEN)) | |
1618 return 0; | |
1619 | |
1620 if(!(DVDReadBytes(ifofile->file, c_adt, C_ADT_SIZE))) | |
1621 return 0; | |
1622 | |
1623 B2N_16(c_adt->nr_of_vobs); | |
1624 B2N_32(c_adt->last_byte); | |
20 | 1625 |
3 | 1626 info_length = c_adt->last_byte + 1 - C_ADT_SIZE; |
20 | 1627 |
3 | 1628 CHECK_ZERO(c_adt->zero_1); |
20 | 1629 /* assert(c_adt->nr_of_vobs > 0); |
1630 Magic Knight Rayearth Daybreak is mastered very strange and has | |
3 | 1631 Titles with a VOBS that has no cells. */ |
1632 CHECK_VALUE(info_length % sizeof(cell_adr_t) == 0); | |
20 | 1633 |
3 | 1634 /* assert(info_length / sizeof(cell_adr_t) >= c_adt->nr_of_vobs); |
1635 Enemy of the State region 2 (de) has Titles where nr_of_vobs field | |
1636 is to high, they high ones are never referenced though. */ | |
1637 if(info_length / sizeof(cell_adr_t) < c_adt->nr_of_vobs) { | |
61 | 1638 fprintf(stderr, "libdvdread: *C_ADT nr_of_vobs > available info entries\n"); |
3 | 1639 c_adt->nr_of_vobs = info_length / sizeof(cell_adr_t); |
1640 } | |
20 | 1641 |
3 | 1642 c_adt->cell_adr_table = (cell_adr_t *)malloc(info_length); |
1643 if(!c_adt->cell_adr_table) | |
1644 return 0; | |
1645 | |
20 | 1646 if(info_length && |
3 | 1647 !(DVDReadBytes(ifofile->file, c_adt->cell_adr_table, info_length))) { |
1648 free(c_adt->cell_adr_table); | |
1649 return 0; | |
1650 } | |
1651 | |
1652 for(i = 0; i < info_length/sizeof(cell_adr_t); i++) { | |
1653 B2N_16(c_adt->cell_adr_table[i].vob_id); | |
1654 B2N_32(c_adt->cell_adr_table[i].start_sector); | |
1655 B2N_32(c_adt->cell_adr_table[i].last_sector); | |
1656 | |
1657 CHECK_ZERO(c_adt->cell_adr_table[i].zero_1); | |
1658 CHECK_VALUE(c_adt->cell_adr_table[i].vob_id > 0); | |
1659 CHECK_VALUE(c_adt->cell_adr_table[i].vob_id <= c_adt->nr_of_vobs); | |
1660 CHECK_VALUE(c_adt->cell_adr_table[i].cell_id > 0); | |
20 | 1661 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
|
1662 c_adt->cell_adr_table[i].last_sector); |
3 | 1663 } |
1664 | |
1665 return 1; | |
1666 } | |
1667 | |
1668 | |
1669 static void ifoFree_C_ADT_internal(c_adt_t *c_adt) { | |
1670 if(c_adt) { | |
1671 free(c_adt->cell_adr_table); | |
1672 free(c_adt); | |
1673 } | |
1674 } | |
1675 | |
1676 void ifoFree_C_ADT(ifo_handle_t *ifofile) { | |
1677 if(!ifofile) | |
1678 return; | |
20 | 1679 |
3 | 1680 ifoFree_C_ADT_internal(ifofile->menu_c_adt); |
1681 ifofile->menu_c_adt = 0; | |
1682 } | |
1683 | |
1684 void ifoFree_TITLE_C_ADT(ifo_handle_t *ifofile) { | |
1685 if(!ifofile) | |
1686 return; | |
20 | 1687 |
3 | 1688 ifoFree_C_ADT_internal(ifofile->vts_c_adt); |
1689 ifofile->vts_c_adt = 0; | |
1690 } | |
1691 | |
1692 int ifoRead_TITLE_VOBU_ADMAP(ifo_handle_t *ifofile) { | |
1693 if(!ifofile) | |
1694 return 0; | |
1695 | |
1696 if(!ifofile->vtsi_mat) | |
1697 return 0; | |
20 | 1698 |
3 | 1699 if(ifofile->vtsi_mat->vts_vobu_admap == 0) /* mandatory */ |
1700 return 0; | |
20 | 1701 |
3 | 1702 ifofile->vts_vobu_admap = (vobu_admap_t *)malloc(sizeof(vobu_admap_t)); |
1703 if(!ifofile->vts_vobu_admap) | |
1704 return 0; | |
1705 | |
1706 if(!ifoRead_VOBU_ADMAP_internal(ifofile, ifofile->vts_vobu_admap, | |
1707 ifofile->vtsi_mat->vts_vobu_admap)) { | |
1708 free(ifofile->vts_vobu_admap); | |
1709 ifofile->vts_vobu_admap = 0; | |
1710 return 0; | |
1711 } | |
1712 | |
1713 return 1; | |
1714 } | |
1715 | |
1716 int ifoRead_VOBU_ADMAP(ifo_handle_t *ifofile) { | |
1717 unsigned int sector; | |
1718 | |
1719 if(!ifofile) | |
1720 return 0; | |
20 | 1721 |
3 | 1722 if(ifofile->vmgi_mat) { |
1723 if(ifofile->vmgi_mat->vmgm_vobu_admap == 0) | |
1724 return 1; | |
1725 sector = ifofile->vmgi_mat->vmgm_vobu_admap; | |
1726 } else if(ifofile->vtsi_mat) { | |
1727 if(ifofile->vtsi_mat->vtsm_vobu_admap == 0) | |
1728 return 1; | |
1729 sector = ifofile->vtsi_mat->vtsm_vobu_admap; | |
1730 } else { | |
1731 return 0; | |
1732 } | |
20 | 1733 |
3 | 1734 ifofile->menu_vobu_admap = (vobu_admap_t *)malloc(sizeof(vobu_admap_t)); |
1735 if(!ifofile->menu_vobu_admap) | |
1736 return 0; | |
20 | 1737 |
3 | 1738 if(!ifoRead_VOBU_ADMAP_internal(ifofile, ifofile->menu_vobu_admap, sector)) { |
1739 free(ifofile->menu_vobu_admap); | |
1740 ifofile->menu_vobu_admap = 0; | |
1741 return 0; | |
1742 } | |
1743 | |
1744 return 1; | |
1745 } | |
1746 | |
20 | 1747 static int ifoRead_VOBU_ADMAP_internal(ifo_handle_t *ifofile, |
1748 vobu_admap_t *vobu_admap, | |
26 | 1749 unsigned int sector) { |
3 | 1750 unsigned int i; |
1751 int info_length; | |
1752 | |
1753 if(!DVDFileSeekForce_(ifofile->file, sector * DVD_BLOCK_LEN, sector)) | |
1754 return 0; | |
1755 | |
1756 if(!(DVDReadBytes(ifofile->file, vobu_admap, VOBU_ADMAP_SIZE))) | |
1757 return 0; | |
1758 | |
1759 B2N_32(vobu_admap->last_byte); | |
20 | 1760 |
3 | 1761 info_length = vobu_admap->last_byte + 1 - VOBU_ADMAP_SIZE; |
1762 /* assert(info_length > 0); | |
20 | 1763 Magic Knight Rayearth Daybreak is mastered very strange and has |
3 | 1764 Titles with a VOBS that has no VOBUs. */ |
1765 CHECK_VALUE(info_length % sizeof(uint32_t) == 0); | |
20 | 1766 |
1767 vobu_admap->vobu_start_sectors = (uint32_t *)malloc(info_length); | |
3 | 1768 if(!vobu_admap->vobu_start_sectors) { |
1769 return 0; | |
1770 } | |
20 | 1771 if(info_length && |
1772 !(DVDReadBytes(ifofile->file, | |
26 | 1773 vobu_admap->vobu_start_sectors, info_length))) { |
3 | 1774 free(vobu_admap->vobu_start_sectors); |
1775 return 0; | |
1776 } | |
1777 | |
1778 for(i = 0; i < info_length/sizeof(uint32_t); i++) | |
1779 B2N_32(vobu_admap->vobu_start_sectors[i]); | |
1780 | |
1781 return 1; | |
1782 } | |
1783 | |
1784 | |
1785 static void ifoFree_VOBU_ADMAP_internal(vobu_admap_t *vobu_admap) { | |
1786 if(vobu_admap) { | |
1787 free(vobu_admap->vobu_start_sectors); | |
1788 free(vobu_admap); | |
1789 } | |
1790 } | |
1791 | |
1792 void ifoFree_VOBU_ADMAP(ifo_handle_t *ifofile) { | |
1793 if(!ifofile) | |
1794 return; | |
20 | 1795 |
3 | 1796 ifoFree_VOBU_ADMAP_internal(ifofile->menu_vobu_admap); |
1797 ifofile->menu_vobu_admap = 0; | |
1798 } | |
1799 | |
1800 void ifoFree_TITLE_VOBU_ADMAP(ifo_handle_t *ifofile) { | |
1801 if(!ifofile) | |
1802 return; | |
20 | 1803 |
3 | 1804 ifoFree_VOBU_ADMAP_internal(ifofile->vts_vobu_admap); |
1805 ifofile->vts_vobu_admap = 0; | |
1806 } | |
1807 | |
1808 int ifoRead_PGCIT(ifo_handle_t *ifofile) { | |
1809 | |
1810 if(!ifofile) | |
1811 return 0; | |
20 | 1812 |
3 | 1813 if(!ifofile->vtsi_mat) |
1814 return 0; | |
20 | 1815 |
3 | 1816 if(ifofile->vtsi_mat->vts_pgcit == 0) /* mandatory */ |
1817 return 0; | |
20 | 1818 |
3 | 1819 ifofile->vts_pgcit = (pgcit_t *)malloc(sizeof(pgcit_t)); |
1820 if(!ifofile->vts_pgcit) | |
1821 return 0; | |
1822 | |
20 | 1823 if(!ifoRead_PGCIT_internal(ifofile, ifofile->vts_pgcit, |
3 | 1824 ifofile->vtsi_mat->vts_pgcit * DVD_BLOCK_LEN)) { |
1825 free(ifofile->vts_pgcit); | |
1826 ifofile->vts_pgcit = 0; | |
1827 return 0; | |
1828 } | |
1829 | |
1830 return 1; | |
1831 } | |
1832 | |
20 | 1833 static int ifoRead_PGCIT_internal(ifo_handle_t *ifofile, pgcit_t *pgcit, |
3 | 1834 unsigned int offset) { |
1835 int i, info_length; | |
1836 uint8_t *data, *ptr; | |
20 | 1837 |
3 | 1838 if(!DVDFileSeek_(ifofile->file, offset)) |
1839 return 0; | |
1840 | |
1841 if(!(DVDReadBytes(ifofile->file, pgcit, PGCIT_SIZE))) | |
1842 return 0; | |
1843 | |
1844 B2N_16(pgcit->nr_of_pgci_srp); | |
1845 B2N_32(pgcit->last_byte); | |
20 | 1846 |
3 | 1847 CHECK_ZERO(pgcit->zero_1); |
1848 /* assert(pgcit->nr_of_pgci_srp != 0); | |
20 | 1849 Magic Knight Rayearth Daybreak is mastered very strange and has |
3 | 1850 Titles with 0 PTTs. */ |
1851 CHECK_VALUE(pgcit->nr_of_pgci_srp < 10000); /* ?? seen max of 1338 */ | |
20 | 1852 |
3 | 1853 info_length = pgcit->nr_of_pgci_srp * PGCI_SRP_SIZE; |
1854 data = malloc(info_length); | |
1855 if(!data) | |
1856 return 0; | |
1857 | |
1858 if(info_length && !(DVDReadBytes(ifofile->file, data, info_length))) { | |
1859 free(data); | |
1860 return 0; | |
1861 } | |
1862 | |
1863 pgcit->pgci_srp = malloc(pgcit->nr_of_pgci_srp * sizeof(pgci_srp_t)); | |
1864 if(!pgcit->pgci_srp) { | |
1865 free(data); | |
1866 return 0; | |
1867 } | |
1868 ptr = data; | |
1869 for(i = 0; i < pgcit->nr_of_pgci_srp; i++) { | |
1870 memcpy(&pgcit->pgci_srp[i], ptr, PGCI_SRP_SIZE); | |
1871 ptr += PGCI_SRP_SIZE; | |
1872 read_pgci_srp(&pgcit->pgci_srp[i]); | |
1873 CHECK_VALUE(pgcit->pgci_srp[i].unknown1 == 0); | |
1874 } | |
1875 free(data); | |
20 | 1876 |
3 | 1877 for(i = 0; i < pgcit->nr_of_pgci_srp; i++) |
1878 CHECK_VALUE(pgcit->pgci_srp[i].pgc_start_byte + PGC_SIZE <= pgcit->last_byte+1); | |
20 | 1879 |
3 | 1880 for(i = 0; i < pgcit->nr_of_pgci_srp; i++) { |
1881 pgcit->pgci_srp[i].pgc = malloc(sizeof(pgc_t)); | |
1882 if(!pgcit->pgci_srp[i].pgc) { | |
1883 int j; | |
1884 for(j = 0; j < i; j++) { | |
1885 ifoFree_PGC(pgcit->pgci_srp[j].pgc); | |
1886 free(pgcit->pgci_srp[j].pgc); | |
1887 } | |
1888 goto fail; | |
1889 } | |
20 | 1890 if(!ifoRead_PGC(ifofile, pgcit->pgci_srp[i].pgc, |
3 | 1891 offset + pgcit->pgci_srp[i].pgc_start_byte)) { |
1892 int j; | |
1893 for(j = 0; j < i; j++) { | |
1894 ifoFree_PGC(pgcit->pgci_srp[j].pgc); | |
1895 free(pgcit->pgci_srp[j].pgc); | |
1896 } | |
1897 goto fail; | |
1898 } | |
1899 } | |
1900 | |
1901 return 1; | |
1902 fail: | |
1903 free(pgcit->pgci_srp); | |
1904 pgcit->pgci_srp = NULL; | |
1905 return 0; | |
1906 } | |
1907 | |
1908 static void ifoFree_PGCIT_internal(pgcit_t *pgcit) { | |
1909 if(pgcit) { | |
1910 int i; | |
1911 for(i = 0; i < pgcit->nr_of_pgci_srp; i++) | |
1912 ifoFree_PGC(pgcit->pgci_srp[i].pgc); | |
1913 free(pgcit->pgci_srp); | |
1914 } | |
1915 } | |
1916 | |
1917 void ifoFree_PGCIT(ifo_handle_t *ifofile) { | |
1918 if(!ifofile) | |
1919 return; | |
20 | 1920 |
3 | 1921 if(ifofile->vts_pgcit) { |
1922 ifoFree_PGCIT_internal(ifofile->vts_pgcit); | |
1923 free(ifofile->vts_pgcit); | |
1924 ifofile->vts_pgcit = 0; | |
1925 } | |
1926 } | |
1927 | |
1928 | |
1929 int ifoRead_PGCI_UT(ifo_handle_t *ifofile) { | |
1930 pgci_ut_t *pgci_ut; | |
1931 unsigned int sector; | |
20 | 1932 unsigned int i; |
3 | 1933 int info_length; |
1934 uint8_t *data, *ptr; | |
1935 | |
1936 if(!ifofile) | |
1937 return 0; | |
20 | 1938 |
3 | 1939 if(ifofile->vmgi_mat) { |
1940 if(ifofile->vmgi_mat->vmgm_pgci_ut == 0) | |
1941 return 1; | |
1942 sector = ifofile->vmgi_mat->vmgm_pgci_ut; | |
1943 } else if(ifofile->vtsi_mat) { | |
1944 if(ifofile->vtsi_mat->vtsm_pgci_ut == 0) | |
1945 return 1; | |
1946 sector = ifofile->vtsi_mat->vtsm_pgci_ut; | |
1947 } else { | |
1948 return 0; | |
1949 } | |
20 | 1950 |
3 | 1951 ifofile->pgci_ut = (pgci_ut_t *)malloc(sizeof(pgci_ut_t)); |
1952 if(!ifofile->pgci_ut) | |
1953 return 0; | |
20 | 1954 |
3 | 1955 if(!DVDFileSeek_(ifofile->file, sector * DVD_BLOCK_LEN)) { |
1956 free(ifofile->pgci_ut); | |
1957 ifofile->pgci_ut = 0; | |
1958 return 0; | |
1959 } | |
20 | 1960 |
3 | 1961 if(!(DVDReadBytes(ifofile->file, ifofile->pgci_ut, PGCI_UT_SIZE))) { |
1962 free(ifofile->pgci_ut); | |
1963 ifofile->pgci_ut = 0; | |
1964 return 0; | |
1965 } | |
20 | 1966 |
3 | 1967 pgci_ut = ifofile->pgci_ut; |
20 | 1968 |
3 | 1969 B2N_16(pgci_ut->nr_of_lus); |
1970 B2N_32(pgci_ut->last_byte); | |
20 | 1971 |
3 | 1972 CHECK_ZERO(pgci_ut->zero_1); |
1973 CHECK_VALUE(pgci_ut->nr_of_lus != 0); | |
1974 CHECK_VALUE(pgci_ut->nr_of_lus < 100); /* ?? 3-4 ? */ | |
1975 CHECK_VALUE((uint32_t)pgci_ut->nr_of_lus * PGCI_LU_SIZE < pgci_ut->last_byte); | |
1976 | |
1977 info_length = pgci_ut->nr_of_lus * PGCI_LU_SIZE; | |
1978 data = malloc(info_length); | |
1979 if(!data) { | |
1980 free(pgci_ut); | |
1981 ifofile->pgci_ut = 0; | |
1982 return 0; | |
1983 } | |
1984 if(!(DVDReadBytes(ifofile->file, data, info_length))) { | |
1985 free(data); | |
1986 free(pgci_ut); | |
1987 ifofile->pgci_ut = 0; | |
1988 return 0; | |
1989 } | |
1990 | |
1991 pgci_ut->lu = malloc(pgci_ut->nr_of_lus * sizeof(pgci_lu_t)); | |
1992 if(!pgci_ut->lu) { | |
1993 free(data); | |
1994 free(pgci_ut); | |
1995 ifofile->pgci_ut = 0; | |
27
98951f8ec89c
cosmetics: Sync indentation and similar changes from libdvdread 0.9.5.
diego
parents:
26
diff
changeset
|
1996 return 0; |
3 | 1997 } |
1998 ptr = data; | |
1999 for(i = 0; i < pgci_ut->nr_of_lus; i++) { | |
2000 memcpy(&pgci_ut->lu[i], ptr, PGCI_LU_SIZE); | |
2001 ptr += PGCI_LU_SIZE; | |
20 | 2002 B2N_16(pgci_ut->lu[i].lang_code); |
2003 B2N_32(pgci_ut->lu[i].lang_start_byte); | |
3 | 2004 } |
2005 free(data); | |
20 | 2006 |
3 | 2007 for(i = 0; i < pgci_ut->nr_of_lus; i++) { |
2008 /* Maybe this is only defined for v1.1 and later titles? */ | |
2009 /* 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
|
2010 VTS_x_yy.IFO VIDEO_TS.IFO |
3 | 2011 a == 0x83 "Root" 0x82 "Title" |
2012 b == 0x84 "Subpicture" | |
2013 c == 0x85 "Audio" | |
2014 d == 0x86 "Angle" | |
2015 e == 0x87 "PTT" | |
2016 */ | |
2017 CHECK_VALUE((pgci_ut->lu[i].exists & 0x07) == 0); | |
2018 } | |
2019 | |
2020 for(i = 0; i < pgci_ut->nr_of_lus; i++) { | |
2021 pgci_ut->lu[i].pgcit = malloc(sizeof(pgcit_t)); | |
2022 if(!pgci_ut->lu[i].pgcit) { | |
2023 unsigned int j; | |
2024 for(j = 0; j < i; j++) { | |
2025 ifoFree_PGCIT_internal(pgci_ut->lu[j].pgcit); | |
2026 free(pgci_ut->lu[j].pgcit); | |
2027 } | |
2028 free(pgci_ut->lu); | |
2029 free(pgci_ut); | |
2030 ifofile->pgci_ut = 0; | |
2031 return 0; | |
2032 } | |
20 | 2033 if(!ifoRead_PGCIT_internal(ifofile, pgci_ut->lu[i].pgcit, |
2034 sector * DVD_BLOCK_LEN | |
3 | 2035 + pgci_ut->lu[i].lang_start_byte)) { |
2036 unsigned int j; | |
2037 for(j = 0; j < i; j++) { | |
2038 ifoFree_PGCIT_internal(pgci_ut->lu[j].pgcit); | |
2039 free(pgci_ut->lu[j].pgcit); | |
2040 } | |
2041 free(pgci_ut->lu[i].pgcit); | |
2042 free(pgci_ut->lu); | |
2043 free(pgci_ut); | |
2044 ifofile->pgci_ut = 0; | |
2045 return 0; | |
2046 } | |
27
98951f8ec89c
cosmetics: Sync indentation and similar changes from libdvdread 0.9.5.
diego
parents:
26
diff
changeset
|
2047 /* 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
|
2048 * to pgci_ut->lu[i].exists really do? */ |
3 | 2049 } |
2050 | |
2051 return 1; | |
2052 } | |
2053 | |
2054 | |
2055 void ifoFree_PGCI_UT(ifo_handle_t *ifofile) { | |
2056 unsigned int i; | |
2057 | |
2058 if(!ifofile) | |
2059 return; | |
20 | 2060 |
3 | 2061 if(ifofile->pgci_ut) { |
2062 for(i = 0; i < ifofile->pgci_ut->nr_of_lus; i++) { | |
2063 ifoFree_PGCIT_internal(ifofile->pgci_ut->lu[i].pgcit); | |
2064 free(ifofile->pgci_ut->lu[i].pgcit); | |
2065 } | |
2066 free(ifofile->pgci_ut->lu); | |
2067 free(ifofile->pgci_ut); | |
2068 ifofile->pgci_ut = 0; | |
2069 } | |
2070 } | |
2071 | |
20 | 2072 static int ifoRead_VTS_ATTRIBUTES(ifo_handle_t *ifofile, |
2073 vts_attributes_t *vts_attributes, | |
3 | 2074 unsigned int offset) { |
2075 unsigned int i; | |
2076 | |
2077 if(!DVDFileSeek_(ifofile->file, offset)) | |
2078 return 0; | |
2079 | |
2080 if(!(DVDReadBytes(ifofile->file, vts_attributes, sizeof(vts_attributes_t)))) | |
2081 return 0; | |
2082 | |
2083 read_video_attr(&vts_attributes->vtsm_vobs_attr); | |
2084 read_video_attr(&vts_attributes->vtstt_vobs_video_attr); | |
2085 read_audio_attr(&vts_attributes->vtsm_audio_attr); | |
2086 for(i=0; i<8; i++) | |
2087 read_audio_attr(&vts_attributes->vtstt_audio_attr[i]); | |
2088 read_subp_attr(&vts_attributes->vtsm_subp_attr); | |
2089 for(i=0; i<32; i++) | |
2090 read_subp_attr(&vts_attributes->vtstt_subp_attr[i]); | |
2091 B2N_32(vts_attributes->last_byte); | |
2092 B2N_32(vts_attributes->vts_cat); | |
20 | 2093 |
3 | 2094 CHECK_ZERO(vts_attributes->zero_1); |
2095 CHECK_ZERO(vts_attributes->zero_2); | |
2096 CHECK_ZERO(vts_attributes->zero_3); | |
2097 CHECK_ZERO(vts_attributes->zero_4); | |
2098 CHECK_ZERO(vts_attributes->zero_5); | |
2099 CHECK_ZERO(vts_attributes->zero_6); | |
2100 CHECK_ZERO(vts_attributes->zero_7); | |
2101 CHECK_VALUE(vts_attributes->nr_of_vtsm_audio_streams <= 1); | |
2102 CHECK_VALUE(vts_attributes->nr_of_vtsm_subp_streams <= 1); | |
2103 CHECK_VALUE(vts_attributes->nr_of_vtstt_audio_streams <= 8); | |
2104 for(i = vts_attributes->nr_of_vtstt_audio_streams; i < 8; i++) | |
2105 CHECK_ZERO(vts_attributes->vtstt_audio_attr[i]); | |
2106 CHECK_VALUE(vts_attributes->nr_of_vtstt_subp_streams <= 32); | |
2107 { | |
2108 unsigned int nr_coded; | |
20 | 2109 CHECK_VALUE(vts_attributes->last_byte + 1 >= VTS_ATTRIBUTES_MIN_SIZE); |
3 | 2110 nr_coded = (vts_attributes->last_byte + 1 - VTS_ATTRIBUTES_MIN_SIZE)/6; |
2111 /* This is often nr_coded = 70, how do you know how many there really are? */ | |
2112 if(nr_coded > 32) { /* We haven't read more from disk/file anyway */ | |
2113 nr_coded = 32; | |
2114 } | |
2115 CHECK_VALUE(vts_attributes->nr_of_vtstt_subp_streams <= nr_coded); | |
2116 for(i = vts_attributes->nr_of_vtstt_subp_streams; i < nr_coded; i++) | |
2117 CHECK_ZERO(vts_attributes->vtstt_subp_attr[i]); | |
2118 } | |
2119 | |
2120 return 1; | |
2121 } | |
2122 | |
2123 | |
2124 | |
2125 int ifoRead_VTS_ATRT(ifo_handle_t *ifofile) { | |
2126 vts_atrt_t *vts_atrt; | |
2127 unsigned int i, info_length, sector; | |
2128 uint32_t *data; | |
2129 | |
2130 if(!ifofile) | |
2131 return 0; | |
20 | 2132 |
3 | 2133 if(!ifofile->vmgi_mat) |
2134 return 0; | |
20 | 2135 |
3 | 2136 if(ifofile->vmgi_mat->vts_atrt == 0) /* mandatory */ |
2137 return 0; | |
20 | 2138 |
3 | 2139 sector = ifofile->vmgi_mat->vts_atrt; |
2140 if(!DVDFileSeek_(ifofile->file, sector * DVD_BLOCK_LEN)) | |
2141 return 0; | |
2142 | |
2143 vts_atrt = (vts_atrt_t *)malloc(sizeof(vts_atrt_t)); | |
2144 if(!vts_atrt) | |
2145 return 0; | |
2146 | |
2147 ifofile->vts_atrt = vts_atrt; | |
20 | 2148 |
3 | 2149 if(!(DVDReadBytes(ifofile->file, vts_atrt, VTS_ATRT_SIZE))) { |
2150 free(vts_atrt); | |
2151 ifofile->vts_atrt = 0; | |
2152 return 0; | |
2153 } | |
2154 | |
2155 B2N_16(vts_atrt->nr_of_vtss); | |
2156 B2N_32(vts_atrt->last_byte); | |
2157 | |
2158 CHECK_ZERO(vts_atrt->zero_1); | |
2159 CHECK_VALUE(vts_atrt->nr_of_vtss != 0); | |
2160 CHECK_VALUE(vts_atrt->nr_of_vtss < 100); /* ?? */ | |
20 | 2161 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
|
2162 VTS_ATRT_SIZE < vts_atrt->last_byte + 1); |
3 | 2163 |
2164 info_length = vts_atrt->nr_of_vtss * sizeof(uint32_t); | |
2165 data = (uint32_t *)malloc(info_length); | |
2166 if(!data) { | |
2167 free(vts_atrt); | |
2168 ifofile->vts_atrt = 0; | |
2169 return 0; | |
2170 } | |
2171 | |
20 | 2172 vts_atrt->vts_atrt_offsets = data; |
3 | 2173 |
2174 if(!(DVDReadBytes(ifofile->file, data, info_length))) { | |
2175 free(data); | |
2176 free(vts_atrt); | |
2177 ifofile->vts_atrt = 0; | |
2178 return 0; | |
2179 } | |
20 | 2180 |
3 | 2181 for(i = 0; i < vts_atrt->nr_of_vtss; i++) { |
2182 B2N_32(data[i]); | |
2183 CHECK_VALUE(data[i] + VTS_ATTRIBUTES_MIN_SIZE < vts_atrt->last_byte + 1); | |
2184 } | |
20 | 2185 |
3 | 2186 info_length = vts_atrt->nr_of_vtss * sizeof(vts_attributes_t); |
2187 vts_atrt->vts = (vts_attributes_t *)malloc(info_length); | |
2188 if(!vts_atrt->vts) { | |
2189 free(data); | |
2190 free(vts_atrt); | |
2191 ifofile->vts_atrt = 0; | |
2192 return 0; | |
2193 } | |
2194 for(i = 0; i < vts_atrt->nr_of_vtss; i++) { | |
2195 unsigned int offset = data[i]; | |
2196 if(!ifoRead_VTS_ATTRIBUTES(ifofile, &(vts_atrt->vts[i]), | |
2197 (sector * DVD_BLOCK_LEN) + offset)) { | |
2198 free(data); | |
2199 free(vts_atrt); | |
2200 ifofile->vts_atrt = 0; | |
2201 return 0; | |
2202 } | |
2203 | |
2204 /* This assert cant be in ifoRead_VTS_ATTRIBUTES */ | |
2205 CHECK_VALUE(offset + vts_atrt->vts[i].last_byte <= vts_atrt->last_byte + 1); | |
2206 /* Is this check correct? */ | |
2207 } | |
2208 | |
2209 return 1; | |
2210 } | |
2211 | |
2212 | |
2213 void ifoFree_VTS_ATRT(ifo_handle_t *ifofile) { | |
2214 if(!ifofile) | |
2215 return; | |
20 | 2216 |
3 | 2217 if(ifofile->vts_atrt) { |
2218 free(ifofile->vts_atrt->vts); | |
2219 free(ifofile->vts_atrt->vts_atrt_offsets); | |
2220 free(ifofile->vts_atrt); | |
2221 ifofile->vts_atrt = 0; | |
2222 } | |
2223 } | |
2224 | |
2225 | |
2226 int ifoRead_TXTDT_MGI(ifo_handle_t *ifofile) { | |
2227 txtdt_mgi_t *txtdt_mgi; | |
2228 | |
2229 if(!ifofile) | |
2230 return 0; | |
20 | 2231 |
3 | 2232 if(!ifofile->vmgi_mat) |
2233 return 0; | |
20 | 2234 |
2235 /* Return successfully if there is nothing to read. */ | |
3 | 2236 if(ifofile->vmgi_mat->txtdt_mgi == 0) |
2237 return 1; | |
2238 | |
20 | 2239 if(!DVDFileSeek_(ifofile->file, |
26 | 2240 ifofile->vmgi_mat->txtdt_mgi * DVD_BLOCK_LEN)) |
3 | 2241 return 0; |
20 | 2242 |
3 | 2243 txtdt_mgi = (txtdt_mgi_t *)malloc(sizeof(txtdt_mgi_t)); |
2244 if(!txtdt_mgi) { | |
2245 return 0; | |
2246 } | |
2247 ifofile->txtdt_mgi = txtdt_mgi; | |
2248 | |
2249 if(!(DVDReadBytes(ifofile->file, txtdt_mgi, TXTDT_MGI_SIZE))) { | |
2250 fprintf(stderr, "libdvdread: Unable to read TXTDT_MGI.\n"); | |
2251 free(txtdt_mgi); | |
2252 ifofile->txtdt_mgi = 0; | |
2253 return 0; | |
2254 } | |
2255 | |
2256 /* fprintf(stderr, "-- Not done yet --\n"); */ | |
2257 return 1; | |
2258 } | |
2259 | |
2260 void ifoFree_TXTDT_MGI(ifo_handle_t *ifofile) { | |
2261 if(!ifofile) | |
2262 return; | |
20 | 2263 |
3 | 2264 if(ifofile->txtdt_mgi) { |
2265 free(ifofile->txtdt_mgi); | |
2266 ifofile->txtdt_mgi = 0; | |
2267 } | |
2268 } |