1 /*****************************************************************************
2 * dvd_ifo.c: Functions for ifo parsing
3 *****************************************************************************
4 * Copyright (C) 1999-2001 VideoLAN
5 * $Id: dvd_ifo.c,v 1.35 2001/07/25 08:41:21 gbazin Exp $
7 * Authors: Stéphane Borel <stef@via.ecp.fr>
8 * German Tischler <tanis@gaspode.franken.de>
11 * - libifo by Thomas Mirlacher <dent@cosy.sbg.ac.at>
12 * - IFO structure documentation by Thomas Mirlacher, Björn Englund,
15 * This program is free software; you can redistribute it and/or modify
16 * it under the terms of the GNU General Public License as published by
17 * the Free Software Foundation; either version 2 of the License, or
18 * (at your option) any later version.
20 * This program is distributed in the hope that it will be useful,
21 * but WITHOUT ANY WARRANTY; without even the implied warranty of
22 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
23 * GNU General Public License for more details.
25 * You should have received a copy of the GNU General Public License
26 * along with this program; if not, write to the Free Software
27 * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111, USA.
28 *****************************************************************************/
30 /*****************************************************************************
32 *****************************************************************************/
41 #elif defined( _MSC_VER ) && defined( _WIN32 )
48 #include <videolan/dvdcss.h>
57 #include "input_dvd.h"
62 #include "modules_export.h"
64 /*****************************************************************************
66 *****************************************************************************/
67 void CommandRead ( command_desc_t );
68 static int ReadTitle ( ifo_t * , title_t *, int, int );
69 static int FreeTitle ( title_t * );
70 static int ReadUnitInf ( ifo_t * , unit_inf_t *, int, int );
71 static int FreeUnitInf ( unit_inf_t * );
72 static int ReadTitleUnit ( ifo_t * , title_unit_t *, int );
73 static int FreeTitleUnit ( title_unit_t * );
74 static int ReadVobuMap ( ifo_t * , vobu_map_t *, int );
75 static int FreeVobuMap ( vobu_map_t * );
76 static int ReadCellInf ( ifo_t * , cell_inf_t *, int );
77 static int FreeCellInf ( cell_inf_t * );
78 static int FreeTitleSet ( vts_t * );
80 static u8* FillBuffer ( ifo_t *, u8 *, int );
81 static u8 ReadByte ( ifo_t *, u8 *, u8 ** );
82 static void ReadBytes ( ifo_t *, u8 *, u8 **, u8 *, int );
83 static void DumpBytes ( ifo_t *, u8 *, u8 **, int );
84 static u16 ReadWord ( ifo_t *, u8 *, u8 ** );
85 static u32 ReadDouble ( ifo_t *, u8 *, u8 ** );
86 static u64 ReadQuad ( ifo_t *, u8 *, u8 ** );
92 /*****************************************************************************
93 * IfoCreate : Creates an ifo structure and prepares for parsing directly
95 *****************************************************************************/
96 int IfoCreate( thread_dvd_data_t * p_dvd )
98 p_dvd->p_ifo = malloc( sizeof(ifo_t) );
99 if( p_dvd->p_ifo == NULL )
101 intf_ErrMsg( "ifo error: unable to allocate memory. aborting" );
105 /* if we are here the dvd device has already been opened */
106 p_dvd->p_ifo->dvdhandle = p_dvd->dvdhandle;
111 /*****************************************************************************
112 * IfoInit : Reads information from the management table.
113 *****************************************************************************/
114 int IfoInit( ifo_t * p_ifo )
116 u8 p_buf[DVD_LB_SIZE];
122 /* find the start sector of video information on the dvd */
123 p_ifo->i_start = UDFFindFile( p_ifo->dvdhandle, "/VIDEO_TS/VIDEO_TS.IFO" );
124 if( !p_ifo->i_start ) return -1;
126 p_tmp = FillBuffer( p_ifo, p_buf, p_ifo->i_start );
127 //i_start = p_ifo->i_pos;
130 * read the video manager information table
132 #define MGINF p_ifo->vmg.manager_inf
133 //fprintf( stderr, "VMGI\n" );
135 ReadBytes( p_ifo, p_buf, &p_tmp, MGINF.psz_id, 12 );
136 MGINF.psz_id[12] = '\0';
137 MGINF.i_vmg_end_sector = ReadDouble( p_ifo, p_buf, &p_tmp );
138 DumpBytes( p_ifo, p_buf, &p_tmp, 12 );
139 MGINF.i_vmg_inf_end_sector = ReadDouble( p_ifo, p_buf, &p_tmp );
140 DumpBytes( p_ifo, p_buf, &p_tmp, 1 );
141 MGINF.i_spec_ver = ReadByte( p_ifo, p_buf, &p_tmp );
142 MGINF.i_cat = ReadDouble( p_ifo, p_buf, &p_tmp );
143 MGINF.i_volume_nb = ReadWord( p_ifo, p_buf, &p_tmp );
144 MGINF.i_volume = ReadWord( p_ifo, p_buf, &p_tmp );
145 MGINF.i_disc_side = ReadByte( p_ifo, p_buf, &p_tmp );
146 DumpBytes( p_ifo, p_buf, &p_tmp, 19 );
147 MGINF.i_title_set_nb = ReadWord( p_ifo, p_buf, &p_tmp );
148 ReadBytes( p_ifo, p_buf, &p_tmp, MGINF.ps_provider_id, 32 );
149 MGINF.i_pos_code = ReadQuad( p_ifo, p_buf, &p_tmp );
150 DumpBytes( p_ifo, p_buf, &p_tmp, 24 );
151 MGINF.i_vmg_inf_end_byte = ReadDouble( p_ifo, p_buf, &p_tmp );
152 MGINF.i_first_play_title_start_byte = ReadDouble( p_ifo, p_buf, &p_tmp );
153 DumpBytes( p_ifo, p_buf, &p_tmp, 56 );
154 MGINF.i_vob_start_sector = ReadDouble( p_ifo, p_buf, &p_tmp );
155 MGINF.i_title_inf_start_sector = ReadDouble( p_ifo, p_buf, &p_tmp );
156 MGINF.i_title_unit_start_sector = ReadDouble( p_ifo, p_buf, &p_tmp );
157 MGINF.i_parental_inf_start_sector = ReadDouble( p_ifo, p_buf, &p_tmp );
158 MGINF.i_vts_inf_start_sector = ReadDouble( p_ifo, p_buf, &p_tmp );
159 MGINF.i_text_data_start_sector = ReadDouble( p_ifo, p_buf, &p_tmp );
160 MGINF.i_cell_inf_start_sector = ReadDouble( p_ifo, p_buf, &p_tmp );
161 MGINF.i_vobu_map_start_sector = ReadDouble( p_ifo, p_buf, &p_tmp );
162 DumpBytes( p_ifo, p_buf, &p_tmp, 32 );
163 DumpBytes( p_ifo, p_buf, &p_tmp, 2 );
164 DumpBytes( p_ifo, p_buf, &p_tmp, 1 );
165 MGINF.i_audio_nb = ReadByte( p_ifo, p_buf, &p_tmp );
166 //fprintf( stderr, "vmgi audio nb : %d\n", MGINF.i_audio_nb );
168 for( i = 0 ; i < 8 ; i++ )
170 i_temp = ReadQuad( p_ifo, p_buf, &p_tmp );
173 DumpBytes( p_ifo, p_buf, &p_tmp, 17 );
174 MGINF.i_spu_nb = ReadByte( p_ifo, p_buf, &p_tmp );
175 //fprintf( stderr, "vmgi subpic nb : %d\n", MGINF.i_spu_nb );
177 for( i = 0 ; i < MGINF.i_spu_nb ; i++ )
179 ReadBytes( p_ifo, p_buf, &p_tmp, (u8*)(&i_temp), 6 );
180 /* FIXME : take care of endianness */
184 * read first play title.
186 //fprintf(stderr,"readtitle %i\n", MGINF.i_first_play_title_start_byte & 0x7ff );
187 if( ReadTitle( p_ifo, &p_ifo->vmg.title, p_ifo->i_start
188 + OFF2LB( MGINF.i_first_play_title_start_byte ),
189 MGINF.i_first_play_title_start_byte & 0x7ff ) < 0 )
195 * fills the title information structure.
197 #define TITINF p_ifo->vmg.title_inf
198 if( MGINF.i_title_inf_start_sector )
200 p_tmp = FillBuffer( p_ifo, p_buf,
201 p_ifo->i_start + MGINF.i_title_inf_start_sector );
202 //fprintf( stderr, "title inf %d\n", p_ifo->i_pos );
204 TITINF.i_title_nb = ReadWord( p_ifo, p_buf, &p_tmp );
205 //fprintf( stderr, "title_inf: TTU nb %d\n", TITINF.i_title_nb );
206 DumpBytes( p_ifo, p_buf, &p_tmp, 2 );
207 TITINF.i_end_byte = ReadDouble( p_ifo, p_buf, &p_tmp );
209 /* parsing of title attributes */
210 TITINF.p_attr = malloc( TITINF.i_title_nb *sizeof(title_attr_t) );
211 if( TITINF.p_attr == NULL )
213 intf_ErrMsg( "ifo error: out of memory in IfoInit" );
217 for( i = 0 ; i < TITINF.i_title_nb ; i++ )
219 TITINF.p_attr[i].i_play_type = ReadByte( p_ifo, p_buf, &p_tmp );
220 TITINF.p_attr[i].i_angle_nb = ReadByte( p_ifo, p_buf, &p_tmp );
221 TITINF.p_attr[i].i_chapter_nb = ReadWord( p_ifo, p_buf, &p_tmp );
222 TITINF.p_attr[i].i_parental_id = ReadWord( p_ifo, p_buf, &p_tmp );
223 TITINF.p_attr[i].i_title_set_num = ReadByte( p_ifo, p_buf, &p_tmp );
224 TITINF.p_attr[i].i_title_num = ReadByte( p_ifo, p_buf, &p_tmp );
225 TITINF.p_attr[i].i_start_sector = ReadDouble( p_ifo, p_buf, &p_tmp );
226 //fprintf( stderr, "title_inf: %d %d %d\n", TITINF.p_attr[i].i_chapter_nb, TITINF.p_attr[i].i_title_set_num, TITINF.p_attr[i].i_title_num );
231 TITINF.p_attr = NULL;
236 * fills the title unit structure.
238 if( MGINF.i_title_unit_start_sector )
240 if( ReadTitleUnit( p_ifo, &p_ifo->vmg.title_unit, p_ifo->i_start
241 + MGINF.i_title_unit_start_sector ) < 0 )
248 * fills the structure about parental information.
250 #define PARINF p_ifo->vmg.parental_inf
251 if( MGINF.i_parental_inf_start_sector )
253 p_tmp = FillBuffer( p_ifo, p_buf, p_ifo->i_start +
254 MGINF.i_parental_inf_start_sector );
255 i_start = p_ifo->i_pos;
257 //fprintf( stderr, "PTL\n" );
259 PARINF.i_country_nb = ReadWord( p_ifo, p_buf, &p_tmp );
260 PARINF.i_vts_nb = ReadWord( p_ifo, p_buf, &p_tmp );
261 PARINF.i_end_byte = ReadDouble( p_ifo, p_buf, &p_tmp );
263 PARINF.p_parental_desc = malloc( PARINF.i_country_nb
264 * sizeof(parental_desc_t) );
265 if( PARINF.p_parental_desc == NULL )
267 intf_ErrMsg( "ifo error: out of memory in IfoInit" );
271 for( i = 0 ; i < PARINF.i_country_nb ; i++ )
273 ReadBytes( p_ifo, p_buf, &p_tmp,
274 PARINF.p_parental_desc[i].ps_country_code, 2 );
275 DumpBytes( p_ifo, p_buf, &p_tmp, 2 );
276 PARINF.p_parental_desc[i].i_parental_mask_start_byte =
277 ReadWord( p_ifo, p_buf, &p_tmp );
278 DumpBytes( p_ifo, p_buf, &p_tmp, 2 );
281 PARINF.p_parental_mask = malloc( PARINF.i_country_nb
282 * sizeof(parental_mask_t) );
283 if( PARINF.p_parental_mask == NULL )
285 intf_ErrMsg( "ifo erro: out of memory in IfoInit" );
289 for( i = 0 ; i < PARINF.i_country_nb ; i++ )
291 p_tmp = FillBuffer( p_ifo, p_buf, i_start + OFF2LB(
292 PARINF.p_parental_desc[i].i_parental_mask_start_byte ) )
293 + (PARINF.p_parental_desc[i].i_parental_mask_start_byte & 0x7ff);
295 for( j = 0 ; j < 8 ; j++ )
297 PARINF.p_parental_mask[i].ppi_mask[j] =
298 malloc( ( PARINF.i_vts_nb + 1 ) * sizeof(u16) );
300 if( PARINF.p_parental_mask[i].ppi_mask[j] == NULL )
302 intf_ErrMsg( "ifo error: out of memory in IfoInit" );
306 for( k = 0 ; k < PARINF.i_vts_nb + 1 ; k++ )
308 PARINF.p_parental_mask[i].ppi_mask[j][k] =
309 ReadWord( p_ifo, p_buf, &p_tmp );
317 * information and attributes about for each vts.
319 #define VTSINF p_ifo->vmg.vts_inf
320 if( MGINF.i_vts_inf_start_sector )
324 p_tmp = FillBuffer( p_ifo, p_buf, p_ifo->i_start +
325 MGINF.i_vts_inf_start_sector );
326 i_start = p_ifo->i_pos;
328 //fprintf( stderr, "VTS ATTR\n" );
330 VTSINF.i_vts_nb = ReadWord( p_ifo, p_buf, &p_tmp );;
331 //fprintf( stderr, "VTS ATTR Nb: %d\n", VTSINF.i_vts_nb );
332 DumpBytes( p_ifo, p_buf, &p_tmp, 2 );
333 VTSINF.i_end_byte = ReadDouble( p_ifo, p_buf, &p_tmp );
334 VTSINF.pi_vts_attr_start_byte =
335 malloc( VTSINF.i_vts_nb * sizeof(u32) );
336 if( VTSINF.pi_vts_attr_start_byte == NULL )
338 intf_ErrMsg( "ifo error: out of memory in IfoInit" );
342 for( i = 0 ; i < VTSINF.i_vts_nb ; i++ )
344 VTSINF.pi_vts_attr_start_byte[i] =
345 ReadDouble( p_ifo, p_buf, &p_tmp );
348 VTSINF.p_vts_attr = malloc( VTSINF.i_vts_nb * sizeof(vts_attr_t) );
349 if( VTSINF.p_vts_attr == NULL )
351 intf_ErrMsg( "ifo erro: out of memory in IfoInit" );
355 for( i = 0 ; i < VTSINF.i_vts_nb ; i++ )
357 p_tmp = FillBuffer( p_ifo, p_buf, i_start +
358 OFF2LB( VTSINF.pi_vts_attr_start_byte[i] ) )
359 + ( VTSINF.pi_vts_attr_start_byte[i] & 0x7ff );
361 VTSINF.p_vts_attr[i].i_end_byte =
362 ReadDouble( p_ifo, p_buf, &p_tmp );
363 VTSINF.p_vts_attr[i].i_cat_app_type =
364 ReadDouble( p_ifo, p_buf, &p_tmp );
365 DumpBytes( p_ifo, p_buf, &p_tmp, 2 );
366 DumpBytes( p_ifo, p_buf, &p_tmp, 1 );
367 VTSINF.p_vts_attr[i].i_vts_menu_audio_nb =
368 ReadByte( p_ifo, p_buf, &p_tmp );
369 //fprintf( stderr, "m audio nb : %d\n", VTSINF.p_vts_attr[i].i_vts_menu_audio_nb );
371 for( j = 0 ; j < 8 ; j++ )
373 i_temp = ReadQuad( p_ifo, p_buf, &p_tmp );
376 DumpBytes( p_ifo, p_buf, &p_tmp, 17 );
377 VTSINF.p_vts_attr[i].i_vts_menu_spu_nb =
378 ReadByte( p_ifo, p_buf, &p_tmp );
379 //fprintf( stderr, "m subp nb : %d\n", VTSINF.p_vts_attr[i].i_vts_menu_spu_nb );
381 for( j = 0 ; j < 28 ; j++ )
383 /* FIXME : Fix endianness issue here */
384 ReadBytes( p_ifo, p_buf, &p_tmp, (u8*)(&i_temp), 6 );
387 DumpBytes( p_ifo, p_buf, &p_tmp, 2 );
388 DumpBytes( p_ifo, p_buf, &p_tmp, 2 );
389 DumpBytes( p_ifo, p_buf, &p_tmp, 1 );
390 VTSINF.p_vts_attr[i].i_vts_title_audio_nb =
391 ReadDouble( p_ifo, p_buf, &p_tmp );
392 //fprintf( stderr, "tt audio nb : %d\n", VTSINF.p_vts_attr[i].i_vts_title_audio_nb );
394 for( j = 0 ; j < 8 ; j++ )
396 i_temp = ReadQuad( p_ifo, p_buf, &p_tmp );;
399 DumpBytes( p_ifo, p_buf, &p_tmp, 17 );
400 VTSINF.p_vts_attr[i].i_vts_title_spu_nb =
401 ReadByte( p_ifo, p_buf, &p_tmp );
402 //fprintf( stderr, "tt subp nb : %d\n", VTSINF.p_vts_attr[i].i_vts_title_spu_nb );
404 for( j = 0 ; j < 28 /*VTSINF.p_vts_vts_inf[i].i_vtstt_subpic_nb*/ ; j++ )
406 /* FIXME : Fix endianness issue here */
407 ReadBytes( p_ifo, p_buf, &p_tmp, (u8*)(&i_temp), 6 );
416 if( MGINF.i_cell_inf_start_sector )
418 if( ReadCellInf( p_ifo, &p_ifo->vmg.cell_inf, p_ifo->i_start +
419 MGINF.i_cell_inf_start_sector ) < 0 )
426 * global vob unit map.
428 if( MGINF.i_vobu_map_start_sector )
430 if( ReadVobuMap( p_ifo, &p_ifo->vmg.vobu_map, p_ifo->i_start +
431 MGINF.i_vobu_map_start_sector ) < 0 )
438 p_ifo->vts.b_initialized = 0;
440 intf_WarnMsg( 2, "ifo info: vmg initialized" );
445 /*****************************************************************************
446 * IfoTitleSet: Parse vts*.ifo files to fill the Video Title Set structure.
447 *****************************************************************************/
448 int IfoTitleSet( ifo_t * p_ifo )
450 u8 p_buf[DVD_LB_SIZE];
458 if( p_ifo->vts.b_initialized )
460 FreeTitleSet( &p_ifo->vts );
463 i_off = p_ifo->vmg.title_inf.p_attr[p_ifo->i_title-1].i_start_sector
466 //fprintf(stderr, "offset: %d\n" , i_off );
468 p_tmp = FillBuffer( p_ifo, p_buf, i_off );
469 //i_start = p_ifo->i_pos;
470 p_ifo->vts.i_pos = p_ifo->i_pos;
472 #define MGINF p_ifo->vts.manager_inf
475 * read manager information
477 //fprintf( stderr, "VTSI\n" );
479 ReadBytes( p_ifo, p_buf, &p_tmp, MGINF.psz_id , 12 );
480 MGINF.psz_id[12] = '\0';
481 MGINF.i_end_sector = ReadDouble( p_ifo, p_buf, &p_tmp );
482 DumpBytes( p_ifo, p_buf, &p_tmp, 12 );
483 MGINF.i_inf_end_sector = ReadDouble( p_ifo, p_buf, &p_tmp );
484 DumpBytes( p_ifo, p_buf, &p_tmp, 1 );
485 MGINF.i_spec_ver = ReadByte( p_ifo, p_buf, &p_tmp );
486 MGINF.i_cat = ReadDouble( p_ifo, p_buf, &p_tmp );
487 DumpBytes( p_ifo, p_buf, &p_tmp, 90 );
488 MGINF.i_inf_end_byte = ReadDouble( p_ifo, p_buf, &p_tmp );
489 DumpBytes( p_ifo, p_buf, &p_tmp, 60 );
490 MGINF.i_menu_vob_start_sector = ReadDouble( p_ifo, p_buf, &p_tmp );
491 MGINF.i_title_vob_start_sector = ReadDouble( p_ifo, p_buf, &p_tmp );
492 MGINF.i_title_inf_start_sector = ReadDouble( p_ifo, p_buf, &p_tmp );
493 MGINF.i_title_unit_start_sector = ReadDouble( p_ifo, p_buf, &p_tmp );
494 MGINF.i_menu_unit_start_sector = ReadDouble( p_ifo, p_buf, &p_tmp );
495 MGINF.i_time_inf_start_sector = ReadDouble( p_ifo, p_buf, &p_tmp );
496 MGINF.i_menu_cell_inf_start_sector = ReadDouble( p_ifo, p_buf, &p_tmp );
497 MGINF.i_menu_vobu_map_start_sector = ReadDouble( p_ifo, p_buf, &p_tmp );
498 MGINF.i_cell_inf_start_sector = ReadDouble( p_ifo, p_buf, &p_tmp );
499 MGINF.i_vobu_map_start_sector = ReadDouble( p_ifo, p_buf, &p_tmp );
500 DumpBytes( p_ifo, p_buf, &p_tmp, 24 );
501 DumpBytes( p_ifo, p_buf, &p_tmp, 2 );
502 DumpBytes( p_ifo, p_buf, &p_tmp, 1 );
503 MGINF.i_menu_audio_nb = ReadByte( p_ifo, p_buf, &p_tmp );
505 for( i = 0 ; i < 8 ; i++ )
507 i_temp = ReadQuad( p_ifo, p_buf, &p_tmp );
510 DumpBytes( p_ifo, p_buf, &p_tmp, 17 );
511 MGINF.i_menu_spu_nb = ReadByte( p_ifo, p_buf, &p_tmp );
513 for( i = 0 ; i < 28 ; i++ )
515 /* FIXME : take care of endianness */
516 ReadBytes( p_ifo, p_buf, &p_tmp, (u8*)(&i_temp), 6 );
519 DumpBytes( p_ifo, p_buf, &p_tmp, 2 );
521 i_short = ReadWord( p_ifo, p_buf, &p_tmp );
523 MGINF.video_attr.i_mode = i_short & 0x1;
525 MGINF.video_attr.i_letterboxed = i_short & 0x1;
527 MGINF.video_attr.i_source_res = i_short & 0x3;
529 MGINF.video_attr.i_line21_2 = i_short & 0x1;
531 MGINF.video_attr.i_line21_1 = i_short & 0x1;
533 MGINF.video_attr.i_perm_displ = i_short & 0x3;
535 MGINF.video_attr.i_ratio = i_short & 0x3;
537 MGINF.video_attr.i_system = i_short & 0x3;
539 MGINF.video_attr.i_compression = i_short & 0x3;
541 DumpBytes( p_ifo, p_buf, &p_tmp, 1 );
542 MGINF.i_audio_nb = ReadByte( p_ifo, p_buf, &p_tmp );
543 //fprintf( stderr, "vtsi audio nb : %d\n", MGINF.i_audio_nb );
545 for( i = 0 ; i < 8 ; i++ )
547 i_temp = ReadQuad( p_ifo, p_buf, &p_tmp );
548 //fprintf( stderr, "Audio %d: %llx\n", i, i_temp );
550 MGINF.p_audio_attr[i].i_bar = i_temp & 0xff;
552 MGINF.p_audio_attr[i].i_caption = i_temp & 0xff;
554 MGINF.p_audio_attr[i].i_foo = i_temp & 0xff;
556 MGINF.p_audio_attr[i].i_lang_code = i_temp & 0xffff;
558 MGINF.p_audio_attr[i].i_num_channels = i_temp & 0x7;
560 MGINF.p_audio_attr[i].i_test = i_temp & 0x1;
562 MGINF.p_audio_attr[i].i_sample_freq = i_temp & 0x3;
564 MGINF.p_audio_attr[i].i_quantization = i_temp & 0x3;
566 MGINF.p_audio_attr[i].i_appl_mode = i_temp & 0x3;
568 MGINF.p_audio_attr[i].i_type = i_temp & 0x3;
570 MGINF.p_audio_attr[i].i_multichannel_extension = i_temp & 0x1;
572 MGINF.p_audio_attr[i].i_coding_mode = i_temp & 0x7;
575 DumpBytes( p_ifo, p_buf, &p_tmp, 17 );
576 MGINF.i_spu_nb = ReadByte( p_ifo, p_buf, &p_tmp );
577 //fprintf( stderr, "vtsi subpic nb : %d\n", MGINF.i_spu_nb );
579 for( i=0 ; i<MGINF.i_spu_nb ; i++ )
581 ReadBytes( p_ifo, p_buf, &p_tmp, (u8*)(&i_temp), 6 );
582 i_temp = hton64( i_temp ) >> 16;
583 //fprintf( stderr, "Subpic %d: %llx\n", i, i_temp );
584 MGINF.p_spu_attr[i].i_caption = i_temp & 0xff;
586 MGINF.p_spu_attr[i].i_foo = i_temp & 0xff;
588 MGINF.p_spu_attr[i].i_lang_code = i_temp & 0xffff;
590 MGINF.p_spu_attr[i].i_prefix = i_temp & 0xffff;
594 * read title information: set of pointers to title
596 #define TITINF p_ifo->vts.title_inf
597 if( MGINF.i_title_inf_start_sector )
599 p_tmp = FillBuffer( p_ifo, p_buf, p_ifo->vts.i_pos +
600 MGINF.i_title_inf_start_sector );
602 i_start = p_ifo->i_pos;
604 //fprintf( stderr, "VTS PTR\n" );
606 TITINF.i_title_nb = ReadWord( p_ifo, p_buf, &p_tmp );
607 //fprintf( stderr, "VTS title_inf nb: %d\n", TITINF.i_title_nb );
608 DumpBytes( p_ifo, p_buf, &p_tmp, 2 );
609 TITINF.i_end_byte = ReadDouble( p_ifo, p_buf, &p_tmp );
611 TITINF.pi_start_byte = malloc( TITINF.i_title_nb * sizeof(u32) );
612 if( TITINF.pi_start_byte == NULL )
614 intf_ErrMsg( "ifo error: out of memory in IfoTitleSet" );
618 for( i = 0 ; i < TITINF.i_title_nb ; i++ )
620 TITINF.pi_start_byte[i] = ReadDouble( p_ifo, p_buf, &p_tmp );
624 TITINF.p_title_start = malloc( TITINF.i_title_nb
625 * sizeof(title_start_t) );
626 if( TITINF.p_title_start == NULL )
628 intf_ErrMsg( "ifo error: out of memory in IfoTitleSet" );
632 for( i = 0 ; i < TITINF.i_title_nb ; i++ )
634 p_tmp = FillBuffer( p_ifo, p_buf, i_start +
635 OFF2LB( TITINF.pi_start_byte[i] ) )
636 + (TITINF.pi_start_byte[i] & 0x7ff);
638 TITINF.p_title_start[i].i_title_id =
639 ReadWord( p_ifo, p_buf, &p_tmp );
640 TITINF.p_title_start[i].i_chapter =
641 ReadWord( p_ifo, p_buf, &p_tmp );
647 * menu unit information
649 if( MGINF.i_menu_unit_start_sector )
651 if( ReadTitleUnit( p_ifo, &p_ifo->vts.menu_unit, p_ifo->vts.i_pos +
652 MGINF.i_menu_unit_start_sector ) < 0 )
659 * title unit information
661 if( MGINF.i_title_unit_start_sector )
663 if( ReadUnitInf( p_ifo, &p_ifo->vts.title_unit, p_ifo->vts.i_pos +
664 MGINF.i_title_unit_start_sector, 0 ) < 0 )
671 * time map information
673 #define TIMINF p_ifo->vts.time_inf
674 if( MGINF.i_time_inf_start_sector )
676 u8 p_buf[DVD_LB_SIZE];
678 p_tmp = FillBuffer( p_ifo, p_buf, p_ifo->vts.i_pos +
679 MGINF.i_time_inf_start_sector );
681 //fprintf( stderr, "TMAP\n" );
683 TIMINF.i_nb = ReadWord( p_ifo, p_buf, &p_tmp );;
684 DumpBytes( p_ifo, p_buf, &p_tmp, 2 );
685 TIMINF.i_end_byte = ReadDouble( p_ifo, p_buf, &p_tmp );
687 TIMINF.pi_start_byte = malloc( TIMINF.i_nb * sizeof(u32) );
688 if( TIMINF.pi_start_byte == NULL )
690 intf_ErrMsg( "ifo error: out of memory in IfoTitleSet" );
694 for( i = 0 ; i < TIMINF.i_nb ; i++ )
696 TIMINF.pi_start_byte[i] = ReadDouble( p_ifo, p_buf, &p_tmp );
699 TIMINF.p_time_map = malloc( TIMINF.i_nb * sizeof(time_map_t) );
700 if( TIMINF.p_time_map == NULL )
702 intf_ErrMsg( "ifo error: out of memory in IfoTitleSet" );
706 for( i = 0 ; i < TIMINF.i_nb ; i++ )
708 TIMINF.p_time_map[i].i_time_unit = ReadByte( p_ifo, p_buf, &p_tmp );
709 DumpBytes( p_ifo, p_buf, &p_tmp, 1 );
710 TIMINF.p_time_map[i].i_entry_nb = ReadWord( p_ifo, p_buf, &p_tmp );
712 TIMINF.p_time_map[i].pi_sector =
713 malloc( TIMINF.p_time_map[i].i_entry_nb * sizeof(u32) );
714 if( TIMINF.p_time_map[i].pi_sector == NULL )
716 intf_ErrMsg( "ifo error: out of memory in IfoTitleSet" );
720 for( j = 0 ; j < TIMINF.p_time_map[i].i_entry_nb ; j++ )
722 TIMINF.p_time_map[i].pi_sector[j] =
723 ReadDouble( p_ifo, p_buf, &p_tmp );
729 if( MGINF.i_menu_cell_inf_start_sector
730 && ReadCellInf( p_ifo, &p_ifo->vts.menu_cell_inf, p_ifo->vts.i_pos +
731 MGINF.i_menu_cell_inf_start_sector ) < 0 )
736 if( MGINF.i_menu_vobu_map_start_sector
737 && ReadVobuMap( p_ifo, &p_ifo->vts.menu_vobu_map, p_ifo->vts.i_pos +
738 MGINF.i_menu_vobu_map_start_sector ) < 0 )
743 if( MGINF.i_cell_inf_start_sector
744 && ReadCellInf( p_ifo, &p_ifo->vts.cell_inf, p_ifo->vts.i_pos +
745 MGINF.i_cell_inf_start_sector ) )
750 if( MGINF.i_vobu_map_start_sector
751 && ReadVobuMap( p_ifo, &p_ifo->vts.vobu_map, p_ifo->vts.i_pos +
752 MGINF.i_vobu_map_start_sector ) )
758 intf_WarnMsg( 2, "ifo info: vts %d initialized",
759 p_ifo->vmg.title_inf.p_attr[p_ifo->i_title-1].i_title_set_num );
761 p_ifo->vts.b_initialized = 1;
766 /*****************************************************************************
767 * FreeTitleSet : free all structures allocated by IfoTitleSet
768 *****************************************************************************/
769 static int FreeTitleSet( vts_t * p_vts )
773 if( p_vts->manager_inf.i_vobu_map_start_sector )
775 FreeVobuMap( &p_vts->vobu_map );
778 if( p_vts->manager_inf.i_cell_inf_start_sector )
780 FreeCellInf( &p_vts->cell_inf );
783 if( p_vts->manager_inf.i_menu_vobu_map_start_sector )
785 FreeVobuMap( &p_vts->menu_vobu_map );
788 if( p_vts->manager_inf.i_menu_cell_inf_start_sector )
790 FreeCellInf( &p_vts->menu_cell_inf );
793 if( p_vts->manager_inf.i_time_inf_start_sector )
795 for( i = 0 ; i < p_vts->time_inf.i_nb ; i++ )
797 free( p_vts->time_inf.p_time_map[i].pi_sector );
800 free( p_vts->time_inf.p_time_map );
801 free( p_vts->time_inf.pi_start_byte );
804 if( p_vts->manager_inf.i_title_unit_start_sector )
806 FreeUnitInf( &p_vts->title_unit );
809 if( p_vts->manager_inf.i_menu_unit_start_sector )
811 FreeTitleUnit( &p_vts->menu_unit );
814 if( p_vts->manager_inf.i_title_inf_start_sector )
816 free( p_vts->title_inf.pi_start_byte );
817 free( p_vts->title_inf.p_title_start );
820 p_vts->b_initialized = 0;
825 /*****************************************************************************
826 * IfoDestroy : Frees all the memory allocated to ifo structures
827 *****************************************************************************/
828 void IfoDestroy( ifo_t * p_ifo )
832 FreeTitleSet( &p_ifo->vts );
834 if( p_ifo->vmg.manager_inf.i_vobu_map_start_sector )
836 FreeVobuMap( &p_ifo->vmg.vobu_map );
839 if( p_ifo->vmg.manager_inf.i_cell_inf_start_sector )
841 FreeCellInf( &p_ifo->vmg.cell_inf );
844 if( p_ifo->vmg.manager_inf.i_vts_inf_start_sector )
846 free( p_ifo->vmg.vts_inf.p_vts_attr );
847 free( p_ifo->vmg.vts_inf.pi_vts_attr_start_byte );
850 /* free parental information structures */
851 if( p_ifo->vmg.manager_inf.i_parental_inf_start_sector )
853 for( i = 0 ; i < p_ifo->vmg.parental_inf.i_country_nb ; i++ )
855 for( j = 0 ; j < 8 ; j++ )
857 free( p_ifo->vmg.parental_inf.p_parental_mask[i].ppi_mask[j] );
861 free( p_ifo->vmg.parental_inf.p_parental_mask );
862 free( p_ifo->vmg.parental_inf.p_parental_desc );
865 if( p_ifo->vmg.manager_inf.i_title_unit_start_sector )
867 FreeTitleUnit( &p_ifo->vmg.title_unit );
870 if( p_ifo->vmg.manager_inf.i_title_inf_start_sector )
872 free( p_ifo->vmg.title_inf.p_attr );
875 FreeTitle( &p_ifo->vmg.title );
883 * Function common to Video Manager and Video Title set Processing
886 /*****************************************************************************
887 * ReadTitle : Fills the title structure.
888 *****************************************************************************
889 * Titles are logical stream units that correspond to a whole inside the dvd.
890 * Several title can point to the same part of the physical DVD, and give
891 * map to different anglesfor instance.
892 *****************************************************************************/
893 static int ReadTitle( ifo_t * p_ifo, title_t * p_title, int i_block, int i_bytes )
895 u8 p_buf[DVD_LB_SIZE];
902 p_tmp = FillBuffer( p_ifo, p_buf, i_block ) + i_bytes;
904 i_start = p_ifo->i_pos;
906 //fprintf( stderr, "PGC @ %d + %d\n", p_ifo->i_pos, i_bytes );
908 DumpBytes( p_ifo, p_buf, &p_tmp, 2);
909 p_title->i_chapter_nb = ReadByte( p_ifo, p_buf, &p_tmp );
910 p_title->i_cell_nb = ReadByte( p_ifo, p_buf, &p_tmp );
911 //fprintf( stderr, "title: Prg: %d Cell: %d\n",p_title->i_chapter_nb,p_title->i_cell_nb );
912 p_title->i_play_time = ReadDouble( p_ifo, p_buf, &p_tmp );
913 p_title->i_prohibited_user_op = ReadDouble( p_ifo, p_buf, &p_tmp );
915 for( i = 0 ; i < 8 ; i++ )
917 i_audio = ReadWord( p_ifo, p_buf, &p_tmp );
918 p_title->pi_audio_status[i].i_foo = i_audio & 0xff;
920 p_title->pi_audio_status[i].i_position = i_audio & 0x07;
922 p_title->pi_audio_status[i].i_available = i_audio;
925 for( i = 0 ; i < 32 ; i++ )
927 i_spu = ReadDouble( p_ifo, p_buf, &p_tmp );
928 p_title->pi_spu_status[i].i_position_pan = i_spu & 0x1f;
930 p_title->pi_spu_status[i].i_position_letter = i_spu & 0x1f;
932 p_title->pi_spu_status[i].i_position_wide = i_spu & 0x1f;
934 p_title->pi_spu_status[i].i_position_43 = i_spu & 0x1f;
936 p_title->pi_spu_status[i].i_available = i_spu;
939 p_title->i_next_title_num = ReadWord( p_ifo, p_buf, &p_tmp );
940 p_title->i_prev_title_num = ReadWord( p_ifo, p_buf, &p_tmp );
941 p_title->i_go_up_title_num = ReadWord( p_ifo, p_buf, &p_tmp );
942 p_title->i_still_time = ReadByte( p_ifo, p_buf, &p_tmp );
943 p_title->i_play_mode = ReadByte( p_ifo, p_buf, &p_tmp );
945 for( i = 0 ; i < 16 ; i++ )
947 /* FIXME : We have to erase the extra bit */
948 p_title->pi_yuv_color[i] = ReadDouble( p_ifo, p_buf, &p_tmp );
951 p_title->i_command_start_byte = ReadWord( p_ifo, p_buf, &p_tmp );
952 p_title->i_chapter_map_start_byte = ReadWord( p_ifo, p_buf, &p_tmp );
953 p_title->i_cell_play_start_byte = ReadWord( p_ifo, p_buf, &p_tmp );
954 p_title->i_cell_pos_start_byte = ReadWord( p_ifo, p_buf, &p_tmp );
956 /* parsing of command_t */
957 if( p_title->i_command_start_byte )
959 p_tmp = FillBuffer( p_ifo, p_buf, i_start +
960 OFF2LB( p_title->i_command_start_byte + i_bytes ) )
961 + ( (p_title->i_command_start_byte + i_bytes) & 0x7ff );
964 p_title->command.i_pre_command_nb = ReadWord( p_ifo, p_buf, &p_tmp );
965 p_title->command.i_post_command_nb = ReadWord( p_ifo, p_buf, &p_tmp );
966 p_title->command.i_cell_command_nb = ReadWord( p_ifo, p_buf, &p_tmp );
967 DumpBytes( p_ifo, p_buf, &p_tmp, 2 );
969 /* pre-title commands */
970 if( p_title->command.i_pre_command_nb )
972 p_title->command.p_pre_command =
973 malloc( p_title->command.i_pre_command_nb
974 * sizeof(command_desc_t) );
976 if( p_title->command.p_pre_command == NULL )
978 intf_ErrMsg( "ifo error: out of memory in ReadTitle" );
982 for( i = 0 ; i < p_title->command.i_pre_command_nb ; i++ )
984 p_title->command.p_pre_command[i] =
985 ReadQuad( p_ifo, p_buf, &p_tmp );
990 p_title->command.p_pre_command = NULL;
993 /* post-title commands */
994 if( p_title->command.i_post_command_nb )
996 p_title->command.p_post_command =
997 malloc( p_title->command.i_post_command_nb
998 * sizeof(command_desc_t) );
1000 if( p_title->command.p_post_command == NULL )
1002 intf_ErrMsg( "ifo error: out of memory in ReadTitle" );
1006 for( i = 0 ; i < p_title->command.i_post_command_nb ; i++ )
1008 p_title->command.p_post_command[i] =
1009 ReadQuad( p_ifo, p_buf, &p_tmp );
1014 p_title->command.p_post_command = NULL;
1018 if( p_title->command.i_cell_command_nb )
1020 p_title->command.p_cell_command =
1021 malloc( p_title->command.i_cell_command_nb
1022 * sizeof(command_desc_t) );
1024 if( p_title->command.p_cell_command == NULL )
1026 intf_ErrMsg( "ifo error: out of memory in ReadTitle" );
1030 for( i = 0 ; i < p_title->command.i_cell_command_nb ; i++ )
1032 p_title->command.p_cell_command[i] =
1033 ReadQuad( p_ifo, p_buf, &p_tmp );
1038 p_title->command.p_cell_command = NULL;
1042 /* parsing of chapter_map_t: it gives the entry cell for each chapter */
1043 if( p_title->i_chapter_map_start_byte )
1045 p_ifo->i_pos = dvdcss_seek( p_ifo->dvdhandle,
1046 OFF2LB( i_start + p_title->i_chapter_map_start_byte ) );
1048 p_title->chapter_map.pi_start_cell =
1049 malloc( p_title->i_chapter_nb * sizeof(chapter_map_t) );
1051 if( p_title->chapter_map.pi_start_cell == NULL )
1053 intf_ErrMsg( "ifo error: out of memory in Read Title" );
1057 ReadBytes( p_ifo, p_buf, &p_tmp, p_title->chapter_map.pi_start_cell,
1058 p_title->i_chapter_nb );
1062 p_title->chapter_map.pi_start_cell = NULL;
1065 /* parsing of cell_play_t */
1066 if( p_title->i_cell_play_start_byte )
1068 p_tmp = FillBuffer( p_ifo, p_buf, i_start +
1069 OFF2LB( p_title->i_cell_play_start_byte+i_bytes ) )
1070 + ( (p_title->i_cell_play_start_byte+i_bytes) & 0x7ff );
1072 p_title->p_cell_play = malloc( p_title->i_cell_nb
1073 * sizeof(cell_play_t) );
1075 if( p_title->p_cell_play == NULL )
1077 intf_ErrMsg( "ifo error: out of memory in ReadTitle" );
1081 for( i = 0 ; i < p_title->i_cell_nb ; i++ )
1083 #define PLAY p_title->p_cell_play[i]
1084 PLAY.i_category = ReadWord( p_ifo, p_buf, &p_tmp );
1085 PLAY.i_still_time = ReadByte( p_ifo, p_buf, &p_tmp );
1086 PLAY.i_command_nb = ReadByte( p_ifo, p_buf, &p_tmp );
1087 PLAY.i_play_time = ReadDouble( p_ifo, p_buf, &p_tmp );
1088 PLAY.i_start_sector = ReadDouble( p_ifo, p_buf, &p_tmp );
1089 PLAY.i_first_ilvu_vobu_esector = ReadDouble( p_ifo, p_buf, &p_tmp );
1090 PLAY.i_last_vobu_start_sector = ReadDouble( p_ifo, p_buf, &p_tmp );
1091 PLAY.i_end_sector = ReadDouble( p_ifo, p_buf, &p_tmp );
1096 /* Parsing of cell_pos_t */
1097 if( p_title->i_cell_pos_start_byte )
1099 p_tmp = FillBuffer( p_ifo, p_buf, i_start +
1100 OFF2LB( p_title->i_cell_pos_start_byte + i_bytes ) )
1101 + ( (p_title->i_cell_pos_start_byte + i_bytes) & 0x7ff );
1103 p_title->p_cell_pos = malloc( p_title->i_cell_nb
1104 * sizeof(cell_pos_t) );
1106 if( p_title->p_cell_pos == NULL )
1108 intf_ErrMsg( "ifo error: out of memory" );
1112 for( i = 0 ; i < p_title->i_cell_nb ; i++ )
1114 p_title->p_cell_pos[i].i_vob_id = ReadWord( p_ifo, p_buf, &p_tmp );
1115 DumpBytes( p_ifo, p_buf, &p_tmp, 1 );
1116 p_title->p_cell_pos[i].i_cell_id = ReadByte( p_ifo, p_buf, &p_tmp );
1123 /*****************************************************************************
1124 * FreeTitle: frees alla structure allocated by a call to ReadTitle
1125 *****************************************************************************/
1126 static int FreeTitle( title_t * p_title )
1128 if( p_title->i_command_start_byte )
1130 if( p_title->command.i_pre_command_nb )
1132 free( p_title->command.p_pre_command );
1135 if( p_title->command.i_post_command_nb )
1137 free( p_title->command.p_post_command );
1140 if( p_title->command.i_cell_command_nb )
1142 free( p_title->command.p_cell_command );
1145 if( p_title->i_chapter_map_start_byte )
1147 free( p_title->chapter_map.pi_start_cell );
1150 if( p_title->i_cell_play_start_byte )
1152 free( p_title->p_cell_play );
1155 if( p_title->i_cell_pos_start_byte )
1157 free( p_title->p_cell_pos );
1164 /*****************************************************************************
1165 * ReadUnitInf : Fills Menu Language Unit Table/ PGC Info Table
1166 *****************************************************************************/
1167 static int ReadUnitInf( ifo_t * p_ifo, unit_inf_t * p_unit_inf,
1168 int i_block, int i_bytes )
1170 u8 p_buf[DVD_LB_SIZE];
1175 p_tmp = FillBuffer( p_ifo, p_buf, i_block ) + i_bytes;
1177 i_start = p_ifo->i_pos;
1178 //fprintf( stderr, "Unit\n" );
1180 p_unit_inf->i_title_nb = ReadWord( p_ifo, p_buf, &p_tmp );
1181 //fprintf( stderr, "Unit nb: %d\n", p_unit_inf->i_title_nb );
1182 DumpBytes( p_ifo, p_buf, &p_tmp, 2 );
1183 p_unit_inf->i_end_byte = ReadDouble( p_ifo, p_buf, &p_tmp );
1185 p_unit_inf->p_title =
1186 malloc( p_unit_inf->i_title_nb * sizeof(unit_title_t) );
1187 if( p_unit_inf->p_title == NULL )
1189 intf_ErrMsg( "ifo error: out of memory in ReadUnit" );
1193 for( i = 0 ; i < p_unit_inf->i_title_nb ; i++ )
1195 #define TITLE p_unit_inf->p_title[i]
1196 TITLE.i_category_mask = ReadByte( p_ifo, p_buf, &p_tmp );
1197 TITLE.i_category = ReadByte( p_ifo, p_buf, &p_tmp );
1198 //fprintf( stderr, "cat mask %d: %x cat %x\n", i, TITLE.i_category_mask, TITLE.i_category );
1199 TITLE.i_parental_mask = ReadWord( p_ifo, p_buf, &p_tmp );
1200 TITLE.i_title_start_byte = ReadDouble( p_ifo, p_buf, &p_tmp );
1204 for( i = 0 ; i < p_unit_inf->i_title_nb ; i++ )
1206 //fprintf( stderr, "Unit: PGC %d @ %d\n", i, p_ifo->i_pos );
1207 ReadTitle( p_ifo, &p_unit_inf->p_title[i].title, i_start +
1208 OFF2LB( p_unit_inf->p_title[i].i_title_start_byte + i_bytes ),
1209 (p_unit_inf->p_title[i].i_title_start_byte+i_bytes) & 0x7ff );
1215 /*****************************************************************************
1216 * FreeUnitInf : frees a structure allocated by ReadUnit
1217 *****************************************************************************/
1218 static int FreeUnitInf( unit_inf_t * p_unit_inf )
1220 if( p_unit_inf->p_title != NULL )
1222 free( p_unit_inf->p_title );
1229 /*****************************************************************************
1230 * ReadTitleUnit: Fills the Title Unit structure.
1231 *****************************************************************************/
1232 static int ReadTitleUnit( ifo_t * p_ifo, title_unit_t * p_title_unit,
1235 u8 p_buf[DVD_LB_SIZE];
1240 p_tmp = FillBuffer( p_ifo, p_buf, i_block );
1241 i_start = p_ifo->i_pos;
1242 //fprintf( stderr, "Unit Table\n" );
1244 p_title_unit->i_unit_nb = ReadWord( p_ifo, p_buf, &p_tmp );
1245 DumpBytes( p_ifo, p_buf, &p_tmp, 2 );
1246 p_title_unit->i_end_byte = ReadDouble( p_ifo, p_buf, &p_tmp );
1248 //fprintf(stderr, "Unit: nb %d end %d\n", p_title_unit->i_unit_nb, p_title_unit->i_end_byte );
1250 p_title_unit->p_unit = malloc( p_title_unit->i_unit_nb * sizeof(unit_t) );
1251 if( p_title_unit->p_unit == NULL )
1253 intf_ErrMsg( "ifo error: out of memory in ReadTitleUnit" );
1257 for( i = 0 ; i < p_title_unit->i_unit_nb ; i++ )
1259 //ReadBytes( p_ifo, p_buf, &p_tmp, p_title_unit->p_unit[i].ps_lang_code, 2 );
1260 p_title_unit->p_unit[i].i_lang_code = ReadWord( p_ifo, p_buf, &p_tmp );
1261 //fprintf( stderr, "lang %d %x\n", i,p_title_unit->p_unit[i].i_lang_code );
1262 DumpBytes( p_ifo, p_buf, &p_tmp, 1 );
1263 p_title_unit->p_unit[i].i_existence_mask =
1264 ReadByte( p_ifo, p_buf, &p_tmp );
1265 p_title_unit->p_unit[i].i_unit_inf_start_byte =
1266 ReadDouble( p_ifo, p_buf, &p_tmp );
1269 p_title_unit->p_unit_inf =
1270 malloc( p_title_unit->i_unit_nb * sizeof(unit_inf_t) );
1271 if( p_title_unit->p_unit_inf == NULL )
1273 intf_ErrMsg( "ifo error: out of memory in ReadTitleUnit" );
1277 for( i = 0 ; i < p_title_unit->i_unit_nb ; i++ )
1279 ReadUnitInf( p_ifo, &p_title_unit->p_unit_inf[i], i_start +
1280 OFF2LB( p_title_unit->p_unit[i].i_unit_inf_start_byte ),
1281 p_title_unit->p_unit[i].i_unit_inf_start_byte & 0x7ff );
1287 /*****************************************************************************
1288 * FreeTitleUnit: frees a structure allocateed by ReadTitleUnit
1289 *****************************************************************************/
1290 static int FreeTitleUnit( title_unit_t * p_title_unit )
1294 if( p_title_unit->p_unit_inf != NULL )
1296 for( i = 0 ; i < p_title_unit->i_unit_nb ; i++ )
1298 FreeUnitInf( &p_title_unit->p_unit_inf[i] );
1301 free( p_title_unit->p_unit_inf );
1307 /*****************************************************************************
1308 * ReadCellInf : Fills the Cell Information structure.
1309 *****************************************************************************/
1310 static int ReadCellInf( ifo_t * p_ifo, cell_inf_t * p_cell_inf, int i_block )
1312 u8 p_buf[DVD_LB_SIZE];
1317 p_tmp = FillBuffer( p_ifo, p_buf, i_block );
1318 i_start = p_ifo->i_pos;
1319 //fprintf( stderr, "CELL ADD\n" );
1321 p_cell_inf->i_vob_nb = ReadWord( p_ifo, p_buf, &p_tmp );
1322 DumpBytes( p_ifo, p_buf, &p_tmp, 2 );
1323 p_cell_inf->i_end_byte = ReadDouble( p_ifo, p_buf, &p_tmp );
1325 p_cell_inf->i_cell_nb = (p_cell_inf->i_end_byte/* - 7*/) / sizeof(cell_map_t);
1327 //fprintf( stderr, "Cell inf: vob %d end %d cell %d\n", p_cell_inf->i_vob_nb, p_cell_inf->i_end_byte, p_cell_inf->i_cell_nb );
1329 p_cell_inf->p_cell_map =
1330 malloc( p_cell_inf->i_cell_nb *sizeof(cell_map_t) );
1331 if( p_cell_inf->p_cell_map == NULL )
1333 intf_ErrMsg( "ifo error: out of memory in ReadCellInf" );
1337 for( i = 0 ; i < p_cell_inf->i_cell_nb ; i++ )
1339 #define MAP p_cell_inf->p_cell_map[i]
1340 MAP.i_vob_id = ReadWord( p_ifo, p_buf, &p_tmp );
1341 MAP.i_cell_id = ReadByte( p_ifo, p_buf, &p_tmp );
1342 DumpBytes( p_ifo, p_buf, &p_tmp, 1 );
1343 MAP.i_start_sector = ReadDouble( p_ifo, p_buf, &p_tmp );
1344 //fprintf(stderr, "sector[%d] %d (%d)\n", i,ntohl(*(u32*)(p_tmp)), p_ifo->i_pos);
1345 MAP.i_end_sector = ReadDouble( p_ifo, p_buf, &p_tmp );
1352 /*****************************************************************************
1353 * FreeCellInf : frees structures allocated by ReadCellInf
1354 *****************************************************************************/
1355 static int FreeCellInf( cell_inf_t * p_cell_inf )
1357 free( p_cell_inf->p_cell_map );
1362 /*****************************************************************************
1363 * ReadVobuMap : Fills the VOBU Map structure.
1364 *****************************************************************************/
1365 static int ReadVobuMap( ifo_t * p_ifo, vobu_map_t * p_vobu_map, int i_block )
1367 u8 p_buf[DVD_LB_SIZE];
1372 p_tmp = FillBuffer( p_ifo, p_buf, i_block );
1373 i_start = p_ifo->i_pos;
1374 //fprintf( stderr, "VOBU ADMAP\n" );
1376 p_vobu_map->i_end_byte = ReadDouble( p_ifo, p_buf, &p_tmp );
1377 i_max = ( i_start + p_vobu_map->i_end_byte + 1 - p_ifo->i_pos )
1380 p_vobu_map->pi_vobu_start_sector = malloc( i_max * sizeof(u32) );
1381 if( p_vobu_map->pi_vobu_start_sector == NULL )
1383 intf_ErrMsg( "ifo error: out of memory in ReadVobuMap" );
1387 for( i = 0 ; i < i_max ; i++ )
1389 p_vobu_map->pi_vobu_start_sector[i] = ReadDouble( p_ifo, p_buf, &p_tmp );
1395 /*****************************************************************************
1396 * FreeVobuMap: frees structures allocated by ReadVobuMap
1397 *****************************************************************************/
1398 static int FreeVobuMap( vobu_map_t * p_vobu_map )
1400 free( p_vobu_map->pi_vobu_start_sector );
1406 * IFO virtual machine : a set of commands that give the
1407 * interactive behaviour of the dvd
1411 #define OP_VAL_16(i) (ntoh16( com.data.pi_16[i]))
1412 #define OP_VAL_8(i) ((com.data.pi_8[i]))
1414 static char ifo_reg[][80]=
1416 "Menu_Language_Code",
1418 "SubPicture_Stream_#",
1424 "Highlighted_Button_#",
1427 "Karaoke_audio_mixing_mode",
1428 "Parental_mgmt_country_code",
1432 "Audio_language_code_setting",
1433 "Audio_language_extension_code",
1434 "SPU_language_code_setting",
1435 "SPU_language_extension_code",
1436 "?Player_Regional_Code",
1442 static char * IfoMath( char val )
1444 static char math_op[][10] =
1464 return (char *) math_op[val & 0x0f];
1468 char ifo_cmp[][10] =
1480 char ifo_parental[][10] =
1492 char ifo_menu_id[][80] =
1504 char * IfoMenuName( char index )
1506 return ifo_menu_id[index&0x07];
1509 static void IfoRegister( u16 i_data, u8 i_direct)
1513 if( 0/*isalpha( i_data >> 8 & 0xff )*/ )
1515 printf("'%c%c'", i_data>>8&0xff, i_data&0xff);
1519 printf("0x%02x", i_data);
1534 printf("s[%s]", ifo_reg[i_data]);
1547 printf("r[0x%02x]", i_data);
1553 static void IfoAdvanced( u8 *pi_code )
1555 u8 i_cmd = pi_code[0];
1561 printf( " Highlight button %d; ", pi_code[1]>>2 );
1566 printf( " Illegal " );
1571 printf( "ReSuME %d", pi_code[7] );
1573 else if( ( i_cmd & 0x06) == 0x02 )
1575 printf ("Link to %s cell ", ( i_cmd & 0x01 ) ? "prev" : "next");
1579 printf( "advanced (0x%02x) ", i_cmd );
1584 static void IfoJmp( ifo_command_t com )
1589 switch( com.i_sub_cmd )
1595 printf( "VTS 0x%02x", OP_VAL_8(3) );
1598 printf( "This VTS Title 0x%02x", OP_VAL_8(3) );
1601 printf( "This VTS Title 0x%02x Part 0x%04x",
1603 OP_VAL_8(0)<<8|OP_VAL_8(1));
1607 printf ("in SystemSpace ");
1608 switch (OP_VAL_8(3)>>4) {
1610 printf ("to play first PGC");
1613 printf ("to menu \"%s\"", decode_menuname (OP_VAL_8(3)));
1617 printf ("to VTS 0x%02x and TTN 0x%02x", OP_VAL_8(1), OP_VAL_8(2));
1620 printf ("to VMGM PGC number 0x%02x", OP_VAL_8(0)<<8 | OP_VAL_8(1));
1623 printf ("vts 0x%02x lu 0x%02x menu \"%s\"", OP_VAL_8(2), OP_VAL_8(1), decode_menuname (OP_VAL_8(3)));
1626 switch( OP_VAL_8(3)>>6 )
1629 printf( "to play first PGC" );
1632 printf( "to VMG title menu (?)" );
1635 printf( "vts 0x%02x lu 0x%02x menu \"%s\"",
1638 IfoMenuName( OP_VAL_8(3)&0xF ) );
1641 printf( "vmg pgc 0x%04x (?)", ( OP_VAL_8(0)<<8) | OP_VAL_8(1) );
1648 switch(OP_VAL_8(3)>>4) {
1650 printf ("system first pgc");
1653 printf ("system title menu");
1656 printf ("system menu \"%s\"", decode_menuname (OP_VAL_8(3)));
1659 printf ("system vmg pgc %02x ????", OP_VAL_8(0)<<8|OP_VAL_8(1));
1662 printf ("system lu 0x%02x menu \"%s\"", OP_VAL_8(2), decode_menuname (OP_VAL_8(3)));
1665 printf ("system vmg pgc 0x%02x", OP_VAL_8(0)<<8|OP_VAL_8(1));
1669 // OP_VAL_8(2) is number of cell
1670 // it is processed BEFORE switch
1671 // under some conditions, it is ignored
1672 // I don't understand exactly what it means
1673 printf( " ( spec cell 0x%02X ) ", OP_VAL_8(2) );
1675 switch( OP_VAL_8(3)>>6 )
1678 printf( "to FP PGC" );
1681 printf( "to VMG root menu (?)" );
1684 printf( "to VTS menu \"%s\" (?)",
1685 IfoMenuName(OP_VAL_8(3)&0xF) );
1688 printf( "vmg pgc 0x%02x (?)", (OP_VAL_8(0)<<8)|OP_VAL_8(1) );
1696 static void IfoLnk( ifo_command_t com )
1698 u16 i_button=OP_VAL_8(4)>>2;
1702 switch( com.i_sub_cmd )
1705 IfoAdvanced( &OP_VAL_8(4) );
1709 printf( "PGC 0x%02x", OP_VAL_16(2) );
1713 printf( "PTT 0x%02x", OP_VAL_16(2) );
1717 printf( "Program 0x%02x this PGC", OP_VAL_8(5) );
1721 printf( "Cell 0x%02x this PGC", OP_VAL_8(5) );
1729 printf( ", Highlight 0x%02x", OP_VAL_8(4)>>2 );
1734 void IfoSetSystem( ifo_command_t com )
1741 for( i=1; i<=3; i++ )
1743 if( OP_VAL_8(i)&0x80 )
1747 printf ("s[%s] = 0x%02x;", ifo_reg[i], OP_VAL_8(i)&0xf);
1751 printf ("s[%s] = r[0x%02x];", ifo_reg[i], OP_VAL_8(i)&0xf);
1757 if(OP_VAL_8(1]&0x80)
1758 printf ("s[%s] = 0x%02x;", reg_name[1], OP_VAL_8(1]&0xf);
1759 if(OP_VAL_8(2)&0x80)
1760 //DENT: lwhat about 0x7f here ???
1761 printf ("s[%s] = 0x%02x;", reg_name[2], OP_VAL_8(2)&0x7f);
1762 if(OP_VAL_8(3)&0x80)
1763 printf ("s[%s] = 0x%02x;", reg_name[3], OP_VAL_8(3)&0xf);
1765 if(OP_VAL_8(1)&0x80)
1766 printf ("s[%s] = r[0x%02x];", reg_name[1], OP_VAL_8(1)&0xf);
1767 if(OP_VAL_8(2)&0x80)
1768 printf ("s[%s] = r[0x%02x];", reg_name[2], OP_VAL_8(2)&0xf);
1769 if(OP_VAL_8(3)&0x80)
1770 printf ("s[%s] = r[0x%02x];", reg_name[3], OP_VAL_8(3)&0xf);
1778 printf( "s[%s] = 0x%02x", ifo_reg[9], OP_VAL_16(0) );
1782 printf( "s[%s] = r[0x%02x]", ifo_reg[9], OP_VAL_8(1)&0x0f );
1785 printf( "s[%s] = (s[%s]&0x7FFF)|0x%02x",
1786 ifo_reg[10], ifo_reg[10], OP_VAL_16(1)&0x8000);
1791 printf( "r[0x%02x] = 0x%02x", OP_VAL_8(3)&0x0f, OP_VAL_16(0) );
1795 printf ("r[r[0x%02x]] = r[0x%02x]",
1796 OP_VAL_8(3)&0x0f, OP_VAL_8(1)&0x0f);
1800 //actually only bits 00011100 00011100 are set
1803 printf ("s[%s] = 0x%02x", ifo_reg[11], OP_VAL_16(1));
1807 printf ("s[%s] = r[0x%02x]", ifo_reg[11], OP_VAL_8(3)&0x0f );
1812 //s[%s]=(r[%s]&0x3FF) | (0x%02x << 0xA);
1813 //but it is way too ugly
1816 printf( "s[%s] = 0x%02x", ifo_reg[8], OP_VAL_8(2)>>2 );
1820 printf( "s[%s] = r[0x%02x]", ifo_reg[8], OP_VAL_8(3)&0x0f );
1828 static void IfoSet( ifo_command_t com )
1830 IfoRegister( OP_VAL_16(0), 0 );
1831 printf( " %s ", IfoMath( com.i_cmd ) );
1832 IfoRegister( OP_VAL_16(1), com.i_direct );
1835 /*****************************************************************************
1836 * CommandRead : translates the command strings in ifo into command
1838 *****************************************************************************/
1839 void CommandRead( ifo_command_t com )
1841 u8* pi_code = (u8*)(&com);
1843 switch( com.i_type )
1856 printf ("if (r[0x%02x] %s ", OP_VAL_8(1)&0x0f,
1857 ifo_cmp[com.i_cmp]);
1858 IfoRegister (OP_VAL_16(1), com.i_dir_cmp);
1863 switch( com.i_sub_cmd )
1866 printf( "goto Line 0x%02x", OP_VAL_16(2) );
1870 printf( "stop VM" );
1874 printf( "Set Parental Level To %s and goto Line 0x%02x",
1875 ifo_parental[OP_VAL_8(4)&0x7],
1880 printf( "Illegal" );
1899 printf( "if (r[0x%02x] %s ", OP_VAL_8(4)&0x0f,
1900 ifo_cmp[com.i_cmp] );
1901 IfoRegister( OP_VAL_8(5), 0 );
1912 printf( "if (r[0x%02x] %s ", OP_VAL_8(1)&0x0f,
1913 ifo_cmp[com.i_cmp] );
1914 IfoRegister( OP_VAL_16(1), com.i_dir_cmp );
1928 IfoSetSystem( com );
1930 else if( com.i_cmp && !com.i_sub_cmd )
1932 printf ("if (r[0x%02x] %s ", OP_VAL_8(4)&0x0f, ifo_cmp[com.i_cmp]);
1933 IfoRegister( OP_VAL_8(5), 0 );
1935 IfoSetSystem( com );
1937 else if( !com.i_cmp && com.i_sub_cmd )
1940 IfoSetSystem( com );
1956 else if( com.i_cmp && !com.i_sub_cmd )
1958 printf ("if (r[0x%02x] %s ", OP_VAL_8(0)&0x0f, ifo_cmp[com.i_cmp]);
1959 IfoRegister( OP_VAL_16(2), com.i_dir_cmp );
1963 else if( !com.i_cmp && com.i_sub_cmd )
1977 * math command on r[opcode[1]] and
1978 * direct?be2me_16(OP_VAL_8(0)):reg[OP_VAL_8(1)] is executed
1979 * ( unless command is swap; then r[opcode[1]] and r[OP_VAL_8(1)]
1981 * boolean operation cmp on r[opcode[1]] and
1982 * dir_cmp?be2me_16(OP_VAL_8(1)[1]):reg[OP_VAL_8(3)] is executed
1983 * on true result, buttons(c[6], c[7]) is called
1984 * problem is 'what is buttons()'
1987 printf( "r[0x%X] ", pi_code[1] );
1988 printf( " %s ", IfoMath( com.i_cmd ) );
1989 if( com.i_cmd == 2 )
1991 printf( "r[0x%X] ", OP_VAL_8(1) );
1995 IfoRegister( OP_VAL_16(0), com.i_direct );
1999 printf( "if ( r[%d] %s ", pi_code[1], ifo_cmp[com.i_cmp] );
2000 IfoRegister( OP_VAL_8(1), com.i_dir_cmp );
2001 printf( " ) then {" );
2002 IfoAdvanced( &OP_VAL_8(4) );
2007 * opposite to case 4: boolean, math and buttons.
2013 if( !com.i_direct && com.i_dir_cmp )
2015 printf( "0x%X", OP_VAL_16(1) );
2019 IfoRegister( OP_VAL_8(3), 0 );
2020 if( OP_VAL_8(3)&0x80 )
2022 printf( "s[%s]", ifo_reg[OP_VAL_8(3)&0x1F] );
2026 printf( "r[0x%X]", OP_VAL_8(3)&0x1F);
2027 // 0x1F is either not a mistake,
2028 // or Microsoft programmer's mistake!!!
2032 printf( " %s r[0x%X] ", ifo_cmp[com.i_cmp],
2033 com.i_direct ? OP_VAL_8(2) : OP_VAL_8(1) );
2034 printf( " ) then {" );
2035 printf( "r[0x%X] ", pi_code[1] & 0xF );
2036 printf( " %s ", IfoMath( com.i_cmd ) );
2038 if( com.i_cmd == 0x02 ) // swap
2040 printf("r[0x%X] ", OP_VAL_8(0)&0x1F);
2046 printf( "0x%X", OP_VAL_16(0) );
2050 if( OP_VAL_8(0) & 0x80 )
2052 printf("s[%s]", ifo_reg[OP_VAL_8(0) & 0x1F] );
2056 printf("r[0x%X]", OP_VAL_8(0) & 0x1F );
2062 IfoAdvanced( &OP_VAL_8(4) );
2068 printf( "Unknown Command\n" );
2075 /*****************************************************************************
2076 * CommandPrint : print in clear text (I hope so !) what a command does
2077 *****************************************************************************/
2078 void CommandPrint( ifo_t ifo )
2085 /*****************************************************************************
2087 *****************************************************************************/
2088 static u8* FillBuffer( ifo_t* p_ifo, u8* p_buf, int i_pos )
2090 p_ifo->i_pos = dvdcss_seek( p_ifo->dvdhandle, i_pos );
2091 dvdcss_read( p_ifo->dvdhandle, p_buf, 1, DVDCSS_NOFLAGS );
2096 static void ReadBytes( ifo_t* p_ifo, u8* p_buf, u8** pp_tmp,
2097 u8* pi_dest, int i_nb )
2099 if( i_nb > DVD_LB_SIZE )
2101 intf_ErrMsg( "ifo error: excessive ReadBytes call (%i)", i_nb );
2104 if( *pp_tmp + i_nb >= p_buf + DVD_LB_SIZE )
2106 int i_spare = (int)( (p_buf + DVD_LB_SIZE) - *pp_tmp );
2108 /* Copy the bytes remaining in the current buffer */
2109 memcpy( pi_dest, *pp_tmp, i_spare );
2113 /* Load the next buffer */
2114 *pp_tmp = FillBuffer( p_ifo, p_buf, p_ifo->i_pos + 1 );
2117 memcpy( pi_dest, *pp_tmp, i_nb );
2123 static void DumpBytes( ifo_t* p_ifo, u8* p_buf, u8** pp_tmp, int i_nb )
2125 if( i_nb > DVD_LB_SIZE )
2127 intf_ErrMsg( "ifo error: excessive DumpBytes call (%i)", i_nb );
2132 if( *pp_tmp >= p_buf + DVD_LB_SIZE )
2134 /* If we went too far, load the next buffer */
2135 *pp_tmp = FillBuffer( p_ifo, p_buf, p_ifo->i_pos + 1 )
2136 + (int)( (*pp_tmp) - (p_buf - DVD_LB_SIZE) );
2143 if( *pp_tmp >= p_buf + DVD_LB_SIZE ) \
2145 *pp_tmp = FillBuffer( p_ifo, p_buf, p_ifo->i_pos + 1 ); \
2147 i_ret <<= 8; i_ret |= **pp_tmp; (*pp_tmp)++;
2149 static u8 ReadByte( ifo_t * p_ifo, u8* p_buf, u8** pp_tmp )
2156 static u16 ReadWord( ifo_t * p_ifo, u8* p_buf, u8** pp_tmp )
2163 static u32 ReadDouble( ifo_t * p_ifo, u8* p_buf, u8** pp_tmp )
2166 ADDBYTE; ADDBYTE; ADDBYTE; ADDBYTE;
2170 static u64 ReadQuad( ifo_t * p_ifo, u8* p_buf, u8** pp_tmp )
2173 ADDBYTE; ADDBYTE; ADDBYTE; ADDBYTE; ADDBYTE; ADDBYTE; ADDBYTE; ADDBYTE;