1 /*****************************************************************************
2 * dvd_ifo.c: Functions for ifo parsing
3 *****************************************************************************
4 * Copyright (C) 1999-2001 VideoLAN
5 * $Id: dvd_ifo.c,v 1.47 2002/05/20 22:45:03 sam 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 *****************************************************************************/
36 #include <videolan/vlc.h>
40 #elif defined( _MSC_VER ) && defined( _WIN32 )
48 # include "dummy_dvdcss.h"
50 # include <dvdcss/dvdcss.h>
57 /*****************************************************************************
59 *****************************************************************************/
60 void CommandRead ( command_desc_t );
61 static int ReadTitle ( ifo_t * , title_t *, int, int );
62 static int FreeTitle ( title_t * );
63 static int ReadUnitInf ( ifo_t * , unit_inf_t *, int, int );
64 static int FreeUnitInf ( unit_inf_t * );
65 static int ReadTitleUnit ( ifo_t * , title_unit_t *, int );
66 static int FreeTitleUnit ( title_unit_t * );
67 static int ReadVobuMap ( ifo_t * , vobu_map_t *, int );
68 static int FreeVobuMap ( vobu_map_t * );
69 static int ReadCellInf ( ifo_t * , cell_inf_t *, int );
70 static int FreeCellInf ( cell_inf_t * );
71 static int FreeTitleSet ( vts_t * );
73 static u8* FillBuffer ( ifo_t *, u8 *, int );
74 static u8 ReadByte ( ifo_t *, u8 *, u8 ** );
75 static void ReadBytes ( ifo_t *, u8 *, u8 **, u8 *, int );
76 static void DumpBytes ( ifo_t *, u8 *, u8 **, int );
77 static u16 ReadWord ( ifo_t *, u8 *, u8 ** );
78 static u32 ReadDouble ( ifo_t *, u8 *, u8 ** );
79 static u64 ReadQuad ( ifo_t *, u8 *, u8 ** );
85 /*****************************************************************************
86 * IfoCreate : Creates an ifo structure and prepares for parsing directly
88 *****************************************************************************/
89 int IfoCreate( thread_dvd_data_t * p_dvd )
91 p_dvd->p_ifo = malloc( sizeof(ifo_t) );
92 if( p_dvd->p_ifo == NULL )
94 intf_ErrMsg( "ifo error: unable to allocate memory. aborting" );
98 /* if we are here the dvd device has already been opened */
99 p_dvd->p_ifo->dvdhandle = p_dvd->dvdhandle;
104 /*****************************************************************************
105 * IfoInit : Reads information from the management table.
106 *****************************************************************************/
107 int IfoInit( ifo_t * p_ifo )
109 u8 p_buf[DVD_LB_SIZE];
115 /* find the start sector of video information on the dvd */
116 p_ifo->i_start = DVDUDFFindFile( p_ifo->dvdhandle, "/VIDEO_TS/VIDEO_TS.IFO" );
117 if( !p_ifo->i_start ) return -1;
119 p_tmp = FillBuffer( p_ifo, p_buf, p_ifo->i_start );
120 //i_start = p_ifo->i_pos;
123 * read the video manager information table
125 #define MGINF p_ifo->vmg.manager_inf
126 //fprintf( stderr, "VMGI\n" );
128 ReadBytes( p_ifo, p_buf, &p_tmp, MGINF.psz_id, 12 );
129 MGINF.psz_id[12] = '\0';
130 MGINF.i_vmg_end_sector = ReadDouble( p_ifo, p_buf, &p_tmp );
131 DumpBytes( p_ifo, p_buf, &p_tmp, 12 );
132 MGINF.i_vmg_inf_end_sector = ReadDouble( p_ifo, p_buf, &p_tmp );
133 DumpBytes( p_ifo, p_buf, &p_tmp, 1 );
134 MGINF.i_spec_ver = ReadByte( p_ifo, p_buf, &p_tmp );
135 MGINF.i_cat = ReadDouble( p_ifo, p_buf, &p_tmp );
136 MGINF.i_volume_nb = ReadWord( p_ifo, p_buf, &p_tmp );
137 MGINF.i_volume = ReadWord( p_ifo, p_buf, &p_tmp );
138 MGINF.i_disc_side = ReadByte( p_ifo, p_buf, &p_tmp );
139 DumpBytes( p_ifo, p_buf, &p_tmp, 19 );
140 MGINF.i_title_set_nb = ReadWord( p_ifo, p_buf, &p_tmp );
141 ReadBytes( p_ifo, p_buf, &p_tmp, MGINF.ps_provider_id, 32 );
142 MGINF.i_pos_code = ReadQuad( p_ifo, p_buf, &p_tmp );
143 DumpBytes( p_ifo, p_buf, &p_tmp, 24 );
144 MGINF.i_vmg_inf_end_byte = ReadDouble( p_ifo, p_buf, &p_tmp );
145 MGINF.i_first_play_title_start_byte = ReadDouble( p_ifo, p_buf, &p_tmp );
146 DumpBytes( p_ifo, p_buf, &p_tmp, 56 );
147 MGINF.i_vob_start_sector = ReadDouble( p_ifo, p_buf, &p_tmp );
148 MGINF.i_title_inf_start_sector = ReadDouble( p_ifo, p_buf, &p_tmp );
149 MGINF.i_title_unit_start_sector = ReadDouble( p_ifo, p_buf, &p_tmp );
150 MGINF.i_parental_inf_start_sector = ReadDouble( p_ifo, p_buf, &p_tmp );
151 MGINF.i_vts_inf_start_sector = ReadDouble( p_ifo, p_buf, &p_tmp );
152 MGINF.i_text_data_start_sector = ReadDouble( p_ifo, p_buf, &p_tmp );
153 MGINF.i_cell_inf_start_sector = ReadDouble( p_ifo, p_buf, &p_tmp );
154 MGINF.i_vobu_map_start_sector = ReadDouble( p_ifo, p_buf, &p_tmp );
155 DumpBytes( p_ifo, p_buf, &p_tmp, 32 );
156 DumpBytes( p_ifo, p_buf, &p_tmp, 2 );
157 DumpBytes( p_ifo, p_buf, &p_tmp, 1 );
158 MGINF.i_audio_nb = ReadByte( p_ifo, p_buf, &p_tmp );
159 //fprintf( stderr, "vmgi audio nb : %d\n", MGINF.i_audio_nb );
161 for( i = 0 ; i < 8 ; i++ )
163 i_temp = ReadQuad( p_ifo, p_buf, &p_tmp );
166 DumpBytes( p_ifo, p_buf, &p_tmp, 17 );
167 MGINF.i_spu_nb = ReadByte( p_ifo, p_buf, &p_tmp );
168 //fprintf( stderr, "vmgi subpic nb : %d\n", MGINF.i_spu_nb );
170 for( i = 0 ; i < MGINF.i_spu_nb ; i++ )
172 ReadBytes( p_ifo, p_buf, &p_tmp, (u8*)(&i_temp), 6 );
173 /* FIXME : take care of endianness */
177 * read first play title.
179 //fprintf(stderr,"readtitle %i\n", MGINF.i_first_play_title_start_byte & 0x7ff );
180 if( ReadTitle( p_ifo, &p_ifo->vmg.title, p_ifo->i_start
181 + OFF2LB( MGINF.i_first_play_title_start_byte ),
182 MGINF.i_first_play_title_start_byte & 0x7ff ) < 0 )
188 * fills the title information structure.
190 #define TITINF p_ifo->vmg.title_inf
191 if( MGINF.i_title_inf_start_sector )
193 p_tmp = FillBuffer( p_ifo, p_buf,
194 p_ifo->i_start + MGINF.i_title_inf_start_sector );
195 //fprintf( stderr, "title inf %d\n", p_ifo->i_pos );
197 TITINF.i_title_nb = ReadWord( p_ifo, p_buf, &p_tmp );
198 //fprintf( stderr, "title_inf: TTU nb %d\n", TITINF.i_title_nb );
199 DumpBytes( p_ifo, p_buf, &p_tmp, 2 );
200 TITINF.i_last_byte = ReadDouble( p_ifo, p_buf, &p_tmp );
202 /* parsing of title attributes */
203 TITINF.p_attr = malloc( TITINF.i_title_nb *sizeof(title_attr_t) );
204 if( TITINF.p_attr == NULL )
206 intf_ErrMsg( "ifo error: out of memory in IfoInit" );
210 for( i = 0 ; i < TITINF.i_title_nb ; i++ )
212 TITINF.p_attr[i].i_play_type = ReadByte( p_ifo, p_buf, &p_tmp );
213 TITINF.p_attr[i].i_angle_nb = ReadByte( p_ifo, p_buf, &p_tmp );
214 TITINF.p_attr[i].i_chapter_nb = ReadWord( p_ifo, p_buf, &p_tmp );
215 TITINF.p_attr[i].i_parental_id = ReadWord( p_ifo, p_buf, &p_tmp );
216 TITINF.p_attr[i].i_title_set_num = ReadByte( p_ifo, p_buf, &p_tmp );
217 TITINF.p_attr[i].i_title_num = ReadByte( p_ifo, p_buf, &p_tmp );
218 TITINF.p_attr[i].i_start_sector = ReadDouble( p_ifo, p_buf, &p_tmp );
219 //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 );
224 TITINF.p_attr = NULL;
229 * fills the title unit structure.
231 if( MGINF.i_title_unit_start_sector )
233 if( ReadTitleUnit( p_ifo, &p_ifo->vmg.title_unit, p_ifo->i_start
234 + MGINF.i_title_unit_start_sector ) < 0 )
241 * fills the structure about parental information.
243 #define PARINF p_ifo->vmg.parental_inf
244 if( MGINF.i_parental_inf_start_sector )
246 p_tmp = FillBuffer( p_ifo, p_buf, p_ifo->i_start +
247 MGINF.i_parental_inf_start_sector );
248 i_start = p_ifo->i_pos;
250 //fprintf( stderr, "PTL\n" );
252 PARINF.i_country_nb = ReadWord( p_ifo, p_buf, &p_tmp );
253 PARINF.i_vts_nb = ReadWord( p_ifo, p_buf, &p_tmp );
254 PARINF.i_last_byte = ReadDouble( p_ifo, p_buf, &p_tmp );
256 PARINF.p_parental_desc = malloc( PARINF.i_country_nb
257 * sizeof(parental_desc_t) );
258 if( PARINF.p_parental_desc == NULL )
260 intf_ErrMsg( "ifo error: out of memory in IfoInit" );
264 for( i = 0 ; i < PARINF.i_country_nb ; i++ )
266 ReadBytes( p_ifo, p_buf, &p_tmp,
267 PARINF.p_parental_desc[i].ps_country_code, 2 );
268 DumpBytes( p_ifo, p_buf, &p_tmp, 2 );
269 PARINF.p_parental_desc[i].i_parental_mask_start_byte =
270 ReadWord( p_ifo, p_buf, &p_tmp );
271 DumpBytes( p_ifo, p_buf, &p_tmp, 2 );
274 PARINF.p_parental_mask = malloc( PARINF.i_country_nb
275 * sizeof(parental_mask_t) );
276 if( PARINF.p_parental_mask == NULL )
278 intf_ErrMsg( "ifo error: out of memory in IfoInit" );
282 for( i = 0 ; i < PARINF.i_country_nb ; i++ )
284 p_tmp = FillBuffer( p_ifo, p_buf, i_start + OFF2LB(
285 PARINF.p_parental_desc[i].i_parental_mask_start_byte ) )
286 + (PARINF.p_parental_desc[i].i_parental_mask_start_byte & 0x7ff);
288 for( j = 0 ; j < 8 ; j++ )
290 PARINF.p_parental_mask[i].ppi_mask[j] =
291 malloc( ( PARINF.i_vts_nb + 1 ) * sizeof(u16) );
293 if( PARINF.p_parental_mask[i].ppi_mask[j] == NULL )
295 intf_ErrMsg( "ifo error: out of memory in IfoInit" );
299 for( k = 0 ; k < PARINF.i_vts_nb + 1 ; k++ )
301 PARINF.p_parental_mask[i].ppi_mask[j][k] =
302 ReadWord( p_ifo, p_buf, &p_tmp );
310 * information and attributes about for each vts.
312 #define VTSINF p_ifo->vmg.vts_inf
313 if( MGINF.i_vts_inf_start_sector )
317 p_tmp = FillBuffer( p_ifo, p_buf, p_ifo->i_start +
318 MGINF.i_vts_inf_start_sector );
319 i_start = p_ifo->i_pos;
321 //fprintf( stderr, "VTS ATTR\n" );
323 VTSINF.i_vts_nb = ReadWord( p_ifo, p_buf, &p_tmp );;
324 //fprintf( stderr, "VTS ATTR Nb: %d\n", VTSINF.i_vts_nb );
325 DumpBytes( p_ifo, p_buf, &p_tmp, 2 );
326 VTSINF.i_last_byte = ReadDouble( p_ifo, p_buf, &p_tmp );
327 VTSINF.pi_vts_attr_start_byte =
328 malloc( VTSINF.i_vts_nb * sizeof(u32) );
329 if( VTSINF.pi_vts_attr_start_byte == NULL )
331 intf_ErrMsg( "ifo error: out of memory in IfoInit" );
335 for( i = 0 ; i < VTSINF.i_vts_nb ; i++ )
337 VTSINF.pi_vts_attr_start_byte[i] =
338 ReadDouble( p_ifo, p_buf, &p_tmp );
341 VTSINF.p_vts_attr = malloc( VTSINF.i_vts_nb * sizeof(vts_attr_t) );
342 if( VTSINF.p_vts_attr == NULL )
344 intf_ErrMsg( "ifo error: out of memory in IfoInit" );
348 for( i = 0 ; i < VTSINF.i_vts_nb ; i++ )
350 p_tmp = FillBuffer( p_ifo, p_buf, i_start +
351 OFF2LB( VTSINF.pi_vts_attr_start_byte[i] ) )
352 + ( VTSINF.pi_vts_attr_start_byte[i] & 0x7ff );
354 VTSINF.p_vts_attr[i].i_last_byte =
355 ReadDouble( p_ifo, p_buf, &p_tmp );
356 VTSINF.p_vts_attr[i].i_cat_app_type =
357 ReadDouble( p_ifo, p_buf, &p_tmp );
358 DumpBytes( p_ifo, p_buf, &p_tmp, 2 );
359 DumpBytes( p_ifo, p_buf, &p_tmp, 1 );
360 VTSINF.p_vts_attr[i].i_vts_menu_audio_nb =
361 ReadByte( p_ifo, p_buf, &p_tmp );
362 //fprintf( stderr, "m audio nb : %d\n", VTSINF.p_vts_attr[i].i_vts_menu_audio_nb );
364 for( j = 0 ; j < 8 ; j++ )
366 i_temp = ReadQuad( p_ifo, p_buf, &p_tmp );
369 DumpBytes( p_ifo, p_buf, &p_tmp, 17 );
370 VTSINF.p_vts_attr[i].i_vts_menu_spu_nb =
371 ReadByte( p_ifo, p_buf, &p_tmp );
372 //fprintf( stderr, "m subp nb : %d\n", VTSINF.p_vts_attr[i].i_vts_menu_spu_nb );
374 for( j = 0 ; j < 28 ; j++ )
376 /* FIXME : Fix endianness issue here */
377 ReadBytes( p_ifo, p_buf, &p_tmp, (u8*)(&i_temp), 6 );
380 DumpBytes( p_ifo, p_buf, &p_tmp, 2 );
381 DumpBytes( p_ifo, p_buf, &p_tmp, 2 );
382 DumpBytes( p_ifo, p_buf, &p_tmp, 1 );
383 VTSINF.p_vts_attr[i].i_vts_title_audio_nb =
384 ReadDouble( p_ifo, p_buf, &p_tmp );
385 //fprintf( stderr, "tt audio nb : %d\n", VTSINF.p_vts_attr[i].i_vts_title_audio_nb );
387 for( j = 0 ; j < 8 ; j++ )
389 i_temp = ReadQuad( p_ifo, p_buf, &p_tmp );;
392 DumpBytes( p_ifo, p_buf, &p_tmp, 17 );
393 VTSINF.p_vts_attr[i].i_vts_title_spu_nb =
394 ReadByte( p_ifo, p_buf, &p_tmp );
395 //fprintf( stderr, "tt subp nb : %d\n", VTSINF.p_vts_attr[i].i_vts_title_spu_nb );
397 for( j = 0 ; j < 28 /*VTSINF.p_vts_vts_inf[i].i_vtstt_subpic_nb*/ ; j++ )
399 /* FIXME : Fix endianness issue here */
400 ReadBytes( p_ifo, p_buf, &p_tmp, (u8*)(&i_temp), 6 );
409 if( MGINF.i_cell_inf_start_sector )
411 if( ReadCellInf( p_ifo, &p_ifo->vmg.cell_inf, p_ifo->i_start +
412 MGINF.i_cell_inf_start_sector ) < 0 )
419 * global vob unit map.
421 if( MGINF.i_vobu_map_start_sector )
423 if( ReadVobuMap( p_ifo, &p_ifo->vmg.vobu_map, p_ifo->i_start +
424 MGINF.i_vobu_map_start_sector ) < 0 )
431 p_ifo->vts.b_initialized = 0;
433 intf_WarnMsg( 2, "ifo info: vmg initialized" );
438 /*****************************************************************************
439 * IfoTitleSet: Parse vts*.ifo files to fill the Video Title Set structure.
440 *****************************************************************************/
441 int IfoTitleSet( ifo_t * p_ifo, int i_title )
443 u8 p_buf[DVD_LB_SIZE];
451 if( p_ifo->vts.b_initialized )
453 FreeTitleSet( &p_ifo->vts );
456 i_off = p_ifo->vmg.title_inf.p_attr[i_title-1].i_start_sector
459 //fprintf(stderr, "offset: %d\n" , i_off );
461 p_tmp = FillBuffer( p_ifo, p_buf, i_off );
462 //i_start = p_ifo->i_pos;
463 p_ifo->vts.i_pos = p_ifo->i_pos;
465 #define MGINF p_ifo->vts.manager_inf
468 * read manager information
470 //fprintf( stderr, "VTSI\n" );
472 ReadBytes( p_ifo, p_buf, &p_tmp, MGINF.psz_id , 12 );
473 MGINF.psz_id[12] = '\0';
474 MGINF.i_last_sector = ReadDouble( p_ifo, p_buf, &p_tmp );
475 DumpBytes( p_ifo, p_buf, &p_tmp, 12 );
476 MGINF.i_inf_last_sector = ReadDouble( p_ifo, p_buf, &p_tmp );
477 DumpBytes( p_ifo, p_buf, &p_tmp, 1 );
478 MGINF.i_spec_ver = ReadByte( p_ifo, p_buf, &p_tmp );
479 MGINF.i_cat = ReadDouble( p_ifo, p_buf, &p_tmp );
480 DumpBytes( p_ifo, p_buf, &p_tmp, 90 );
481 MGINF.i_inf_end_byte = ReadDouble( p_ifo, p_buf, &p_tmp );
482 DumpBytes( p_ifo, p_buf, &p_tmp, 60 );
483 MGINF.i_menu_vob_start_sector = ReadDouble( p_ifo, p_buf, &p_tmp );
484 MGINF.i_title_vob_start_sector = ReadDouble( p_ifo, p_buf, &p_tmp );
485 MGINF.i_title_inf_start_sector = ReadDouble( p_ifo, p_buf, &p_tmp );
486 MGINF.i_title_unit_start_sector = ReadDouble( p_ifo, p_buf, &p_tmp );
487 MGINF.i_menu_unit_start_sector = ReadDouble( p_ifo, p_buf, &p_tmp );
488 MGINF.i_time_inf_start_sector = ReadDouble( p_ifo, p_buf, &p_tmp );
489 MGINF.i_menu_cell_inf_start_sector = ReadDouble( p_ifo, p_buf, &p_tmp );
490 MGINF.i_menu_vobu_map_start_sector = ReadDouble( p_ifo, p_buf, &p_tmp );
491 MGINF.i_cell_inf_start_sector = ReadDouble( p_ifo, p_buf, &p_tmp );
492 MGINF.i_vobu_map_start_sector = ReadDouble( p_ifo, p_buf, &p_tmp );
493 DumpBytes( p_ifo, p_buf, &p_tmp, 24 );
494 DumpBytes( p_ifo, p_buf, &p_tmp, 2 );
495 DumpBytes( p_ifo, p_buf, &p_tmp, 1 );
496 MGINF.i_menu_audio_nb = ReadByte( p_ifo, p_buf, &p_tmp );
498 for( i = 0 ; i < 8 ; i++ )
500 i_temp = ReadQuad( p_ifo, p_buf, &p_tmp );
503 DumpBytes( p_ifo, p_buf, &p_tmp, 17 );
504 MGINF.i_menu_spu_nb = ReadByte( p_ifo, p_buf, &p_tmp );
506 for( i = 0 ; i < 28 ; i++ )
508 /* FIXME : take care of endianness */
509 ReadBytes( p_ifo, p_buf, &p_tmp, (u8*)(&i_temp), 6 );
512 DumpBytes( p_ifo, p_buf, &p_tmp, 2 );
514 i_short = ReadWord( p_ifo, p_buf, &p_tmp );
516 MGINF.video_attr.i_mode = i_short & 0x1;
518 MGINF.video_attr.i_letterboxed = i_short & 0x1;
520 MGINF.video_attr.i_source_res = i_short & 0x3;
522 MGINF.video_attr.i_line21_2 = i_short & 0x1;
524 MGINF.video_attr.i_line21_1 = i_short & 0x1;
526 MGINF.video_attr.i_perm_displ = i_short & 0x3;
528 MGINF.video_attr.i_ratio = i_short & 0x3;
530 MGINF.video_attr.i_system = i_short & 0x3;
532 MGINF.video_attr.i_compression = i_short & 0x3;
534 DumpBytes( p_ifo, p_buf, &p_tmp, 1 );
535 MGINF.i_audio_nb = ReadByte( p_ifo, p_buf, &p_tmp );
536 //fprintf( stderr, "vtsi audio nb : %d\n", MGINF.i_audio_nb );
538 for( i = 0 ; i < 8 ; i++ )
540 i_temp = ReadQuad( p_ifo, p_buf, &p_tmp );
541 //fprintf( stderr, "Audio %d: %llx\n", i, i_temp );
543 MGINF.p_audio_attr[i].i_bar = i_temp & 0xff;
545 MGINF.p_audio_attr[i].i_caption = i_temp & 0xff;
547 MGINF.p_audio_attr[i].i_foo = i_temp & 0xff;
549 MGINF.p_audio_attr[i].i_lang_code = i_temp & 0xffff;
551 MGINF.p_audio_attr[i].i_num_channels = i_temp & 0x7;
553 MGINF.p_audio_attr[i].i_test = i_temp & 0x1;
555 MGINF.p_audio_attr[i].i_sample_freq = i_temp & 0x3;
557 MGINF.p_audio_attr[i].i_quantization = i_temp & 0x3;
559 MGINF.p_audio_attr[i].i_appl_mode = i_temp & 0x3;
561 MGINF.p_audio_attr[i].i_type = i_temp & 0x3;
563 MGINF.p_audio_attr[i].i_multichannel_extension = i_temp & 0x1;
565 MGINF.p_audio_attr[i].i_coding_mode = i_temp & 0x7;
568 DumpBytes( p_ifo, p_buf, &p_tmp, 17 );
569 MGINF.i_spu_nb = ReadByte( p_ifo, p_buf, &p_tmp );
570 //fprintf( stderr, "vtsi subpic nb : %d\n", MGINF.i_spu_nb );
572 for( i=0 ; i<MGINF.i_spu_nb ; i++ )
574 ReadBytes( p_ifo, p_buf, &p_tmp, (u8*)(&i_temp), 6 );
575 i_temp = hton64( i_temp ) >> 16;
576 //fprintf( stderr, "Subpic %d: %llx\n", i, i_temp );
577 MGINF.p_spu_attr[i].i_caption = i_temp & 0xff;
579 MGINF.p_spu_attr[i].i_foo = i_temp & 0xff;
581 MGINF.p_spu_attr[i].i_lang_code = i_temp & 0xffff;
583 MGINF.p_spu_attr[i].i_prefix = i_temp & 0xffff;
587 * read title information: set of pointers to title
589 #define TITINF p_ifo->vts.title_inf
590 if( MGINF.i_title_inf_start_sector )
592 p_tmp = FillBuffer( p_ifo, p_buf, p_ifo->vts.i_pos +
593 MGINF.i_title_inf_start_sector );
595 i_start = p_ifo->i_pos;
597 //fprintf( stderr, "VTS PTR\n" );
599 TITINF.i_title_nb = ReadWord( p_ifo, p_buf, &p_tmp );
600 //fprintf( stderr, "VTS title_inf nb: %d\n", TITINF.i_title_nb );
601 DumpBytes( p_ifo, p_buf, &p_tmp, 2 );
602 TITINF.i_last_byte = ReadDouble( p_ifo, p_buf, &p_tmp );
604 TITINF.pi_start_byte = malloc( TITINF.i_title_nb * sizeof(u32) );
605 if( TITINF.pi_start_byte == NULL )
607 intf_ErrMsg( "ifo error: out of memory in IfoTitleSet" );
611 for( i = 0 ; i < TITINF.i_title_nb ; i++ )
613 TITINF.pi_start_byte[i] = ReadDouble( p_ifo, p_buf, &p_tmp );
617 TITINF.p_title_start = malloc( TITINF.i_title_nb
618 * sizeof(title_start_t) );
619 if( TITINF.p_title_start == NULL )
621 intf_ErrMsg( "ifo error: out of memory in IfoTitleSet" );
625 for( i = 0 ; i < TITINF.i_title_nb ; i++ )
627 p_tmp = FillBuffer( p_ifo, p_buf, i_start +
628 OFF2LB( TITINF.pi_start_byte[i] ) )
629 + (TITINF.pi_start_byte[i] & 0x7ff);
631 TITINF.p_title_start[i].i_title_id =
632 ReadWord( p_ifo, p_buf, &p_tmp );
633 TITINF.p_title_start[i].i_chapter =
634 ReadWord( p_ifo, p_buf, &p_tmp );
640 * menu unit information
642 if( MGINF.i_menu_unit_start_sector )
644 if( ReadTitleUnit( p_ifo, &p_ifo->vts.menu_unit, p_ifo->vts.i_pos +
645 MGINF.i_menu_unit_start_sector ) < 0 )
652 * title unit information
654 if( MGINF.i_title_unit_start_sector )
656 if( ReadUnitInf( p_ifo, &p_ifo->vts.title_unit, p_ifo->vts.i_pos +
657 MGINF.i_title_unit_start_sector, 0 ) < 0 )
664 * time map information
666 #define TIMINF p_ifo->vts.time_inf
667 if( MGINF.i_time_inf_start_sector )
669 u8 p_buf[DVD_LB_SIZE];
671 p_tmp = FillBuffer( p_ifo, p_buf, p_ifo->vts.i_pos +
672 MGINF.i_time_inf_start_sector );
674 //fprintf( stderr, "TMAP\n" );
676 TIMINF.i_nb = ReadWord( p_ifo, p_buf, &p_tmp );;
677 DumpBytes( p_ifo, p_buf, &p_tmp, 2 );
678 TIMINF.i_last_byte = ReadDouble( p_ifo, p_buf, &p_tmp );
680 TIMINF.pi_start_byte = malloc( TIMINF.i_nb * sizeof(u32) );
681 if( TIMINF.pi_start_byte == NULL )
683 intf_ErrMsg( "ifo error: out of memory in IfoTitleSet" );
687 for( i = 0 ; i < TIMINF.i_nb ; i++ )
689 TIMINF.pi_start_byte[i] = ReadDouble( p_ifo, p_buf, &p_tmp );
692 TIMINF.p_time_map = malloc( TIMINF.i_nb * sizeof(time_map_t) );
693 if( TIMINF.p_time_map == NULL )
695 intf_ErrMsg( "ifo error: out of memory in IfoTitleSet" );
699 for( i = 0 ; i < TIMINF.i_nb ; i++ )
701 TIMINF.p_time_map[i].i_time_unit = ReadByte( p_ifo, p_buf, &p_tmp );
702 DumpBytes( p_ifo, p_buf, &p_tmp, 1 );
703 TIMINF.p_time_map[i].i_entry_nb = ReadWord( p_ifo, p_buf, &p_tmp );
705 if( TIMINF.p_time_map[i].i_entry_nb )
707 TIMINF.p_time_map[i].pi_sector =
708 malloc( TIMINF.p_time_map[i].i_entry_nb * sizeof(u32) );
709 if( TIMINF.p_time_map[i].pi_sector == NULL )
711 intf_ErrMsg( "ifo error: out of memory in IfoTitleSet" );
715 for( j = 0 ; j < TIMINF.p_time_map[i].i_entry_nb ; j++ )
717 TIMINF.p_time_map[i].pi_sector[j] =
718 ReadDouble( p_ifo, p_buf, &p_tmp );
725 if( MGINF.i_menu_cell_inf_start_sector
726 && ReadCellInf( p_ifo, &p_ifo->vts.menu_cell_inf, p_ifo->vts.i_pos +
727 MGINF.i_menu_cell_inf_start_sector ) < 0 )
732 if( MGINF.i_menu_vobu_map_start_sector
733 && ReadVobuMap( p_ifo, &p_ifo->vts.menu_vobu_map, p_ifo->vts.i_pos +
734 MGINF.i_menu_vobu_map_start_sector ) < 0 )
739 if( MGINF.i_cell_inf_start_sector
740 && ReadCellInf( p_ifo, &p_ifo->vts.cell_inf, p_ifo->vts.i_pos +
741 MGINF.i_cell_inf_start_sector ) )
746 if( MGINF.i_vobu_map_start_sector
747 && ReadVobuMap( p_ifo, &p_ifo->vts.vobu_map, p_ifo->vts.i_pos +
748 MGINF.i_vobu_map_start_sector ) )
754 intf_WarnMsg( 4, "ifo info: vts %d initialized",
755 p_ifo->vmg.title_inf.p_attr[i_title-1].i_title_set_num );
757 p_ifo->vts.b_initialized = 1;
762 /*****************************************************************************
763 * FreeTitleSet : free all structures allocated by IfoTitleSet
764 *****************************************************************************/
765 static int FreeTitleSet( vts_t * p_vts )
769 if( p_vts->manager_inf.i_vobu_map_start_sector )
771 FreeVobuMap( &p_vts->vobu_map );
774 if( p_vts->manager_inf.i_cell_inf_start_sector )
776 FreeCellInf( &p_vts->cell_inf );
779 if( p_vts->manager_inf.i_menu_vobu_map_start_sector )
781 FreeVobuMap( &p_vts->menu_vobu_map );
784 if( p_vts->manager_inf.i_menu_cell_inf_start_sector )
786 FreeCellInf( &p_vts->menu_cell_inf );
789 if( p_vts->manager_inf.i_time_inf_start_sector )
791 for( i = 0 ; i < p_vts->time_inf.i_nb ; i++ )
793 if( p_vts->time_inf.p_time_map[i].i_entry_nb )
795 free( p_vts->time_inf.p_time_map[i].pi_sector );
799 free( p_vts->time_inf.p_time_map );
800 free( p_vts->time_inf.pi_start_byte );
803 if( p_vts->manager_inf.i_title_unit_start_sector )
805 FreeUnitInf( &p_vts->title_unit );
808 if( p_vts->manager_inf.i_menu_unit_start_sector )
810 FreeTitleUnit( &p_vts->menu_unit );
813 if( p_vts->manager_inf.i_title_inf_start_sector )
815 free( p_vts->title_inf.pi_start_byte );
816 free( p_vts->title_inf.p_title_start );
819 p_vts->b_initialized = 0;
824 /*****************************************************************************
825 * IfoDestroy : Frees all the memory allocated to ifo structures
826 *****************************************************************************/
827 void IfoDestroy( ifo_t * p_ifo )
831 FreeTitleSet( &p_ifo->vts );
833 if( p_ifo->vmg.manager_inf.i_vobu_map_start_sector )
835 FreeVobuMap( &p_ifo->vmg.vobu_map );
838 if( p_ifo->vmg.manager_inf.i_cell_inf_start_sector )
840 FreeCellInf( &p_ifo->vmg.cell_inf );
843 if( p_ifo->vmg.manager_inf.i_vts_inf_start_sector )
845 free( p_ifo->vmg.vts_inf.p_vts_attr );
846 free( p_ifo->vmg.vts_inf.pi_vts_attr_start_byte );
849 /* free parental information structures */
850 if( p_ifo->vmg.manager_inf.i_parental_inf_start_sector )
852 for( i = 0 ; i < p_ifo->vmg.parental_inf.i_country_nb ; i++ )
854 for( j = 0 ; j < 8 ; j++ )
856 free( p_ifo->vmg.parental_inf.p_parental_mask[i].ppi_mask[j] );
860 free( p_ifo->vmg.parental_inf.p_parental_mask );
861 free( p_ifo->vmg.parental_inf.p_parental_desc );
864 if( p_ifo->vmg.manager_inf.i_title_unit_start_sector )
866 FreeTitleUnit( &p_ifo->vmg.title_unit );
869 if( p_ifo->vmg.manager_inf.i_title_inf_start_sector )
871 free( p_ifo->vmg.title_inf.p_attr );
874 FreeTitle( &p_ifo->vmg.title );
882 * Function common to Video Manager and Video Title set Processing
885 /*****************************************************************************
886 * ReadTitle : Fills the title structure.
887 *****************************************************************************
888 * Titles are logical stream units that correspond to a whole inside the dvd.
889 * Several title can point to the same part of the physical DVD, and give
890 * map to different anglesfor instance.
891 *****************************************************************************/
892 static int ReadTitle( ifo_t * p_ifo, title_t * p_title, int i_block, int i_bytes )
894 u8 p_buf[DVD_LB_SIZE];
901 p_tmp = FillBuffer( p_ifo, p_buf, i_block ) + i_bytes;
903 i_start = p_ifo->i_pos;
905 //fprintf( stderr, "PGC @ %d + %d\n", p_ifo->i_pos, i_bytes );
907 DumpBytes( p_ifo, p_buf, &p_tmp, 2);
908 p_title->i_chapter_nb = ReadByte( p_ifo, p_buf, &p_tmp );
909 p_title->i_cell_nb = ReadByte( p_ifo, p_buf, &p_tmp );
910 //fprintf( stderr, "title: Prg: %d Cell: %d\n",p_title->i_chapter_nb,p_title->i_cell_nb );
911 p_title->i_play_time = ReadDouble( p_ifo, p_buf, &p_tmp );
912 p_title->i_prohibited_user_op = ReadDouble( p_ifo, p_buf, &p_tmp );
914 for( i = 0 ; i < 8 ; i++ )
916 i_audio = ReadWord( p_ifo, p_buf, &p_tmp );
917 p_title->pi_audio_status[i].i_foo = i_audio & 0xff;
919 p_title->pi_audio_status[i].i_position = i_audio & 0x07;
921 p_title->pi_audio_status[i].i_available = i_audio;
924 for( i = 0 ; i < 32 ; i++ )
926 i_spu = ReadDouble( p_ifo, p_buf, &p_tmp );
927 p_title->pi_spu_status[i].i_position_pan = i_spu & 0x1f;
929 p_title->pi_spu_status[i].i_position_letter = i_spu & 0x1f;
931 p_title->pi_spu_status[i].i_position_wide = i_spu & 0x1f;
933 p_title->pi_spu_status[i].i_position_43 = i_spu & 0x1f;
935 p_title->pi_spu_status[i].i_available = i_spu;
938 p_title->i_next_title_num = ReadWord( p_ifo, p_buf, &p_tmp );
939 p_title->i_prev_title_num = ReadWord( p_ifo, p_buf, &p_tmp );
940 p_title->i_go_up_title_num = ReadWord( p_ifo, p_buf, &p_tmp );
941 p_title->i_still_time = ReadByte( p_ifo, p_buf, &p_tmp );
942 p_title->i_play_mode = ReadByte( p_ifo, p_buf, &p_tmp );
944 for( i = 0 ; i < 16 ; i++ )
946 /* FIXME : We have to erase the extra bit */
947 p_title->pi_yuv_color[i] = ReadDouble( p_ifo, p_buf, &p_tmp );
950 p_title->i_command_start_byte = ReadWord( p_ifo, p_buf, &p_tmp );
951 p_title->i_chapter_map_start_byte = ReadWord( p_ifo, p_buf, &p_tmp );
952 p_title->i_cell_play_start_byte = ReadWord( p_ifo, p_buf, &p_tmp );
953 p_title->i_cell_pos_start_byte = ReadWord( p_ifo, p_buf, &p_tmp );
955 /* parsing of command_t */
956 if( p_title->i_command_start_byte )
958 p_tmp = FillBuffer( p_ifo, p_buf, i_start +
959 OFF2LB( p_title->i_command_start_byte + i_bytes ) )
960 + ( (p_title->i_command_start_byte + i_bytes) & 0x7ff );
963 p_title->command.i_pre_command_nb = ReadWord( p_ifo, p_buf, &p_tmp );
964 p_title->command.i_post_command_nb = ReadWord( p_ifo, p_buf, &p_tmp );
965 p_title->command.i_cell_command_nb = ReadWord( p_ifo, p_buf, &p_tmp );
966 DumpBytes( p_ifo, p_buf, &p_tmp, 2 );
968 /* pre-title commands */
969 if( p_title->command.i_pre_command_nb )
971 p_title->command.p_pre_command =
972 malloc( p_title->command.i_pre_command_nb
973 * sizeof(command_desc_t) );
975 if( p_title->command.p_pre_command == NULL )
977 intf_ErrMsg( "ifo error: out of memory in ReadTitle" );
981 for( i = 0 ; i < p_title->command.i_pre_command_nb ; i++ )
983 p_title->command.p_pre_command[i] =
984 ReadQuad( p_ifo, p_buf, &p_tmp );
989 p_title->command.p_pre_command = NULL;
992 /* post-title commands */
993 if( p_title->command.i_post_command_nb )
995 p_title->command.p_post_command =
996 malloc( p_title->command.i_post_command_nb
997 * sizeof(command_desc_t) );
999 if( p_title->command.p_post_command == NULL )
1001 intf_ErrMsg( "ifo error: out of memory in ReadTitle" );
1005 for( i = 0 ; i < p_title->command.i_post_command_nb ; i++ )
1007 p_title->command.p_post_command[i] =
1008 ReadQuad( p_ifo, p_buf, &p_tmp );
1013 p_title->command.p_post_command = NULL;
1017 if( p_title->command.i_cell_command_nb )
1019 p_title->command.p_cell_command =
1020 malloc( p_title->command.i_cell_command_nb
1021 * sizeof(command_desc_t) );
1023 if( p_title->command.p_cell_command == NULL )
1025 intf_ErrMsg( "ifo error: out of memory in ReadTitle" );
1029 for( i = 0 ; i < p_title->command.i_cell_command_nb ; i++ )
1031 p_title->command.p_cell_command[i] =
1032 ReadQuad( p_ifo, p_buf, &p_tmp );
1037 p_title->command.p_cell_command = NULL;
1041 /* parsing of chapter_map_t: it gives the entry cell for each chapter */
1042 if( p_title->i_chapter_map_start_byte )
1044 p_ifo->i_pos = dvdcss_seek( p_ifo->dvdhandle,
1045 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_first_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_last_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 );
1146 if( p_title->i_chapter_map_start_byte )
1148 free( p_title->chapter_map.pi_start_cell );
1151 if( p_title->i_cell_play_start_byte )
1153 free( p_title->p_cell_play );
1156 if( p_title->i_cell_pos_start_byte )
1158 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_last_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 )
1222 if( p_unit_inf->p_title != NULL )
1224 for( i = 0 ; i < p_unit_inf->i_title_nb ; i++ )
1226 FreeTitle( &p_unit_inf->p_title[i].title );
1229 free( p_unit_inf->p_title );
1236 /*****************************************************************************
1237 * ReadTitleUnit: Fills the Title Unit structure.
1238 *****************************************************************************/
1239 static int ReadTitleUnit( ifo_t * p_ifo, title_unit_t * p_title_unit,
1242 u8 p_buf[DVD_LB_SIZE];
1247 p_tmp = FillBuffer( p_ifo, p_buf, i_block );
1248 i_start = p_ifo->i_pos;
1249 //fprintf( stderr, "Unit Table\n" );
1251 p_title_unit->i_unit_nb = ReadWord( p_ifo, p_buf, &p_tmp );
1252 DumpBytes( p_ifo, p_buf, &p_tmp, 2 );
1253 p_title_unit->i_last_byte = ReadDouble( p_ifo, p_buf, &p_tmp );
1255 //fprintf(stderr, "Unit: nb %d last %d\n", p_title_unit->i_unit_nb, p_title_unit->i_last_byte );
1257 p_title_unit->p_unit = malloc( p_title_unit->i_unit_nb * sizeof(unit_t) );
1258 if( p_title_unit->p_unit == NULL )
1260 intf_ErrMsg( "ifo error: out of memory in ReadTitleUnit" );
1264 for( i = 0 ; i < p_title_unit->i_unit_nb ; i++ )
1266 //ReadBytes( p_ifo, p_buf, &p_tmp, p_title_unit->p_unit[i].ps_lang_code, 2 );
1267 p_title_unit->p_unit[i].i_lang_code = ReadWord( p_ifo, p_buf, &p_tmp );
1268 //fprintf( stderr, "lang %d %x\n", i,p_title_unit->p_unit[i].i_lang_code );
1269 DumpBytes( p_ifo, p_buf, &p_tmp, 1 );
1270 p_title_unit->p_unit[i].i_existence_mask =
1271 ReadByte( p_ifo, p_buf, &p_tmp );
1272 p_title_unit->p_unit[i].i_unit_inf_start_byte =
1273 ReadDouble( p_ifo, p_buf, &p_tmp );
1276 p_title_unit->p_unit_inf =
1277 malloc( p_title_unit->i_unit_nb * sizeof(unit_inf_t) );
1278 if( p_title_unit->p_unit_inf == NULL )
1280 intf_ErrMsg( "ifo error: out of memory in ReadTitleUnit" );
1284 for( i = 0 ; i < p_title_unit->i_unit_nb ; i++ )
1286 ReadUnitInf( p_ifo, &p_title_unit->p_unit_inf[i], i_start +
1287 OFF2LB( p_title_unit->p_unit[i].i_unit_inf_start_byte ),
1288 p_title_unit->p_unit[i].i_unit_inf_start_byte & 0x7ff );
1294 /*****************************************************************************
1295 * FreeTitleUnit: frees a structure allocateed by ReadTitleUnit
1296 *****************************************************************************/
1297 static int FreeTitleUnit( title_unit_t * p_title_unit )
1301 if( p_title_unit->p_unit_inf != NULL )
1303 for( i = 0 ; i < p_title_unit->i_unit_nb ; i++ )
1305 FreeUnitInf( &p_title_unit->p_unit_inf[i] );
1308 free( p_title_unit->p_unit_inf );
1314 /*****************************************************************************
1315 * ReadCellInf : Fills the Cell Information structure.
1316 *****************************************************************************/
1317 static int ReadCellInf( ifo_t * p_ifo, cell_inf_t * p_cell_inf, int i_block )
1319 u8 p_buf[DVD_LB_SIZE];
1324 p_tmp = FillBuffer( p_ifo, p_buf, i_block );
1325 i_start = p_ifo->i_pos;
1326 // fprintf( stderr, "CELL ADD\n" );
1328 p_cell_inf->i_vob_nb = ReadWord( p_ifo, p_buf, &p_tmp );
1329 DumpBytes( p_ifo, p_buf, &p_tmp, 2 );
1330 p_cell_inf->i_last_byte = ReadDouble( p_ifo, p_buf, &p_tmp );
1332 p_cell_inf->i_cell_nb = (p_cell_inf->i_last_byte + 1/* - 7*/) / sizeof(cell_map_t);
1334 /* fprintf( stderr, "Cell inf: vob %d, %d cells, last byte %d\n", p_cell_inf->i_vob_nb, p_cell_inf->i_cell_nb, p_cell_inf->i_last_byte );
1336 p_cell_inf->p_cell_map =
1337 malloc( p_cell_inf->i_cell_nb *sizeof(cell_map_t) );
1338 if( p_cell_inf->p_cell_map == NULL )
1340 intf_ErrMsg( "ifo error: out of memory in ReadCellInf" );
1344 for( i = 0 ; i < p_cell_inf->i_cell_nb ; i++ )
1346 #define MAP p_cell_inf->p_cell_map[i]
1347 MAP.i_vob_id = ReadWord( p_ifo, p_buf, &p_tmp );
1348 MAP.i_cell_id = ReadByte( p_ifo, p_buf, &p_tmp );
1349 DumpBytes( p_ifo, p_buf, &p_tmp, 1 );
1350 MAP.i_first_sector = ReadDouble( p_ifo, p_buf, &p_tmp );
1351 /* fprintf(stderr, "sector[%d] %d (%d)\n", i,ntohl(*(u32*)(p_tmp)), p_ifo->i_pos);*/
1352 MAP.i_last_sector = ReadDouble( p_ifo, p_buf, &p_tmp );
1359 /*****************************************************************************
1360 * FreeCellInf : frees structures allocated by ReadCellInf
1361 *****************************************************************************/
1362 static int FreeCellInf( cell_inf_t * p_cell_inf )
1364 free( p_cell_inf->p_cell_map );
1369 /*****************************************************************************
1370 * ReadVobuMap : Fills the VOBU Map structure.
1371 *****************************************************************************/
1372 static int ReadVobuMap( ifo_t * p_ifo, vobu_map_t * p_vobu_map, int i_block )
1374 u8 p_buf[DVD_LB_SIZE];
1379 p_tmp = FillBuffer( p_ifo, p_buf, i_block );
1380 i_start = p_ifo->i_pos;
1381 //fprintf( stderr, "VOBU ADMAP\n" );
1383 p_vobu_map->i_last_byte = ReadDouble( p_ifo, p_buf, &p_tmp );
1384 i_max = ( i_start + p_vobu_map->i_last_byte + 1 - p_ifo->i_pos )
1387 p_vobu_map->pi_vobu_start_sector = malloc( i_max * sizeof(u32) );
1388 if( p_vobu_map->pi_vobu_start_sector == NULL )
1390 intf_ErrMsg( "ifo error: out of memory in ReadVobuMap" );
1394 for( i = 0 ; i < i_max ; i++ )
1396 p_vobu_map->pi_vobu_start_sector[i] = ReadDouble( p_ifo, p_buf, &p_tmp );
1402 /*****************************************************************************
1403 * FreeVobuMap: frees structures allocated by ReadVobuMap
1404 *****************************************************************************/
1405 static int FreeVobuMap( vobu_map_t * p_vobu_map )
1407 free( p_vobu_map->pi_vobu_start_sector );
1413 * IFO virtual machine : a set of commands that give the
1414 * interactive behaviour of the dvd
1418 #define OP_VAL_16(i) (ntoh16( com.data.pi_16[i]))
1419 #define OP_VAL_8(i) ((com.data.pi_8[i]))
1421 static char ifo_reg[][80]=
1423 "Menu_Language_Code",
1425 "SubPicture_Stream_#",
1431 "Highlighted_Button_#",
1434 "Karaoke_audio_mixing_mode",
1435 "Parental_mgmt_country_code",
1439 "Audio_language_code_setting",
1440 "Audio_language_extension_code",
1441 "SPU_language_code_setting",
1442 "SPU_language_extension_code",
1443 "?Player_Regional_Code",
1449 static char * IfoMath( char val )
1451 static char math_op[][10] =
1471 return (char *) math_op[val & 0x0f];
1475 char ifo_cmp[][10] =
1487 char ifo_parental[][10] =
1499 char ifo_menu_id[][80] =
1511 char * IfoMenuName( char index )
1513 return ifo_menu_id[index&0x07];
1516 static void IfoRegister( u16 i_data, u8 i_direct)
1520 if( 0/*isalpha( i_data >> 8 & 0xff )*/ )
1522 printf("'%c%c'", i_data>>8&0xff, i_data&0xff);
1526 printf("0x%02x", i_data);
1541 printf("s[%s]", ifo_reg[i_data]);
1554 printf("r[0x%02x]", i_data);
1560 static void IfoAdvanced( u8 *pi_code )
1562 u8 i_cmd = pi_code[0];
1568 printf( " Highlight button %d; ", pi_code[1]>>2 );
1573 printf( " Illegal " );
1578 printf( "ReSuME %d", pi_code[7] );
1580 else if( ( i_cmd & 0x06) == 0x02 )
1582 printf ("Link to %s cell ", ( i_cmd & 0x01 ) ? "prev" : "next");
1586 printf( "advanced (0x%02x) ", i_cmd );
1591 static void IfoJmp( ifo_command_t com )
1596 switch( com.i_sub_cmd )
1602 printf( "VTS 0x%02x", OP_VAL_8(3) );
1605 printf( "This VTS Title 0x%02x", OP_VAL_8(3) );
1608 printf( "This VTS Title 0x%02x Part 0x%04x",
1610 OP_VAL_8(0)<<8|OP_VAL_8(1));
1614 printf ("in SystemSpace ");
1615 switch (OP_VAL_8(3)>>4) {
1617 printf ("to play first PGC");
1620 printf ("to menu \"%s\"", decode_menuname (OP_VAL_8(3)));
1624 printf ("to VTS 0x%02x and TTN 0x%02x", OP_VAL_8(1), OP_VAL_8(2));
1627 printf ("to VMGM PGC number 0x%02x", OP_VAL_8(0)<<8 | OP_VAL_8(1));
1630 printf ("vts 0x%02x lu 0x%02x menu \"%s\"", OP_VAL_8(2), OP_VAL_8(1), decode_menuname (OP_VAL_8(3)));
1633 switch( OP_VAL_8(3)>>6 )
1636 printf( "to play first PGC" );
1639 printf( "to VMG title menu (?)" );
1642 printf( "vts 0x%02x lu 0x%02x menu \"%s\"",
1645 IfoMenuName( OP_VAL_8(3)&0xF ) );
1648 printf( "vmg pgc 0x%04x (?)", ( OP_VAL_8(0)<<8) | OP_VAL_8(1) );
1655 switch(OP_VAL_8(3)>>4) {
1657 printf ("system first pgc");
1660 printf ("system title menu");
1663 printf ("system menu \"%s\"", decode_menuname (OP_VAL_8(3)));
1666 printf ("system vmg pgc %02x ????", OP_VAL_8(0)<<8|OP_VAL_8(1));
1669 printf ("system lu 0x%02x menu \"%s\"", OP_VAL_8(2), decode_menuname (OP_VAL_8(3)));
1672 printf ("system vmg pgc 0x%02x", OP_VAL_8(0)<<8|OP_VAL_8(1));
1676 // OP_VAL_8(2) is number of cell
1677 // it is processed BEFORE switch
1678 // under some conditions, it is ignored
1679 // I don't understand exactly what it means
1680 printf( " ( spec cell 0x%02X ) ", OP_VAL_8(2) );
1682 switch( OP_VAL_8(3)>>6 )
1685 printf( "to FP PGC" );
1688 printf( "to VMG root menu (?)" );
1691 printf( "to VTS menu \"%s\" (?)",
1692 IfoMenuName(OP_VAL_8(3)&0xF) );
1695 printf( "vmg pgc 0x%02x (?)", (OP_VAL_8(0)<<8)|OP_VAL_8(1) );
1703 static void IfoLnk( ifo_command_t com )
1705 u16 i_button=OP_VAL_8(4)>>2;
1709 switch( com.i_sub_cmd )
1712 IfoAdvanced( &OP_VAL_8(4) );
1716 printf( "PGC 0x%02x", OP_VAL_16(2) );
1720 printf( "PTT 0x%02x", OP_VAL_16(2) );
1724 printf( "Program 0x%02x this PGC", OP_VAL_8(5) );
1728 printf( "Cell 0x%02x this PGC", OP_VAL_8(5) );
1736 printf( ", Highlight 0x%02x", OP_VAL_8(4)>>2 );
1741 void IfoSetSystem( ifo_command_t com )
1748 for( i=1; i<=3; i++ )
1750 if( OP_VAL_8(i)&0x80 )
1754 printf ("s[%s] = 0x%02x;", ifo_reg[i], OP_VAL_8(i)&0xf);
1758 printf ("s[%s] = r[0x%02x];", ifo_reg[i], OP_VAL_8(i)&0xf);
1764 if(OP_VAL_8(1]&0x80)
1765 printf ("s[%s] = 0x%02x;", reg_name[1], OP_VAL_8(1]&0xf);
1766 if(OP_VAL_8(2)&0x80)
1767 //DENT: lwhat about 0x7f here ???
1768 printf ("s[%s] = 0x%02x;", reg_name[2], OP_VAL_8(2)&0x7f);
1769 if(OP_VAL_8(3)&0x80)
1770 printf ("s[%s] = 0x%02x;", reg_name[3], OP_VAL_8(3)&0xf);
1772 if(OP_VAL_8(1)&0x80)
1773 printf ("s[%s] = r[0x%02x];", reg_name[1], OP_VAL_8(1)&0xf);
1774 if(OP_VAL_8(2)&0x80)
1775 printf ("s[%s] = r[0x%02x];", reg_name[2], OP_VAL_8(2)&0xf);
1776 if(OP_VAL_8(3)&0x80)
1777 printf ("s[%s] = r[0x%02x];", reg_name[3], OP_VAL_8(3)&0xf);
1785 printf( "s[%s] = 0x%02x", ifo_reg[9], OP_VAL_16(0) );
1789 printf( "s[%s] = r[0x%02x]", ifo_reg[9], OP_VAL_8(1)&0x0f );
1792 printf( "s[%s] = (s[%s]&0x7FFF)|0x%02x",
1793 ifo_reg[10], ifo_reg[10], OP_VAL_16(1)&0x8000);
1798 printf( "r[0x%02x] = 0x%02x", OP_VAL_8(3)&0x0f, OP_VAL_16(0) );
1802 printf ("r[r[0x%02x]] = r[0x%02x]",
1803 OP_VAL_8(3)&0x0f, OP_VAL_8(1)&0x0f);
1807 //actually only bits 00011100 00011100 are set
1810 printf ("s[%s] = 0x%02x", ifo_reg[11], OP_VAL_16(1));
1814 printf ("s[%s] = r[0x%02x]", ifo_reg[11], OP_VAL_8(3)&0x0f );
1819 //s[%s]=(r[%s]&0x3FF) | (0x%02x << 0xA);
1820 //but it is way too ugly
1823 printf( "s[%s] = 0x%02x", ifo_reg[8], OP_VAL_8(2)>>2 );
1827 printf( "s[%s] = r[0x%02x]", ifo_reg[8], OP_VAL_8(3)&0x0f );
1835 static void IfoSet( ifo_command_t com )
1837 IfoRegister( OP_VAL_16(0), 0 );
1838 printf( " %s ", IfoMath( com.i_cmd ) );
1839 IfoRegister( OP_VAL_16(1), com.i_direct );
1842 /*****************************************************************************
1843 * CommandRead : translates the command strings in ifo into command
1845 *****************************************************************************/
1846 void CommandRead( ifo_command_t com )
1848 u8* pi_code = (u8*)(&com);
1850 switch( com.i_type )
1863 printf ("if (r[0x%02x] %s ", OP_VAL_8(1)&0x0f,
1864 ifo_cmp[com.i_cmp]);
1865 IfoRegister (OP_VAL_16(1), com.i_dir_cmp);
1870 switch( com.i_sub_cmd )
1873 printf( "goto Line 0x%02x", OP_VAL_16(2) );
1877 printf( "stop VM" );
1881 printf( "Set Parental Level To %s and goto Line 0x%02x",
1882 ifo_parental[OP_VAL_8(4)&0x7],
1887 printf( "Illegal" );
1906 printf( "if (r[0x%02x] %s ", OP_VAL_8(4)&0x0f,
1907 ifo_cmp[com.i_cmp] );
1908 IfoRegister( OP_VAL_8(5), 0 );
1919 printf( "if (r[0x%02x] %s ", OP_VAL_8(1)&0x0f,
1920 ifo_cmp[com.i_cmp] );
1921 IfoRegister( OP_VAL_16(1), com.i_dir_cmp );
1935 IfoSetSystem( com );
1937 else if( com.i_cmp && !com.i_sub_cmd )
1939 printf ("if (r[0x%02x] %s ", OP_VAL_8(4)&0x0f, ifo_cmp[com.i_cmp]);
1940 IfoRegister( OP_VAL_8(5), 0 );
1942 IfoSetSystem( com );
1944 else if( !com.i_cmp && com.i_sub_cmd )
1947 IfoSetSystem( com );
1963 else if( com.i_cmp && !com.i_sub_cmd )
1965 printf ("if (r[0x%02x] %s ", OP_VAL_8(0)&0x0f, ifo_cmp[com.i_cmp]);
1966 IfoRegister( OP_VAL_16(2), com.i_dir_cmp );
1970 else if( !com.i_cmp && com.i_sub_cmd )
1984 * math command on r[opcode[1]] and
1985 * direct?be2me_16(OP_VAL_8(0)):reg[OP_VAL_8(1)] is executed
1986 * ( unless command is swap; then r[opcode[1]] and r[OP_VAL_8(1)]
1988 * boolean operation cmp on r[opcode[1]] and
1989 * dir_cmp?be2me_16(OP_VAL_8(1)[1]):reg[OP_VAL_8(3)] is executed
1990 * on true result, buttons(c[6], c[7]) is called
1991 * problem is 'what is buttons()'
1994 printf( "r[0x%X] ", pi_code[1] );
1995 printf( " %s ", IfoMath( com.i_cmd ) );
1996 if( com.i_cmd == 2 )
1998 printf( "r[0x%X] ", OP_VAL_8(1) );
2002 IfoRegister( OP_VAL_16(0), com.i_direct );
2006 printf( "if ( r[%d] %s ", pi_code[1], ifo_cmp[com.i_cmp] );
2007 IfoRegister( OP_VAL_8(1), com.i_dir_cmp );
2008 printf( " ) then {" );
2009 IfoAdvanced( &OP_VAL_8(4) );
2014 * opposite to case 4: boolean, math and buttons.
2020 if( !com.i_direct && com.i_dir_cmp )
2022 printf( "0x%X", OP_VAL_16(1) );
2026 IfoRegister( OP_VAL_8(3), 0 );
2027 if( OP_VAL_8(3)&0x80 )
2029 printf( "s[%s]", ifo_reg[OP_VAL_8(3)&0x1F] );
2033 printf( "r[0x%X]", OP_VAL_8(3)&0x1F);
2034 // 0x1F is either not a mistake,
2035 // or Microsoft programmer's mistake!!!
2039 printf( " %s r[0x%X] ", ifo_cmp[com.i_cmp],
2040 com.i_direct ? OP_VAL_8(2) : OP_VAL_8(1) );
2041 printf( " ) then {" );
2042 printf( "r[0x%X] ", pi_code[1] & 0xF );
2043 printf( " %s ", IfoMath( com.i_cmd ) );
2045 if( com.i_cmd == 0x02 ) // swap
2047 printf("r[0x%X] ", OP_VAL_8(0)&0x1F);
2053 printf( "0x%X", OP_VAL_16(0) );
2057 if( OP_VAL_8(0) & 0x80 )
2059 printf("s[%s]", ifo_reg[OP_VAL_8(0) & 0x1F] );
2063 printf("r[0x%X]", OP_VAL_8(0) & 0x1F );
2069 IfoAdvanced( &OP_VAL_8(4) );
2075 printf( "Unknown Command\n" );
2082 /*****************************************************************************
2083 * CommandPrint : print in clear text (I hope so !) what a command does
2084 *****************************************************************************/
2085 void CommandPrint( ifo_t ifo )
2092 /*****************************************************************************
2094 *****************************************************************************/
2095 static u8* FillBuffer( ifo_t* p_ifo, u8* p_buf, int i_pos )
2097 p_ifo->i_pos = dvdcss_seek( p_ifo->dvdhandle, i_pos, DVDCSS_NOFLAGS );
2098 dvdcss_read( p_ifo->dvdhandle, p_buf, 1, DVDCSS_NOFLAGS );
2103 static void ReadBytes( ifo_t* p_ifo, u8* p_buf, u8** pp_tmp,
2104 u8* pi_dest, int i_nb )
2106 if( i_nb > DVD_LB_SIZE )
2108 intf_ErrMsg( "ifo error: excessive ReadBytes call (%i)", i_nb );
2111 if( *pp_tmp + i_nb >= p_buf + DVD_LB_SIZE )
2113 int i_spare = (int)( (p_buf + DVD_LB_SIZE) - *pp_tmp );
2115 /* Copy the bytes remaining in the current buffer */
2116 memcpy( pi_dest, *pp_tmp, i_spare );
2120 /* Load the next buffer */
2121 *pp_tmp = FillBuffer( p_ifo, p_buf, p_ifo->i_pos + 1 );
2124 memcpy( pi_dest, *pp_tmp, i_nb );
2130 static void DumpBytes( ifo_t* p_ifo, u8* p_buf, u8** pp_tmp, int i_nb )
2132 if( i_nb > DVD_LB_SIZE )
2134 intf_ErrMsg( "ifo error: excessive DumpBytes call (%i)", i_nb );
2139 if( *pp_tmp >= p_buf + DVD_LB_SIZE )
2141 /* If we went too far, load the next buffer */
2142 *pp_tmp = FillBuffer( p_ifo, p_buf, p_ifo->i_pos + 1 )
2143 + (int)( (*pp_tmp) - (p_buf + DVD_LB_SIZE) );
2150 if( *pp_tmp >= p_buf + DVD_LB_SIZE ) \
2152 *pp_tmp = FillBuffer( p_ifo, p_buf, p_ifo->i_pos + 1 ); \
2154 i_ret <<= 8; i_ret |= **pp_tmp; (*pp_tmp)++;
2156 static u8 ReadByte( ifo_t * p_ifo, u8* p_buf, u8** pp_tmp )
2163 static u16 ReadWord( ifo_t * p_ifo, u8* p_buf, u8** pp_tmp )
2170 static u32 ReadDouble( ifo_t * p_ifo, u8* p_buf, u8** pp_tmp )
2173 ADDBYTE; ADDBYTE; ADDBYTE; ADDBYTE;
2177 static u64 ReadQuad( ifo_t * p_ifo, u8* p_buf, u8** pp_tmp )
2180 ADDBYTE; ADDBYTE; ADDBYTE; ADDBYTE; ADDBYTE; ADDBYTE; ADDBYTE; ADDBYTE;