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