📄 ifo_read.c
字号:
free(cmd_tbl->pre_cmds);
return 0;
}
}
if(cmd_tbl->nr_of_post != 0) {
unsigned int post_cmds_size = cmd_tbl->nr_of_post * COMMAND_DATA_SIZE;
cmd_tbl->post_cmds = (vm_cmd_t *)malloc(post_cmds_size);
if(!cmd_tbl->post_cmds) {
if(cmd_tbl->pre_cmds)
free(cmd_tbl->pre_cmds);
return 0;
}
if(!(DVDReadBytes(ifofile->file, cmd_tbl->post_cmds, post_cmds_size))) {
if(cmd_tbl->pre_cmds)
free(cmd_tbl->pre_cmds);
free(cmd_tbl->post_cmds);
return 0;
}
}
if(cmd_tbl->nr_of_cell != 0) {
unsigned int cell_cmds_size = cmd_tbl->nr_of_cell * COMMAND_DATA_SIZE;
cmd_tbl->cell_cmds = (vm_cmd_t *)malloc(cell_cmds_size);
if(!cmd_tbl->cell_cmds) {
if(cmd_tbl->pre_cmds)
free(cmd_tbl->pre_cmds);
if(cmd_tbl->post_cmds)
free(cmd_tbl->post_cmds);
return 0;
}
if(!(DVDReadBytes(ifofile->file, cmd_tbl->cell_cmds, cell_cmds_size))) {
if(cmd_tbl->pre_cmds)
free(cmd_tbl->pre_cmds);
if(cmd_tbl->post_cmds)
free(cmd_tbl->post_cmds);
free(cmd_tbl->cell_cmds);
return 0;
}
}
/*
* Make a run over all the commands and see that we can interpret them all?
*/
return 1;
}
static void ifoFree_PGC_COMMAND_TBL(pgc_command_tbl_t *cmd_tbl) {
if(cmd_tbl) {
if(cmd_tbl->nr_of_pre && cmd_tbl->pre_cmds)
free(cmd_tbl->pre_cmds);
if(cmd_tbl->nr_of_post && cmd_tbl->post_cmds)
free(cmd_tbl->post_cmds);
if(cmd_tbl->nr_of_cell && cmd_tbl->cell_cmds)
free(cmd_tbl->cell_cmds);
free(cmd_tbl);
}
}
static int ifoRead_PGC_PROGRAM_MAP(ifo_handle_t *ifofile,
pgc_program_map_t *program_map,
unsigned int nr, unsigned int offset) {
unsigned int size = nr * sizeof(pgc_program_map_t);
if(!DVDFileSeek_(ifofile->file, offset))
return 0;
if(!(DVDReadBytes(ifofile->file, program_map, size)))
return 0;
return 1;
}
static int ifoRead_CELL_PLAYBACK_TBL(ifo_handle_t *ifofile,
cell_playback_t *cell_playback,
unsigned int nr, unsigned int offset) {
unsigned int i;
unsigned int size = nr * sizeof(cell_playback_t);
if(!DVDFileSeek_(ifofile->file, offset))
return 0;
if(!(DVDReadBytes(ifofile->file, cell_playback, size)))
return 0;
for(i = 0; i < nr; i++) {
B2N_32(cell_playback[i].first_sector);
B2N_32(cell_playback[i].first_ilvu_end_sector);
B2N_32(cell_playback[i].last_vobu_start_sector);
B2N_32(cell_playback[i].last_sector);
/* Changed < to <= because this was false in the movie 'Pi'. */
CHECK_VALUE(cell_playback[i].last_vobu_start_sector <=
cell_playback[i].last_sector);
CHECK_VALUE(cell_playback[i].first_sector <=
cell_playback[i].last_vobu_start_sector);
}
return 1;
}
static int ifoRead_CELL_POSITION_TBL(ifo_handle_t *ifofile,
cell_position_t *cell_position,
unsigned int nr, unsigned int offset) {
unsigned int i;
unsigned int size = nr * sizeof(cell_position_t);
if(!DVDFileSeek_(ifofile->file, offset))
return 0;
if(!(DVDReadBytes(ifofile->file, cell_position, size)))
return 0;
for(i = 0; i < nr; i++) {
B2N_16(cell_position[i].vob_id_nr);
CHECK_ZERO(cell_position[i].zero_1);
}
return 1;
}
static int ifoRead_PGC(ifo_handle_t *ifofile, pgc_t *pgc, unsigned int offset) {
unsigned int i;
if(!DVDFileSeek_(ifofile->file, offset))
return 0;
if(!(DVDReadBytes(ifofile->file, pgc, PGC_SIZE)))
return 0;
B2N_16(pgc->next_pgc_nr);
B2N_16(pgc->prev_pgc_nr);
B2N_16(pgc->goup_pgc_nr);
B2N_16(pgc->command_tbl_offset);
B2N_16(pgc->program_map_offset);
B2N_16(pgc->cell_playback_offset);
B2N_16(pgc->cell_position_offset);
for(i = 0; i < 8; i++)
B2N_16(pgc->audio_control[i]);
for(i = 0; i < 32; i++)
B2N_32(pgc->subp_control[i]);
for(i = 0; i < 16; i++)
B2N_32(pgc->palette[i]);
CHECK_ZERO(pgc->zero_1);
CHECK_VALUE(pgc->nr_of_programs <= pgc->nr_of_cells);
/* verify time (look at print_time) */
for(i = 0; i < 8; i++)
if(!pgc->audio_control[i] & 0x8000) /* The 'is present' bit */
CHECK_ZERO(pgc->audio_control[i]);
for(i = 0; i < 32; i++)
if(!pgc->subp_control[i] & 0x80000000) /* The 'is present' bit */
CHECK_ZERO(pgc->subp_control[i]);
/* Check that time is 0:0:0:0 also if nr_of_programs == 0 */
if(pgc->nr_of_programs == 0) {
CHECK_ZERO(pgc->still_time);
CHECK_ZERO(pgc->pg_playback_mode); // ??
CHECK_VALUE(pgc->program_map_offset == 0);
CHECK_VALUE(pgc->cell_playback_offset == 0);
CHECK_VALUE(pgc->cell_position_offset == 0);
} else {
CHECK_VALUE(pgc->program_map_offset != 0);
CHECK_VALUE(pgc->cell_playback_offset != 0);
CHECK_VALUE(pgc->cell_position_offset != 0);
}
if(pgc->command_tbl_offset != 0) {
pgc->command_tbl = malloc(sizeof(pgc_command_tbl_t));
if(!pgc->command_tbl)
return 0;
if(!ifoRead_PGC_COMMAND_TBL(ifofile, pgc->command_tbl,
offset + pgc->command_tbl_offset)) {
free(pgc->command_tbl);
return 0;
}
} else {
pgc->command_tbl = NULL;
}
if(pgc->program_map_offset != 0) {
pgc->program_map = malloc(pgc->nr_of_programs * sizeof(pgc_program_map_t));
if(!pgc->program_map) {
ifoFree_PGC_COMMAND_TBL(pgc->command_tbl);
return 0;
}
if(!ifoRead_PGC_PROGRAM_MAP(ifofile, pgc->program_map,pgc->nr_of_programs,
offset + pgc->program_map_offset)) {
ifoFree_PGC_COMMAND_TBL(pgc->command_tbl);
free(pgc->program_map);
return 0;
}
} else {
pgc->program_map = NULL;
}
if(pgc->cell_playback_offset != 0) {
pgc->cell_playback = malloc(pgc->nr_of_cells * sizeof(cell_playback_t));
if(!pgc->cell_playback) {
ifoFree_PGC_COMMAND_TBL(pgc->command_tbl);
if(pgc->program_map)
free(pgc->program_map);
return 0;
}
if(!ifoRead_CELL_PLAYBACK_TBL(ifofile, pgc->cell_playback,
pgc->nr_of_cells,
offset + pgc->cell_playback_offset)) {
ifoFree_PGC_COMMAND_TBL(pgc->command_tbl);
if(pgc->program_map)
free(pgc->program_map);
free(pgc->cell_playback);
return 0;
}
} else {
pgc->cell_playback = NULL;
}
if(pgc->cell_position_offset != 0) {
pgc->cell_position = malloc(pgc->nr_of_cells * sizeof(cell_position_t));
if(!pgc->cell_position) {
ifoFree_PGC(pgc);
return 0;
}
if(!ifoRead_CELL_POSITION_TBL(ifofile, pgc->cell_position,
pgc->nr_of_cells,
offset + pgc->cell_position_offset)) {
ifoFree_PGC(pgc);
return 0;
}
} else {
pgc->cell_position = NULL;
}
return 1;
}
int ifoRead_FP_PGC(ifo_handle_t *ifofile) {
if(!ifofile)
return 0;
if(!ifofile->vmgi_mat)
return 0;
/* It seems that first_play_pgc is optional after all. */
ifofile->first_play_pgc = 0;
if(ifofile->vmgi_mat->first_play_pgc == 0)
return 1;
ifofile->first_play_pgc = (pgc_t *)malloc(sizeof(pgc_t));
if(!ifofile->first_play_pgc)
return 0;
if(!ifoRead_PGC(ifofile, ifofile->first_play_pgc,
ifofile->vmgi_mat->first_play_pgc)) {
free(ifofile->first_play_pgc);
ifofile->first_play_pgc = 0;
return 0;
}
return 1;
}
static void ifoFree_PGC(pgc_t *pgc) {
if(pgc) {
ifoFree_PGC_COMMAND_TBL(pgc->command_tbl);
if(pgc->program_map)
free(pgc->program_map);
if(pgc->cell_playback)
free(pgc->cell_playback);
if(pgc->cell_position)
free(pgc->cell_position);
}
}
void ifoFree_FP_PGC(ifo_handle_t *ifofile) {
if(!ifofile)
return;
if(ifofile->first_play_pgc) {
ifoFree_PGC(ifofile->first_play_pgc);
free(ifofile->first_play_pgc);
ifofile->first_play_pgc = 0;
}
}
int ifoRead_TT_SRPT(ifo_handle_t *ifofile) {
tt_srpt_t *tt_srpt;
int i, info_length;
if(!ifofile)
return 0;
if(!ifofile->vmgi_mat)
return 0;
if(ifofile->vmgi_mat->tt_srpt == 0) /* mandatory */
return 0;
if(!DVDFileSeek_(ifofile->file, ifofile->vmgi_mat->tt_srpt * DVD_BLOCK_LEN))
return 0;
tt_srpt = (tt_srpt_t *)malloc(sizeof(tt_srpt_t));
if(!tt_srpt)
return 0;
ifofile->tt_srpt = tt_srpt;
if(!(DVDReadBytes(ifofile->file, tt_srpt, TT_SRPT_SIZE))) {
fprintf(stderr, "libdvdread: Unable to read read TT_SRPT.\n");
free(tt_srpt);
return 0;
}
B2N_16(tt_srpt->nr_of_srpts);
B2N_32(tt_srpt->last_byte);
info_length = tt_srpt->last_byte + 1 - TT_SRPT_SIZE;
tt_srpt->title = (title_info_t *)malloc(info_length);
if(!tt_srpt->title) {
free(tt_srpt);
ifofile->tt_srpt = 0;
return 0;
}
if(!(DVDReadBytes(ifofile->file, tt_srpt->title, info_length))) {
fprintf(stderr, "libdvdread: Unable to read read TT_SRPT.\n");
ifoFree_TT_SRPT(ifofile);
return 0;
}
for(i = 0; i < tt_srpt->nr_of_srpts; i++) {
B2N_16(tt_srpt->title[i].nr_of_ptts);
B2N_16(tt_srpt->title[i].parental_id);
B2N_32(tt_srpt->title[i].title_set_sector);
}
CHECK_ZERO(tt_srpt->zero_1);
CHECK_VALUE(tt_srpt->nr_of_srpts != 0);
CHECK_VALUE(tt_srpt->nr_of_srpts < 100); // ??
CHECK_VALUE((int)( tt_srpt->nr_of_srpts * sizeof(title_info_t)) <= (int)info_length);
for(i = 0; i < tt_srpt->nr_of_srpts; i++) {
CHECK_VALUE(tt_srpt->title[i].pb_ty.zero_1 == 0);
CHECK_VALUE(tt_srpt->title[i].nr_of_angles != 0);
CHECK_VALUE(tt_srpt->title[i].nr_of_angles < 10);
//CHECK_VALUE(tt_srpt->title[i].nr_of_ptts != 0);
// XXX: this assertion breaks Ghostbusters:
CHECK_VALUE(tt_srpt->title[i].nr_of_ptts < 1000); // ??
CHECK_VALUE(tt_srpt->title[i].title_set_nr != 0);
CHECK_VALUE(tt_srpt->title[i].title_set_nr < 100); // ??
CHECK_VALUE(tt_srpt->title[i].vts_ttn != 0);
CHECK_VALUE(tt_srpt->title[i].vts_ttn < 100); // ??
//CHECK_VALUE(tt_srpt->title[i].title_set_sector != 0);
}
// Make this a function
#if 0
if(memcmp((uint8_t *)tt_srpt->title +
tt_srpt->nr_of_srpts * sizeof(title_info_t),
my_friendly_zeros,
info_length - tt_srpt->nr_of_srpts * sizeof(title_info_t))) {
fprintf(stderr, "VMG_PTT_SRPT slack is != 0, ");
hexdump((uint8_t *)tt_srpt->title +
tt_srpt->nr_of_srpts * sizeof(title_info_t),
info_length - tt_srpt->nr_of_srpts * sizeof(title_info_t));
}
#endif
return 1;
}
void ifoFree_TT_SRPT(ifo_handle_t *ifofile) {
if(!ifofile)
return;
if(ifofile->tt_srpt) {
free(ifofile->tt_srpt->title);
free(ifofile->tt_srpt);
ifofile->tt_srpt = 0;
}
}
int ifoRead_VTS_PTT_SRPT(ifo_handle_t *ifofile) {
vts_ptt_srpt_t *vts_ptt_srpt;
int info_length, i, j;
uint32_t *data;
if(!ifofile)
return 0;
if(!ifofile->vtsi_mat)
return 0;
if(ifofile->vtsi_mat->vts_ptt_srpt == 0) /* mandatory */
return 0;
if(!DVDFileSeek_(ifofile->file,
ifofile->vtsi_mat->vts_ptt_srpt * DVD_BLOCK_LEN))
return 0;
vts_ptt_srpt = (vts_ptt_srpt_t *)malloc(sizeof(vts_ptt_srpt_t));
if(!vts_ptt_srpt)
return 0;
ifofile->vts_ptt_srpt = vts_ptt_srpt;
if(!(DVDReadBytes(ifofile->file, vts_ptt_srpt, VTS_PTT_SRPT_SIZE))) {
fprintf(stderr, "libdvdread: Unable to read PTT search table.\n");
free(vts_ptt_srpt);
return 0;
}
B2N_16(vts_ptt_srpt->nr_of_srpts);
B2N_32(vts_ptt_srpt->last_byte);
CHECK_ZERO(vts_ptt_srpt->zero_1);
CHECK_VALUE(vts_ptt_srpt->nr_of_srpts != 0);
CHECK_VALUE(vts_ptt_srpt->nr_of_srpts < 100); // ??
info_length = vts_ptt_srpt->last_byte + 1 - VTS_PTT_SRPT_SIZE;
data = (uint32_t *)malloc(info_length);
if(!data) {
free(vts_ptt_srpt);
ifofile->vts_ptt_srpt = 0;
return 0;
}
if(!(DVDReadBytes(ifofile->file, data, info_length))) {
fprintf(stderr, "libdvdread: Unable to read PTT search table.\n");
free(vts_ptt_srpt);
free(data);
ifofile->vts_ptt_srpt = 0;
return 0;
}
for(i = 0; i < vts_ptt_srpt->nr_of_srpts; i++) {
B2N_32(data[i]);
/* assert(data[i] + sizeof(ptt_info_t) <= vts_ptt_srpt->last_byte + 1);
Magic Knight Rayearth Daybreak is mastered very strange and has
Titles with 0 PTTs. They all have a data[i] offsets beyond the end of
of the vts_ptt_srpt structure. */
CHECK_VALUE(data[i] + sizeof(ptt_info_t) <= vts_ptt_srpt->last_byte + 1 + 4);
}
vts_ptt_srpt->ttu_offset = data;
vts_ptt_srpt->title = malloc(vts_ptt_srpt->nr_of_srpts * sizeof(ttu_t));
if(!vts_ptt_srpt->title) {
free(vts_ptt_srpt);
free(data);
ifofile->vts_ptt_srpt = 0;
return 0;
}
for(i = 0; i < vts_ptt_srpt->nr_of_srpts; i++) {
int n;
if(i < vts_ptt_srpt->nr_of_srpts - 1)
n = (data[i+1] - data[i]);
else
n = (vts_ptt_srpt->last_byte + 1 - data[i]);
/* assert(n > 0 && (n % 4) == 0);
Magic Knight Rayearth Daybreak is mastered very strange and has
Titles with 0 PTTs. */
if(n < 0) n = 0;
CHECK_VALUE(n % 4 == 0);
vts_ptt_srpt->title[i].nr_of_ptts = n / 4;
vts_ptt_srpt->title[i].ptt = malloc(n * sizeof(ptt_info_t));
if(!vts_ptt_srpt->title[i].ptt) {
for(n = 0; n < i; n++)
free(vts_ptt_srpt->title[n].ptt);
free(vts_ptt_srpt);
free(data);
ifofile->vts_ptt_srpt = 0;
return 0;
}
for(j = 0; j < vts_ptt_srpt->title[i].nr_of_ptts; j++) {
/* The assert placed here because of Magic Knight Rayearth Daybreak */
CHECK_VALUE(data[i] + sizeof(ptt_info_t) <= vts_ptt_srpt->last_byte + 1);
vts_ptt_srpt->title[i].ptt[j].pgcn
= *(uint16_t*)(((char *)data) + data[i] + 4*j - VTS_PTT_SRPT_SIZE);
vts_ptt_srpt->title[i].ptt[j].pgn
= *(uint16_t*)(((char *)data) + data[i] + 4*j + 2 - VTS_PTT_SRPT_SIZE);
}
}
for(i = 0; i < vts_ptt_srpt->nr_of_srpts; i++) {
for(j = 0; j < vts_ptt_srpt->title[i].nr_of_ptts; j++) {
B2N_16(vts_ptt_srpt->title[i].ptt[j].pgcn);
B2N_16(vts_ptt_srpt->title[i].ptt[j].pgn);
}
}
for(i = 0; i < vts_ptt_srpt->nr_of_srpts; i++) {
CHECK_VALUE(vts_ptt_srpt->title[i].nr_of_ptts < 1000); // ??
for(j = 0; j < vts_ptt_srpt->title[i].nr_of_ptts; j++) {
CHECK_VALUE(vts_ptt_srpt->title[i].ptt[j].pgcn != 0 );
CHECK_VALUE(vts_ptt_srpt->title[i].ptt[j].pgcn < 1000); // ??
CHECK_VALUE(vts_ptt_srpt->title[i].ptt[j].pgn != 0);
CHECK_VALUE(vts_ptt_srpt->title[i].ptt[j].pgn < 100); // ??
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -