* dvd_ifo.c: Functions for ifo parsing
*****************************************************************************
* Copyright (C) 1999-2001 VideoLAN
- * $Id: dvd_ifo.c,v 1.3 2001/02/08 17:44:12 massiot Exp $
+ * $Id: dvd_ifo.c,v 1.14 2001/02/22 08:44:45 stef Exp $
*
* Author: Stéphane Borel <stef@via.ecp.fr>
*
+ * based on:
+ * - libifo by Thomas Mirlacher <dent@cosy.sbg.ac.at>
+ * - IFO structure documentation by Thomas Mirlacher, Björn Englund,
+ * Håkan Hjort
+ *
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation; either version 2 of the License, or
#include "intf_msg.h"
#include "dvd_ifo.h"
+#include "dvd_udf.h"
+#include "dvd_css.h"
#include "input_dvd.h"
/*
- * IFO Management.
+ * Local prototypes
*/
+static vmg_t ReadVMG ( ifo_t* );
+void CommandRead( ifo_command_t );
-/*****************************************************************************
- * IfoFindVMG : When reading directly on a device, finds the offset to the
- * beginning of video_ts.ifo.
- *****************************************************************************/
-static int IfoFindVMG( ifo_t* p_ifo )
-{
- char psz_ifo_start[12] = "DVDVIDEO-VMG";
- char psz_test[12];
-
- read( p_ifo->i_fd, psz_test, 12 );
-
- while( strncmp( psz_test, psz_ifo_start, 12 ) != 0 )
- {
- /* The start of ifo file is on a sector boundary */
- p_ifo->i_pos = lseek( p_ifo->i_fd,
- p_ifo->i_pos + DVD_LB_SIZE,
- SEEK_SET );
- read( p_ifo->i_fd, psz_test, 12 );
- }
- p_ifo->i_off = p_ifo->i_pos;
-
-//fprintf( stderr, "VMG Off : %lld\n", (long long)(p_ifo->i_off) );
-
- return 0;
-}
-
-/*****************************************************************************
- * IfoFindVTS : beginning of vts_*.ifo.
- *****************************************************************************/
-static int IfoFindVTS( ifo_t* p_ifo )
-{
- char psz_ifo_start[12] = "DVDVIDEO-VTS";
- char psz_test[12];
-
- read( p_ifo->i_fd, psz_test, 12 );
-
- while( strncmp( psz_test, psz_ifo_start, 12 ) != 0 )
- {
- /* The start of ifo file is on a sector boundary */
- p_ifo->i_pos = lseek( p_ifo->i_fd,
- p_ifo->i_pos + DVD_LB_SIZE,
- SEEK_SET );
- read( p_ifo->i_fd, psz_test, 12 );
- }
- p_ifo->i_off = p_ifo->i_pos;
-
-//fprintf( stderr, "VTS Off : %lld\n", (long long)(p_ifo->i_off) );
-
- return 0;
-}
+/*
+ * IFO Management.
+ */
/*****************************************************************************
* IfoInit : Creates an ifo structure and prepares for parsing directly
ifo_t IfoInit( int i_fd )
{
ifo_t ifo;
+ u32 i_lba;
/* If we are here the dvd device has already been opened */
ifo.i_fd = i_fd;
- /* No data at the beginning of the disk
- * 512000 bytes is just another value :) */
- ifo.i_pos = lseek( ifo.i_fd, 250 *DVD_LB_SIZE, SEEK_SET );
- /* FIXME : use udf filesystem to find the beginning of the file */
- IfoFindVMG( &ifo );
-
+
+ i_lba = UDFFindFile( i_fd, "/VIDEO_TS/VIDEO_TS.IFO");
+
+ ifo.i_off = (off_t)(i_lba) * DVD_LB_SIZE;
+ ifo.i_pos = lseek( ifo.i_fd, ifo.i_off, SEEK_SET );
+
+ /* Video Manager Initialization */
+ intf_WarnMsg( 2, "ifo: initializing VMG" );
+ ifo.vmg = ReadVMG( &ifo );
+
return ifo;
}
*****************************************************************************/
void IfoEnd( ifo_t* p_ifo )
{
+#if 0
int i,j;
/* Free structures from video title sets */
free( p_ifo->vmg.pgc.com_tab.p_cell_com );
free( p_ifo->vmg.pgc.com_tab.p_post_com );
free( p_ifo->vmg.pgc.com_tab.p_pre_com );
-
+#endif
return;
}
(int)((p_com)->i_dir_cmp), \
(int)((p_com)->i_cmp), \
(int)((p_com)->i_sub_cmd), \
- (int)((p_com)->i_v0), \
- (int)((p_com)->i_v2), \
- (int)((p_com)->i_v4) ); */ \
+ (int)((p_com)->data.pi_16[0]), \
+ (int)((p_com)->data.pi_16[1]), \
+ (int)((p_com)->data.pi_16[2]));*/ \
+/* CommandRead( *(p_com) );*/ \
p_ifo->i_pos += 8; \
}
FLUSH(2);
GETC( &pgc.i_prg_nb );
GETC( &pgc.i_cell_nb );
+//fprintf( stderr, "PGC: Prg: %d Cell: %d\n", pgc.i_prg_nb, pgc.i_cell_nb );
GETL( &pgc.i_play_time );
GETL( &pgc.i_prohibited_user_op );
for( i=0 ; i<8 ; i++ )
GETS( &pgc.i_next_pgc_nb );
GETS( &pgc.i_prev_pgc_nb );
GETS( &pgc.i_goup_pgc_nb );
+//fprintf( stderr, "PGC: Prev: %d Next: %d Up: %d\n",pgc.i_prev_pgc_nb ,pgc.i_next_pgc_nb, pgc.i_goup_pgc_nb );
GETC( &pgc.i_still_time );
GETC( &pgc.i_play_mode );
for( i=0 ; i<16 ; i++ )
p_ifo->i_pos = lseek( p_ifo->i_fd, i_start
+ pgc.i_cell_pos_inf_sbyte, SEEK_SET );
pgc.p_cell_pos_inf = malloc( pgc.i_cell_nb *sizeof(cell_pos_inf_t) );
- if( pgc.p_cell_play_inf == NULL )
+ if( pgc.p_cell_pos_inf == NULL )
{
intf_ErrMsg( "Out of memory" );
p_ifo->b_error = 1;
p_ifo->i_pos = lseek( p_ifo->i_fd,
i_start + inf.p_srp[i].i_pgci_sbyte,
SEEK_SET );
+//fprintf( stderr, "Unit: PGC %d\n", i );
inf.p_srp[i].pgc = ReadPGC( p_ifo );
}
static c_adt_t ReadCellInf( ifo_t* p_ifo )
{
c_adt_t c_adt;
- int i, i_max;
off_t i_start = p_ifo->i_pos;
+ int i;
//fprintf( stderr, "CELL ADD\n" );
GETS( &c_adt.i_vob_nb );
FLUSH( 2 );
GETL( &c_adt.i_ebyte );
- i_max = ( i_start + c_adt.i_ebyte + 1 - p_ifo->i_pos ) / sizeof(cell_inf_t);
- c_adt.p_cell_inf = malloc( i_max *sizeof(cell_inf_t) );
+ c_adt.i_cell_nb =
+ ( i_start + c_adt.i_ebyte + 1 - p_ifo->i_pos ) / sizeof(cell_inf_t);
+ c_adt.p_cell_inf = malloc( c_adt.i_cell_nb *sizeof(cell_inf_t) );
if( c_adt.p_cell_inf == NULL )
{
intf_ErrMsg( "Out of memory" );
p_ifo->b_error = 1;
return c_adt;
}
- for( i=0 ; i<i_max ; i++ )
+ for( i = 0 ; i < c_adt.i_cell_nb ; i++ )
{
GETS( &c_adt.p_cell_inf[i].i_vob_id );
GETC( &c_adt.p_cell_inf[i].i_cell_id );
static vmgi_mat_t ReadVMGInfMat( ifo_t* p_ifo )
{
vmgi_mat_t mat;
+ u64 i_temp;
int i;
// off_t i_start = p_ifo->i_pos;
GETL( &mat.i_c_adt_ssector );
GETL( &mat.i_vobu_admap_ssector );
FLUSH( 32 );
- GETS( &mat.i_video_atrt );
+// GETS( &mat.video_atrt );
+FLUSH(2);
FLUSH( 1 );
GETC( &mat.i_audio_nb );
//fprintf( stderr, "vmgi audio nb : %d\n", mat.i_audio_nb );
for( i=0 ; i < 8 ; i++ )
{
- GETLL( &mat.pi_audio_atrt[i] );
+ GETLL( &i_temp );
}
FLUSH( 17 );
GETC( &mat.i_subpic_nb );
//fprintf( stderr, "vmgi subpic nb : %d\n", mat.i_subpic_nb );
for( i=0 ; i < mat.i_subpic_nb ; i++ )
{
- GET( &mat.pi_subpic_atrt[i], 6 );
+ GET( &i_temp, 6 );
/* FIXME : take care of endianness */
}
//fprintf( stderr, "PTR\n" );
GETS( &ptr.i_ttu_nb );
+//fprintf( stderr, "PTR: TTU nb %d\n", ptr.i_ttu_nb );
FLUSH( 2 );
GETL( &ptr.i_ebyte );
/* Parsing of tts */
GETC( &ptr.p_tts[i].i_tts_nb );
GETC( &ptr.p_tts[i].i_vts_ttn );
GETL( &ptr.p_tts[i].i_ssector );
+//fprintf( stderr, "PTR: %d %d %d\n", ptr.p_tts[i].i_ptt_nb, ptr.p_tts[i].i_tts_nb,ptr.p_tts[i].i_vts_ttn );
}
return ptr;
{
vmg_vts_atrt_t atrt;
int i, j;
+ u64 i_temp;
off_t i_start = p_ifo->i_pos;
//fprintf( stderr, "VTS ATTR\n" );
GETS( &atrt.i_vts_nb );
+//fprintf( stderr, "VTS ATTR Nb: %d\n", atrt.i_vts_nb );
FLUSH( 2 );
GETL( &atrt.i_ebyte );
atrt.pi_vts_atrt_sbyte = malloc( atrt.i_vts_nb *sizeof(u32) );
SEEK_SET );
GETL( &atrt.p_vts_atrt[i].i_ebyte );
GETL( &atrt.p_vts_atrt[i].i_cat_app_type );
- GETS( &atrt.p_vts_atrt[i].i_vtsm_video_atrt );
+// GETS( &atrt.p_vts_atrt[i].vtsm_video_atrt );
+FLUSH(2);
FLUSH( 1 );
GETC( &atrt.p_vts_atrt[i].i_vtsm_audio_nb );
//fprintf( stderr, "m audio nb : %d\n", atrt.p_vts_atrt[i].i_vtsm_audio_nb );
for( j=0 ; j<8 ; j++ )
{
- GETLL( &atrt.p_vts_atrt[i].pi_vtsm_audio_atrt[j] );
+ GETLL( &i_temp );
}
FLUSH( 17 );
GETC( &atrt.p_vts_atrt[i].i_vtsm_subpic_nb );
//fprintf( stderr, "m subp nb : %d\n", atrt.p_vts_atrt[i].i_vtsm_subpic_nb );
for( j=0 ; j<28 ; j++ )
{
- GET( &atrt.p_vts_atrt[i].pi_vtsm_subpic_atrt[j], 6 );
+ GET( &i_temp, 6 );
/* FIXME : Fix endianness issue here */
}
FLUSH( 2 );
- GETS( &atrt.p_vts_atrt[i].i_vtstt_video_atrt );
+// GETS( &atrt.p_vts_atrt[i].vtstt_video_atrt );
+FLUSH(2);
FLUSH( 1 );
GETL( &atrt.p_vts_atrt[i].i_vtstt_audio_nb );
//fprintf( stderr, "tt audio nb : %d\n", atrt.p_vts_atrt[i].i_vtstt_audio_nb );
for( j=0 ; j<8 ; j++ )
{
- GETLL( &atrt.p_vts_atrt[i].pi_vtstt_audio_atrt[j] );
+ GETLL( &i_temp );
}
FLUSH( 17 );
GETC( &atrt.p_vts_atrt[i].i_vtstt_subpic_nb );
//fprintf( stderr, "tt subp nb : %d\n", atrt.p_vts_atrt[i].i_vtstt_subpic_nb );
for( j=0 ; j<28/*atrt.p_vts_atrt[i].i_vtstt_subpic_nb*/ ; j++ )
{
- GET( &atrt.p_vts_atrt[i].pi_vtstt_subpic_atrt[j], 6 );
+ GET( &i_temp, 6 );
/* FIXME : Fix endianness issue here */
}
}
{
vtsi_mat_t mat;
int i;
+ u64 i_temp;
// off_t i_start = p_ifo->i_pos;
//fprintf( stderr, "VTSI\n" );
GETL( &mat.i_c_adt_ssector );
GETL( &mat.i_vobu_admap_ssector );
FLUSH( 24 );
- GETS( &mat.i_m_video_atrt );
+// GETS( &mat.m_video_atrt );
+FLUSH(2);
FLUSH( 1 );
GETC( &mat.i_m_audio_nb );
for( i=0 ; i<8 ; i++ )
{
- GETLL( &mat.pi_m_audio_atrt[i] );
+ GETLL( &i_temp );
}
FLUSH( 17 );
GETC( &mat.i_m_subpic_nb );
for( i=0 ; i<28 ; i++ )
{
- GET( &mat.pi_m_subpic_atrt[i], 6 );
+ GET( &i_temp, 6 );
/* FIXME : take care of endianness */
}
FLUSH( 2 );
- GETS( &mat.i_video_atrt );
+// GETS( &mat.video_atrt );
+FLUSH(2);
FLUSH( 1 );
GETC( &mat.i_audio_nb );
//fprintf( stderr, "vtsi audio nb : %d\n", mat.i_audio_nb );
for( i=0 ; i<8 ; i++ )
{
- GETLL( &mat.pi_audio_atrt[i] );
+ GETLL( &i_temp );
+//fprintf( stderr, "Audio %d: %llx\n", i, i_temp );
+ i_temp >>= 32;
+ mat.p_audio_atrt[i].i_lang_code = i_temp & 0xffff;
+ i_temp >>= 16;
+ mat.p_audio_atrt[i].i_num_channels = i_temp & 0x7;
+ i_temp >>= 4;
+ mat.p_audio_atrt[i].i_sample_freq = i_temp & 0x3;
+ i_temp >>= 2;
+ mat.p_audio_atrt[i].i_quantization = i_temp & 0x3;
+ i_temp >>= 2;
+ mat.p_audio_atrt[i].i_appl_mode = i_temp & 0x3;
+ i_temp >>= 2;
+ mat.p_audio_atrt[i].i_type = i_temp & 0x3;
+ i_temp >>= 2;
+ mat.p_audio_atrt[i].i_multichannel_extension = i_temp & 0x1;
+ i_temp >>= 1;
+ mat.p_audio_atrt[i].i_coding_mode = i_temp & 0x7;
}
FLUSH( 17 );
GETC( &mat.i_subpic_nb );
//fprintf( stderr, "vtsi subpic nb : %d\n", mat.i_subpic_nb );
for( i=0 ; i<mat.i_subpic_nb ; i++ )
{
- GET( &mat.pi_subpic_atrt[i], 6 );
- /* FIXME : take care of endianness */
+ GET( &i_temp, 6 );
+ i_temp = hton64( i_temp ) >> 16;
+//fprintf( stderr, "Subpic %d: %llx\n", i, i_temp );
+ mat.p_subpic_atrt[i].i_caption = i_temp & 0xff;
+ i_temp >>= 16;
+ mat.p_subpic_atrt[i].i_lang_code = i_temp & 0xffff;
+ i_temp >>= 16;
+ mat.p_subpic_atrt[i].i_prefix = i_temp & 0xffff;
}
return mat;
int i;
off_t i_start = p_ifo->i_pos;
-//fprintf( stderr, "PTR\n" );
+//fprintf( stderr, "VTS PTR\n" );
GETS( &ptr.i_ttu_nb );
+//fprintf( stderr, "VTS PTR nb: %d\n", ptr.i_ttu_nb );
FLUSH( 2 );
GETL( &ptr.i_ebyte );
ptr.pi_ttu_sbyte = malloc( ptr.i_ttu_nb *sizeof(u32) );
ptr.pi_ttu_sbyte[i], SEEK_SET );
GETS( &ptr.p_ttu[i].i_pgc_nb );
GETS( &ptr.p_ttu[i].i_prg_nb );
+//fprintf( stderr, "VTS %d PTR Pgc: %d Prg: %d\n", i,ptr.p_ttu[i].i_pgc_nb, ptr.p_ttu[i].i_prg_nb );
}
return ptr;
/*****************************************************************************
- * ReadVTS : Parse vts*.ifo files to fill the Video Title Set structure.
+ * IfoReadVTS : Parse vts*.ifo files to fill the Video Title Set structure.
*****************************************************************************/
-static vts_t ReadVTS( ifo_t* p_ifo )
+int IfoReadVTS( ifo_t* p_ifo )
{
vts_t vts;
+ off_t i_off;
+ int i_title;
+
+ intf_WarnMsg( 2, "ifo: initializing VTS %d", p_ifo->i_title );
+
+ i_title = p_ifo->i_title;
+ i_off = (off_t)( p_ifo->vmg.ptt_srpt.p_tts[i_title-1].i_ssector )
+ * DVD_LB_SIZE
+ + p_ifo->i_off;
+
+ p_ifo->i_pos = lseek( p_ifo->i_fd, i_off, SEEK_SET );
vts.i_pos = p_ifo->i_pos;
vts.mat = ReadVTSInfMat( p_ifo );
if( vts.mat.i_ptt_srpt_ssector )
{
- p_ifo->i_pos = lseek( p_ifo->i_fd, p_ifo->i_off +
+ p_ifo->i_pos = lseek( p_ifo->i_fd, vts.i_pos +
vts.mat.i_ptt_srpt_ssector *DVD_LB_SIZE,
SEEK_SET );
vts.ptt_srpt = ReadVTSTitlePointer( p_ifo );
}
if( vts.mat.i_m_pgci_ut_ssector )
{
- p_ifo->i_pos = lseek( p_ifo->i_fd, p_ifo->i_off +
+ p_ifo->i_pos = lseek( p_ifo->i_fd, vts.i_pos +
vts.mat.i_m_pgci_ut_ssector *DVD_LB_SIZE,
SEEK_SET );
vts.pgci_ut = ReadUnitTable( p_ifo );
}
if( vts.mat.i_pgcit_ssector )
{
- p_ifo->i_pos = lseek( p_ifo->i_fd, p_ifo->i_off +
+ p_ifo->i_pos = lseek( p_ifo->i_fd, vts.i_pos +
vts.mat.i_pgcit_ssector *DVD_LB_SIZE,
SEEK_SET );
vts.pgci_ti = ReadUnit( p_ifo );
}
if( vts.mat.i_tmap_ti_ssector )
{
- p_ifo->i_pos = lseek( p_ifo->i_fd, p_ifo->i_off +
+ p_ifo->i_pos = lseek( p_ifo->i_fd, vts.i_pos +
vts.mat.i_tmap_ti_ssector *DVD_LB_SIZE,
SEEK_SET );
vts.tmap_ti = ReadVTSTimeMap( p_ifo );
}
if( vts.mat.i_m_c_adt_ssector )
{
- p_ifo->i_pos = lseek( p_ifo->i_fd, p_ifo->i_off +
+ p_ifo->i_pos = lseek( p_ifo->i_fd, vts.i_pos +
vts.mat.i_m_c_adt_ssector *DVD_LB_SIZE,
SEEK_SET );
vts.m_c_adt = ReadCellInf( p_ifo );
}
if( vts.mat.i_m_vobu_admap_ssector )
{
- p_ifo->i_pos = lseek( p_ifo->i_fd, p_ifo->i_off +
+ p_ifo->i_pos = lseek( p_ifo->i_fd, vts.i_pos +
vts.mat.i_m_vobu_admap_ssector *DVD_LB_SIZE,
SEEK_SET );
vts.m_vobu_admap = ReadMap( p_ifo );
}
if( vts.mat.i_c_adt_ssector )
{
- p_ifo->i_pos = lseek( p_ifo->i_fd, p_ifo->i_off +
+ p_ifo->i_pos = lseek( p_ifo->i_fd, vts.i_pos +
vts.mat.i_c_adt_ssector *DVD_LB_SIZE,
SEEK_SET );
vts.c_adt = ReadCellInf( p_ifo );
}
if( vts.mat.i_vobu_admap_ssector )
{
- p_ifo->i_pos = lseek( p_ifo->i_fd, p_ifo->i_off +
+ p_ifo->i_pos = lseek( p_ifo->i_fd, vts.i_pos +
vts.mat.i_vobu_admap_ssector *DVD_LB_SIZE,
SEEK_SET );
vts.vobu_admap = ReadMap( p_ifo );
}
- return vts;
+ p_ifo->vts = vts;
+
+ return 0;
}
/*
* DVD Information Management
*/
-
+#if 0
/*****************************************************************************
* IfoRead : Function that fills structure and calls specified functions
* to do it.
int i;
off_t i_off;
- p_ifo->vmg = ReadVMG( p_ifo );
+ /* Video Title Sets initialization */
p_ifo->p_vts = malloc( p_ifo->vmg.mat.i_tts_nb *sizeof(vts_t) );
if( p_ifo->p_vts == NULL )
{
p_ifo->b_error = 1;
return;
}
- for( i=0 ; i<1/*p_ifo->vmg.mat.i_tts_nb*/ ; i++ )
+
+ for( i=0 ; i<p_ifo->vmg.mat.i_tts_nb ; i++ )
{
- intf_WarnMsg( 3, "######### VTS %d #############\n", i+1 );
+ intf_WarnMsg( 2, "ifo: initializing VTS %d", i+1 );
+
+ i_off = (off_t)( p_ifo->vmg.ptt_srpt.p_tts[i].i_ssector ) *DVD_LB_SIZE
+ + p_ifo->i_off;
- i_off = p_ifo->vmg.ptt_srpt.p_tts[i].i_ssector *DVD_LB_SIZE;
p_ifo->i_pos = lseek( p_ifo->i_fd, i_off, SEEK_SET );
- /* FIXME : use udf filesystem to avoid this */
- IfoFindVTS( p_ifo );
+
+ /* FIXME : I really don't know why udf find file
+ * does not give the exact beginning of file */
+
p_ifo->p_vts[i] = ReadVTS( p_ifo );
+
}
+
return;
}
-
+#endif
/*
- * IFO virtual machine : a set of commands that give the behaviour of the dvd
+ * IFO virtual machine : a set of commands that give the
+ * interactive behaviour of the dvd
*/
-#if 0
-/*****************************************************************************
- * CommandRead : translates the command strings in ifo into command
- * structures.
- *****************************************************************************/
-void CommandRead( ifo_command_t com )
+#if 1
+
+#define OP_VAL_16(i) (ntoh16( com.data.pi_16[i]))
+#define OP_VAL_8(i) ((com.data.pi_8[i]))
+
+static char ifo_reg[][80]=
{
- u8* pi_code = (u8*)(&com);
+ "Menu_Language_Code",
+ "Audio_Stream_#",
+ "SubPicture_Stream_#",
+ "Angle_#",
+ "VTS_#",
+ "VTS_Title_#",
+ "PGC_#",
+ "PTT_#",
+ "Highlighted_Button_#",
+ "Nav_Timer",
+ "TimedPGC",
+ "Karaoke_audio_mixing_mode",
+ "Parental_mgmt_country_code",
+ "Parental_Level",
+ "Player_Video_Cfg",
+ "Player_Audio_Cfg",
+ "Audio_language_code_setting",
+ "Audio_language_extension_code",
+ "SPU_language_code_setting",
+ "SPU_language_extension_code",
+ "?Player_Regional_Code",
+ "Reserved_21",
+ "Reserved_22",
+ "Reserved_23"
+};
+
+static char * IfoMath( char val )
+{
+ static char math_op[][10] =
+ {
+ "none",
+ "=",
+ "<->", // swap
+ "+=",
+ "-=",
+ "*=",
+ "/=",
+ "%=",
+ "rnd", // rnd
+ "&=",
+ "|=",
+ "^=",
+ "??", // invalid
+ "??", // invalid
+ "??", // invalid
+ "??" // invalid
+ };
+
+ return (char *) math_op[val & 0x0f];
+}
- switch( com.i_type )
+
+char ifo_cmp[][10] =
+{
+ "none",
+ "&&",
+ "==",
+ "!=",
+ ">=",
+ ">",
+ "<",
+ "<="
+};
+
+char ifo_parental[][10] =
+{
+ "0",
+ "G",
+ "2",
+ "PG",
+ "PG-13",
+ "5",
+ "R",
+ "NC-17"
+};
+
+char ifo_menu_id[][80] =
+{
+ "-0-",
+ "-1-",
+ "Title (VTS menu)",
+ "Root",
+ "Sub-Picture",
+ "Audio",
+ "Angle",
+ "Part of Title",
+};
+
+char * IfoMenuName( char index )
+{
+ return ifo_menu_id[index&0x07];
+}
+
+static void IfoRegister( u16 i_data, u8 i_direct)
+{
+ if( i_direct )
{
- case 0: /* Goto */
- if( !pi_code[1] )
+ if( 0/*isalpha( i_data >> 8 & 0xff )*/ )
+ {
+ printf("'%c%c'", i_data>>8&0xff, i_data&0xff);
+ }
+ else
+ {
+ printf("0x%02x", i_data);
+ }
+ }
+ else
+ {
+ if( i_data & 0x80 )
+ {
+ i_data &= 0x1f;
+
+ if( i_data > 0x17 )
{
- fprintf( stderr, "NOP\n" );
+ printf("s[ILL]");
}
- else if( cmd.i_cmp )
+ else
{
-
+ printf("s[%s]", ifo_reg[i_data]);
}
+ }
+ else
+ {
+ i_data &= 0x1f;
+
+ if( i_data > 0xf )
+ {
+ printf("r[ILL]");
+ }
+ else
+ {
+ printf("r[0x%02x]", i_data);
+ }
+ }
+ }
+}
+
+static void IfoAdvanced( u8 *pi_code )
+{
+ u8 i_cmd = pi_code[0];
+
+ printf(" { ");
+
+ if( pi_code[1]>>2 )
+ {
+ printf( " Highlight button %d; ", pi_code[1]>>2 );
+ }
+
+ if( i_cmd == 0xff )
+ {
+ printf( " Illegal " );
+ }
+
+ if( i_cmd == 0x00 )
+ {
+ printf( "ReSuME %d", pi_code[7] );
+ }
+ else if( ( i_cmd & 0x06) == 0x02 )
+ { // XX01Y
+ printf ("Link to %s cell ", ( i_cmd & 0x01 ) ? "prev" : "next");
+ }
+ else
+ {
+ printf( "advanced (0x%02x) ", i_cmd );
+ }
+ printf(" } ");
+}
+
+static void IfoJmp( ifo_command_t com )
+{
+
+ printf ("jmp ");
+
+ switch( com.i_sub_cmd )
+ {
+ case 0x01:
+ printf( "Exit" );
+ break;
+ case 0x02:
+ printf( "VTS 0x%02x", OP_VAL_8(3) );
+ break;
+ case 0x03:
+ printf( "This VTS Title 0x%02x", OP_VAL_8(3) );
+ break;
+ case 0x05:
+ printf( "This VTS Title 0x%02x Part 0x%04x",
+ OP_VAL_8(3),
+ OP_VAL_8(0)<<8|OP_VAL_8(1));
+ break;
+ case 0x06:
+#if 0
+ printf ("in SystemSpace ");
+ switch (OP_VAL_8(3)>>4) {
+ case 0x00:
+ printf ("to play first PGC");
+ break;
+ case 0x01: {
+ printf ("to menu \"%s\"", decode_menuname (OP_VAL_8(3)));
+ }
+ break;
+ case 0x02:
+ printf ("to VTS 0x%02x and TTN 0x%02x", OP_VAL_8(1), OP_VAL_8(2));
+ break;
+ case 0x03:
+ printf ("to VMGM PGC number 0x%02x", OP_VAL_8(0)<<8 | OP_VAL_8(1));
+ break;
+ case 0x08:
+ printf ("vts 0x%02x lu 0x%02x menu \"%s\"", OP_VAL_8(2), OP_VAL_8(1), decode_menuname (OP_VAL_8(3)));
+ break;
+#else
+ switch( OP_VAL_8(3)>>6 )
+ {
+ case 0x00:
+ printf( "to play first PGC" );
+ break;
+ case 0x01:
+ printf( "to VMG title menu (?)" );
break;
- case 1: /* Lnk */
- break;
- case 2: /* SetSystem */
- break;
- case 3: /* Set */
- break;
- case 4: /* */
+ case 0x02:
+ printf( "vts 0x%02x lu 0x%02x menu \"%s\"",
+ OP_VAL_8(2),
+ OP_VAL_8(1),
+ IfoMenuName( OP_VAL_8(3)&0xF ) );
+ break;
+ case 0x03:
+ printf( "vmg pgc 0x%04x (?)", ( OP_VAL_8(0)<<8) | OP_VAL_8(1) );
break;
- case 5: /* */
+#endif
+ }
+ break;
+ case 0x08:
+#if 0
+ switch(OP_VAL_8(3)>>4) {
+ case 0x00:
+ printf ("system first pgc");
+ break;
+ case 0x01:
+ printf ("system title menu");
+ break;
+ case 0x02:
+ printf ("system menu \"%s\"", decode_menuname (OP_VAL_8(3)));
+ break;
+ case 0x03:
+ printf ("system vmg pgc %02x ????", OP_VAL_8(0)<<8|OP_VAL_8(1));
+ break;
+ case 0x08:
+ printf ("system lu 0x%02x menu \"%s\"", OP_VAL_8(2), decode_menuname (OP_VAL_8(3)));
+ break;
+ case 0x0c:
+ printf ("system vmg pgc 0x%02x", OP_VAL_8(0)<<8|OP_VAL_8(1));
+ break;
+ }
+#else
+ // OP_VAL_8(2) is number of cell
+ // it is processed BEFORE switch
+ // under some conditions, it is ignored
+ // I don't understand exactly what it means
+ printf( " ( spec cell 0x%02X ) ", OP_VAL_8(2) );
+
+ switch( OP_VAL_8(3)>>6 )
+ {
+ case 0:
+ printf( "to FP PGC" );
break;
- case 6: /* */
+ case 1:
+ printf( "to VMG root menu (?)" );
break;
- default:
- fprintf( stderr, "Unknown Command\n" );
+ case 2:
+ printf( "to VTS menu \"%s\" (?)",
+ IfoMenuName(OP_VAL_8(3)&0xF) );
+ break;
+ case 3:
+ printf( "vmg pgc 0x%02x (?)", (OP_VAL_8(0)<<8)|OP_VAL_8(1) );
break;
+ }
+#endif
+ break;
}
+}
- return;
+static void IfoLnk( ifo_command_t com )
+{
+ u16 i_button=OP_VAL_8(4)>>2;
+
+ printf ("lnk to ");
+
+ switch( com.i_sub_cmd )
+ {
+ case 0x01:
+ IfoAdvanced( &OP_VAL_8(4) );
+ break;
+
+ case 0x04:
+ printf( "PGC 0x%02x", OP_VAL_16(2) );
+ break;
+
+ case 0x05:
+ printf( "PTT 0x%02x", OP_VAL_16(2) );
+ break;
+
+ case 0x06:
+ printf( "Program 0x%02x this PGC", OP_VAL_8(5) );
+ break;
+
+ case 0x07:
+ printf( "Cell 0x%02x this PGC", OP_VAL_8(5) );
+ break;
+ default:
+ return;
+ }
+
+ if( i_button )
+ {
+ printf( ", Highlight 0x%02x", OP_VAL_8(4)>>2 );
+ }
+
}
-/*****************************************************************************
- * IfoGoto
- *****************************************************************************/
-static void IfoGoto( ifo_command_t cmd )
+void IfoSetSystem( ifo_command_t com )
{
-
+ switch( com.i_cmd )
+ {
+ case 1: {
+ int i;
- return;
+ for( i=1; i<=3; i++ )
+ {
+ if( OP_VAL_8(i)&0x80 )
+ {
+ if( com.i_direct )
+ {
+ printf ("s[%s] = 0x%02x;", ifo_reg[i], OP_VAL_8(i)&0xf);
+ }
+ else
+ {
+ printf ("s[%s] = r[0x%02x];", ifo_reg[i], OP_VAL_8(i)&0xf);
+ }
+ }
+ }
+#if 0
+ if(op->direct) {
+ if(OP_VAL_8(1]&0x80)
+ printf ("s[%s] = 0x%02x;", reg_name[1], OP_VAL_8(1]&0xf);
+ if(OP_VAL_8(2)&0x80)
+//DENT: lwhat about 0x7f here ???
+ printf ("s[%s] = 0x%02x;", reg_name[2], OP_VAL_8(2)&0x7f);
+ if(OP_VAL_8(3)&0x80)
+ printf ("s[%s] = 0x%02x;", reg_name[3], OP_VAL_8(3)&0xf);
+ } else {
+ if(OP_VAL_8(1)&0x80)
+ printf ("s[%s] = r[0x%02x];", reg_name[1], OP_VAL_8(1)&0xf);
+ if(OP_VAL_8(2)&0x80)
+ printf ("s[%s] = r[0x%02x];", reg_name[2], OP_VAL_8(2)&0xf);
+ if(OP_VAL_8(3)&0x80)
+ printf ("s[%s] = r[0x%02x];", reg_name[3], OP_VAL_8(3)&0xf);
+ }
+#endif
+ }
+ break;
+ case 2:
+ if( com.i_direct )
+ {
+ printf( "s[%s] = 0x%02x", ifo_reg[9], OP_VAL_16(0) );
+ }
+ else
+ {
+ printf( "s[%s] = r[0x%02x]", ifo_reg[9], OP_VAL_8(1)&0x0f );
+ }
+
+ printf( "s[%s] = (s[%s]&0x7FFF)|0x%02x",
+ ifo_reg[10], ifo_reg[10], OP_VAL_16(1)&0x8000);
+ break;
+ case 3:
+ if( com.i_direct )
+ {
+ printf( "r[0x%02x] = 0x%02x", OP_VAL_8(3)&0x0f, OP_VAL_16(0) );
+ }
+ else
+ {
+ printf ("r[r[0x%02x]] = r[0x%02x]",
+ OP_VAL_8(3)&0x0f, OP_VAL_8(1)&0x0f);
+ }
+ break;
+ case 4:
+ //actually only bits 00011100 00011100 are set
+ if( com.i_direct )
+ {
+ printf ("s[%s] = 0x%02x", ifo_reg[11], OP_VAL_16(1));
+ }
+ else
+ {
+ printf ("s[%s] = r[0x%02x]", ifo_reg[11], OP_VAL_8(3)&0x0f );
+ }
+ break;
+ case 6:
+ //actually,
+ //s[%s]=(r[%s]&0x3FF) | (0x%02x << 0xA);
+ //but it is way too ugly
+ if( com.i_direct )
+ {
+ printf( "s[%s] = 0x%02x", ifo_reg[8], OP_VAL_8(2)>>2 );
+ }
+ else
+ {
+ printf( "s[%s] = r[0x%02x]", ifo_reg[8], OP_VAL_8(3)&0x0f );
+ }
+ break;
+ default:
+ printf ("unknown");
+ }
+}
+
+static void IfoSet( ifo_command_t com )
+{
+ IfoRegister( OP_VAL_16(0), 0 );
+ printf( " %s ", IfoMath( com.i_cmd ) );
+ IfoRegister( OP_VAL_16(1), com.i_direct );
}
/*****************************************************************************
- * IfoLnk
+ * CommandRead : translates the command strings in ifo into command
+ * structures.
*****************************************************************************/
-static void IfoLnk( ifo_t* p_ifo )
+void CommandRead( ifo_command_t com )
{
+ u8* pi_code = (u8*)(&com);
+
+ switch( com.i_type )
+ {
+ /* Goto */
+ case 0:
+ /* Main command */
+ if( !pi_code[1] )
+ {
+ printf( "NOP\n" );
+ }
+ else
+ {
+ if( com.i_cmp )
+ {
+ printf ("if (r[0x%02x] %s ", OP_VAL_8(1)&0x0f,
+ ifo_cmp[com.i_cmp]);
+ IfoRegister (OP_VAL_16(1), com.i_dir_cmp);
+ printf (") ");
+ }
+
+ /* Sub command */
+ switch( com.i_sub_cmd )
+ {
+ case 1:
+ printf( "goto Line 0x%02x", OP_VAL_16(2) );
+ break;
+
+ case 2:
+ printf( "stop VM" );
+ break;
+
+ case 3:
+ printf( "Set Parental Level To %s and goto Line 0x%02x",
+ ifo_parental[OP_VAL_8(4)&0x7],
+ OP_VAL_8(5) );
+ break;
+
+ default:
+ printf( "Illegal" );
+ break;
+ }
+ }
+ break;
+
+ /* Lnk */
+ case 1:
+ /* Main command */
+ if( !pi_code[1] )
+ {
+ printf( "NOP\n" );
+ }
+ else
+ {
+ if( com.i_direct )
+ {
+ if( com.i_cmp )
+ {
+ printf( "if (r[0x%02x] %s ", OP_VAL_8(4)&0x0f,
+ ifo_cmp[com.i_cmp] );
+ IfoRegister( OP_VAL_8(5), 0 );
+ printf( ") " );
+ }
+
+ /* Sub command */
+ IfoJmp( com );
+ }
+ else
+ {
+ if( com.i_cmp )
+ {
+ printf( "if (r[0x%02x] %s ", OP_VAL_8(1)&0x0f,
+ ifo_cmp[com.i_cmp] );
+ IfoRegister( OP_VAL_16(1), com.i_dir_cmp );
+ printf( ") " );
+ }
+
+ /* Sub command */
+ IfoLnk( com );
+ }
+ }
+ break;
+
+ /* SetSystem */
+ case 2:
+ if( !pi_code[1] )
+ {
+ IfoSetSystem( com );
+ }
+ else if( com.i_cmp && !com.i_sub_cmd )
+ {
+ printf ("if (r[0x%02x] %s ", OP_VAL_8(4)&0x0f, ifo_cmp[com.i_cmp]);
+ IfoRegister( OP_VAL_8(5), 0 );
+ printf (") ");
+ IfoSetSystem( com );
+ }
+ else if( !com.i_cmp && com.i_sub_cmd )
+ {
+ printf( "if (" );
+ IfoSetSystem( com );
+ printf( ") " );
+ IfoLnk( com );
+ }
+ else
+ {
+ printf("nop");
+ }
+ break;
+
+ /* Set */
+ case 3:
+ if( ! pi_code[1] )
+ {
+ IfoSet( com );
+ }
+ else if( com.i_cmp && !com.i_sub_cmd )
+ {
+ printf ("if (r[0x%02x] %s ", OP_VAL_8(0)&0x0f, ifo_cmp[com.i_cmp]);
+ IfoRegister( OP_VAL_16(2), com.i_dir_cmp );
+ printf (") ");
+ IfoSet( com );
+ }
+ else if( !com.i_cmp && com.i_sub_cmd )
+ {
+ printf ("if (");
+ IfoSet( com );
+ printf (") ");
+ IfoLnk( com );
+ }
+ else
+ {
+ printf( "nop" );
+ }
+ break;
+
+ /*
+ * math command on r[opcode[1]] and
+ * direct?be2me_16(OP_VAL_8(0)):reg[OP_VAL_8(1)] is executed
+ * ( unless command is swap; then r[opcode[1]] and r[OP_VAL_8(1)]
+ * are swapped )
+ * boolean operation cmp on r[opcode[1]] and
+ * dir_cmp?be2me_16(OP_VAL_8(1)[1]):reg[OP_VAL_8(3)] is executed
+ * on true result, buttons(c[6], c[7]) is called
+ * problem is 'what is buttons()'
+ */
+ case 4:
+ printf( "r[0x%X] ", pi_code[1] );
+ printf( " %s ", IfoMath( com.i_cmd ) );
+ if( com.i_cmd == 2 )
+ {
+ printf( "r[0x%X] ", OP_VAL_8(1) );
+ }
+ else
+ {
+ IfoRegister( OP_VAL_16(0), com.i_direct );
+ }
+ printf("; ");
+
+ printf( "if ( r[%d] %s ", pi_code[1], ifo_cmp[com.i_cmp] );
+ IfoRegister( OP_VAL_8(1), com.i_dir_cmp );
+ printf( " ) then {" );
+ IfoAdvanced( &OP_VAL_8(4) );
+ printf( "}" );
+ break;
+
+ /*
+ * opposite to case 4: boolean, math and buttons.
+ */
+ case 5:
+ case 6:
+ printf("if (");
+
+ if( !com.i_direct && com.i_dir_cmp )
+ {
+ printf( "0x%X", OP_VAL_16(1) );
+ }
+ else
+ {
+ IfoRegister( OP_VAL_8(3), 0 );
+ if( OP_VAL_8(3)&0x80 )
+ {
+ printf( "s[%s]", ifo_reg[OP_VAL_8(3)&0x1F] );
+ }
+ else
+ {
+ printf( "r[0x%X]", OP_VAL_8(3)&0x1F);
+ // 0x1F is either not a mistake,
+ // or Microsoft programmer's mistake!!!
+ }
+ }
+
+ printf( " %s r[0x%X] ", ifo_cmp[com.i_cmp],
+ com.i_direct ? OP_VAL_8(2) : OP_VAL_8(1) );
+ printf( " ) then {" );
+ printf( "r[0x%X] ", pi_code[1] & 0xF );
+ printf( " %s ", IfoMath( com.i_cmd ) );
+
+ if( com.i_cmd == 0x02 ) // swap
+ {
+ printf("r[0x%X] ", OP_VAL_8(0)&0x1F);
+ }
+ else
+ {
+ if( com.i_direct )
+ {
+ printf( "0x%X", OP_VAL_16(0) );
+ }
+ else
+ {
+ if( OP_VAL_8(0) & 0x80 )
+ {
+ printf("s[%s]", ifo_reg[OP_VAL_8(0) & 0x1F] );
+ }
+ else
+ {
+ printf("r[0x%X]", OP_VAL_8(0) & 0x1F );
+ }
+ }
+ }
+
+ printf("; ");
+ IfoAdvanced( &OP_VAL_8(4) );
+ printf("}");
+
+ break;
+
+ default:
+ printf( "Unknown Command\n" );
+ break;
+ }
+
return;
}
/*****************************************************************************
- * IfoJmp
+ * CommandPrint : print in clear text (I hope so !) what a command does
*****************************************************************************/
-static void IfoJmp( ifo_t* p_ifo )
+void CommandPrint( ifo_t ifo )
{
return;
}
+
#endif