📄 vm.c
字号:
/* Ogle - A video player * Copyright (C) 2000, 2001 H錵an 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 * (at your option) any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA */#include <stdio.h>#include <string.h>#include <stdlib.h>#include <unistd.h>#include <inttypes.h>#include <assert.h>#include "ogle/dvd.h"#include "ogle/dvdevents.h"#include "ogle/msgevents.h"#include <dvdread/ifo_types.h>#include <dvdread/ifo_read.h>#include "decoder.h"#include "vmcmd.h"#include "vm.h"#include "vm_serialize.h"#include "debug_print.h"static dvd_reader_t *dvd;static ifo_handle_t *vmgi;static ifo_handle_t *vtsi;dvd_state_t state;unsigned char discid[16];/* Local prototypes */static void saveRSMinfo(int cellN, int blockN);static int update_PGN(void);static int next_PG(link_t *link_values);static int prev_PG(link_t *link_values);static link_t play_PGC(void);static link_t play_PG(void);static link_t play_Cell(void);static link_t play_Cell_post(void);static link_t play_PGC_post(void);static link_t process_command(link_t link_values);static void ifoOpenNewVTSI(dvd_reader_t *dvd, int vtsN);static pgcit_t* get_PGCIT(void);static int get_video_aspect(void);/* Can only be called when in VTS_DOMAIN */static int get_TT(int tt);static int get_VTS_TT(int vtsN, int vts_ttn);static int get_TT_PTT(int tt, int ptt);static int get_VTS_PTT(int vtsN, int vts_ttn, int part);/* Could add code so that it's callable in menus too... */static int get_cellN_for_vobu(uint32_t vobu_addr);static int get_MENU(int menu); // VTSM & VMGMstatic int get_FP_PGC(void); // FP/* Called in any domain */static int get_ID(int id);static int get_PGC(int pgcN);static int get_PGCN(void);char *vm_get_state_str(int blockN){ dvd_state_t save_state; char *state_str = NULL; save_state = state; save_state.blockN = blockN; save_state.pgcN = get_PGCN(); state_str = vm_serialize_dvd_state(&save_state); return state_str;}int vm_set_state_str(char *state_str){ dvd_state_t save_state; if(state_str == NULL) { return 0; } if(!vm_deserialize_dvd_state(state_str, &save_state)) { WARNING("%s", "state_str wrong\n"); return 0; } //reads: state.vtsN (if vtsN == state.vtsN) do nothing //writes: state.vtsN ifoOpenNewVTSI(dvd, save_state.vtsN); // sets state.vtsN state = save_state; /* set state.domain before calling */ //calls get_pgcit() // needs state.domain and sprm[0] set // sets pgcit depending on state.domain //writes: state.pgc // state.pgN // state.TT_PGCN_REG get_PGC(save_state.pgcN); save_state.pgc = state.pgc; /* set the rest of state after the call */ state = save_state; return 1;}int set_sprm(unsigned int nr, uint16_t val){ if(nr > 23) { return 0; } state.registers.SPRM[nr] = val; return 1;}int vm_reset(void) // , register_t regs){ // Setup State memset(state.registers.SPRM, 0, sizeof(uint16_t)*24); memset(state.registers.GPRM, 0, sizeof(state.registers.GPRM)); state.registers.SPRM[0] = ('e'<<8)|'n'; // Player Menu Languange code state.AST_REG = 0; // 15 why? state.SPST_REG = 0; // 62 why? state.AGL_REG = 1; state.TTN_REG = 1; state.VTS_TTN_REG = 1; //state.TT_PGCN_REG = 0 state.PTTN_REG = 1; state.HL_BTNN_REG = 1 << 10; state.PTL_REG = 15; // Parental Level state.registers.SPRM[12] = ('U'<<8)|'S'; // Parental Management Country Code state.registers.SPRM[16] = ('e'<<8)|'n'; // Initial Language Code for Audio state.registers.SPRM[18] = ('e'<<8)|'n'; // Initial Language Code for Spu state.registers.SPRM[20] = 1; // Player Regional Code (bit mask?) state.pgN = 0; state.cellN = 0; state.domain = FP_DOMAIN; state.rsm_vtsN = 0; state.rsm_cellN = 0; state.rsm_blockN = 0; state.vtsN = -1; state.mode = RESET_MODE; return 0;} int vm_init(char *dvdroot) // , register_t regs){ dvd = DVDOpen(dvdroot); if(!dvd) { ERROR("%s", "faild to open/read the DVD\n"); return -1; } if(DVDDiscID(dvd, discid) == -1) { memset(discid, 0, sizeof(discid)); } vmgi = ifoOpenVMGI(dvd); if(!vmgi) { ERROR("%s", "faild to read VIDEO_TS.IFO\n"); return -1; } if(!ifoRead_FP_PGC(vmgi)) { ERROR("%s", "ifoRead_FP_PGC faild\n"); return -1; } if(!ifoRead_TT_SRPT(vmgi)) { ERROR("%s", "ifoRead_TT_SRPT faild\n"); return -1; } if(!ifoRead_PGCI_UT(vmgi)) { ERROR("%s", "ifoRead_PGCI_UT faild\n"); return -1; } if(!ifoRead_PTL_MAIT(vmgi)) { ERROR("%s", "ifoRead_PTL_MAIT faild\n"); ; // return -1; Not really used for now.. } if(!ifoRead_VTS_ATRT(vmgi)) { ERROR("%s", "ifoRead_VTS_ATRT faild\n"); ; // return -1; Not really used for now.. } //ifoRead_TXTDT_MGI(vmgi); Not implemented yet return 0;}// FIXME TODO XXX $$$ Handle error condition too...int vm_start(void){ link_t link_values; // Set pgc to FP pgc get_FP_PGC(); link_values = play_PGC(); link_values = process_command(link_values); assert(link_values.command == PlayThis); state.blockN = link_values.data1; return 0; //??}int vm_eval_cmd(vm_cmd_t *cmd){ link_t link_values; if(vmEval_CMD(cmd, 1, &state.registers, &link_values)) { link_values = process_command(link_values); assert(link_values.command == PlayThis); state.blockN = link_values.data1; return 1; // Something changed, Jump } else { return 0; // It updated some state thats all... }}int vm_get_next_cell(void){ link_t link_values; link_values = play_Cell_post(); link_values = process_command(link_values); assert(link_values.command == PlayThis); state.blockN = link_values.data1; return 0; // ??}int vm_top_pg(void){ link_t link_values; link_values = play_PG(); link_values = process_command(link_values); assert(link_values.command == PlayThis); state.blockN = link_values.data1; return 1; // Jump}int vm_next_pg(void){ link_t link_values; if(next_PG(&link_values) == -1) return 0; // do nothing link_values = process_command(link_values); assert(link_values.command == PlayThis); state.blockN = link_values.data1; return 1; // Jump}int vm_prev_pg(void){ link_t link_values; if(prev_PG(&link_values) == -1) return 0; // do nothing link_values = process_command(link_values); assert(link_values.command == PlayThis); state.blockN = link_values.data1; return 1; // Jump}int vm_goup_pgc(void){ link_t link_values; if(get_PGC(state.pgc->goup_pgc_nr)) return 0; // do nothing link_values = play_PGC(); link_values = process_command(link_values); assert(link_values.command == PlayThis); state.blockN = link_values.data1; return 1; // Jump}int vm_jump_ptt(int pttN){ link_t link_values; //check domain!! should be only VTS Title domain if(get_VTS_PTT(state.vtsN, state.VTS_TTN_REG, pttN) == -1) return 0; link_values = play_PGC(); link_values = process_command(link_values); assert(link_values.command == PlayThis); state.blockN = link_values.data1; return 1; // Something changed, Jump}int vm_jump_title_ptt(int titleN, int pttN){ link_t link_values; //check domain?!? (VMGM & (Menu) Title & Stop)? if(get_TT_PTT(titleN, pttN) == -1) return 0; link_values = play_PGC(); link_values = process_command(link_values); assert(link_values.command == PlayThis); state.blockN = link_values.data1; return 1; // Something changed, Jump}int vm_jump_title(int titleN){ link_t link_values; //check domain? VMGM & (Menu) Title & Stop if(get_TT(titleN) == -1) return 0; link_values = play_PGC(); link_values = process_command(link_values); assert(link_values.command == PlayThis); state.blockN = link_values.data1; return 1; // Something changed, Jump}static domain_t menuid2domain(DVDMenuID_t menuid){ domain_t result = VTSM_DOMAIN; // Really shouldn't have to.. switch(menuid) { case DVD_MENU_Title: result = VMGM_DOMAIN; break; case DVD_MENU_Root: case DVD_MENU_Subpicture: case DVD_MENU_Audio: case DVD_MENU_Angle: case DVD_MENU_Part: result = VTSM_DOMAIN; break; } return result;}int vm_menu_call(DVDMenuID_t menuid, int block){ domain_t old_domain; link_t link_values; /* FIXME XXX $$$ How much state needs to be restored * when we fail to find a menu? */ old_domain = state.domain; switch(state.domain) { case VTS_DOMAIN: saveRSMinfo(0, block); /* FALL THROUGH */ case VTSM_DOMAIN: state.domain = menuid2domain(menuid); /* FALL THROUGH */ case VMGM_DOMAIN: /* or should one be able to jump from vmgm to title dom? */ if(get_PGCIT() != NULL && get_MENU(menuid) != -1) { link_values = play_PGC(); link_values = process_command(link_values); assert(link_values.command == PlayThis); state.blockN = link_values.data1; return 1; // Jump } else { state.domain = old_domain; } break; case FP_DOMAIN: /* FIXME XXX $$$ What should we do here? */ break; } return 0;}static int vm_resume_int(link_t *link_return){ int i; link_t link_values; if(state.domain == VTS_DOMAIN) { // Not allowed in the Titlte domain return 0; // Fail } // Check and see if there is any rsm info!! if(state.rsm_vtsN == 0) { return 0; // Fail } state.domain = VTS_DOMAIN; ifoOpenNewVTSI(dvd, state.rsm_vtsN); // FIXME check return value get_PGC(state.rsm_pgcN); // FIXME check return value /* These should never be set in SystemSpace and/or MenuSpace */ // state.TTN_REG = state.rsm_tt; // state.TT_PGCN_REG = state.rsm_pgcN; // state.HL_BTNN_REG = state.rsm_btnn; ?? for(i = 0; i < 5; i++) { state.registers.SPRM[4 + i] = state.rsm_regs[i]; } if(state.rsm_cellN == 0) { assert(state.cellN); // Checking if this ever happens /* assert( time/block/vobu is 0 ); */ state.pgN = 1; link_values = play_PG(); } else { /* assert( time/block/vobu is _not_ 0 ); */ /* play_Cell_at_time */ state.cellN = state.rsm_cellN; state.blockN = state.rsm_blockN; //state.pgN = ?? does this gets the righ value in play_Cell, no! if(update_PGN()) { /* Were at or past the end of the PGC, should not happen for a RSM */ assert(0); link_values = play_PGC_post(); } else { link_t do_nothing = { PlayThis, 0, 0, 0 };
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -