📄 vcd_con.cpp
字号:
}
else
{
error = 0xff;
}
errout:
if (TracksFile != 0)
{
LoaderFileClose(tLoader, TracksFile);
}
return (error);
}
VCD_VER find_vcd_type(char *vcd_dir, char *vcd_ext)
{
BYTE bVCD = 1;
BYTE bSVCD = 1;
BYTE bHQVCD = 1;
if (LoaderFileAccess(tLoader, "/mnt/cdrom/vcd", LOADER_FILE_ACCESS_EXIST, &bVCD) != LOADER_SUCCESS)
{
DbgPrint(("%s:%u - ERROR", __FILE__, __LINE__));
return(VCD_VER_UNKNOWN);
}
if (LoaderFileAccess(tLoader, "/mnt/cdrom/hqvcd", LOADER_FILE_ACCESS_EXIST, &bHQVCD) != LOADER_SUCCESS)
{
DbgPrint(("%s:%u - ERROR", __FILE__, __LINE__));
return(VCD_VER_UNKNOWN);
}
if (LoaderFileAccess(tLoader, "/mnt/cdrom/svcd", LOADER_FILE_ACCESS_EXIST, &bSVCD) != LOADER_SUCCESS)
{
DbgPrint(("%s:%u - ERROR", __FILE__, __LINE__));
return(VCD_VER_UNKNOWN);
}
if (bVCD)
{
DBGPRINT(DBG_ON(DBG_TRACE), ("IT'S A VCD\n"));
strncpy(vcd_dir, "vcd\0", 4);
strncpy(vcd_ext, "vcd\0", 4);
return(VCD_VER_VCD);
}
else if (bHQVCD)
{
DBGPRINT(DBG_ON(DBG_TRACE), ("IT'S AN HQVCD\n"));
strncpy(vcd_dir, "hqvcd\0", 6);
strncpy(vcd_ext, "vcd\0", 4);
return(VCD_VER_HQVCD);
}
else if (bSVCD)
{
DBGPRINT(DBG_ON(DBG_TRACE), ("IT'S AN SVCD\n"));
strncpy(vcd_dir, "svcd\0", 5);
strncpy(vcd_ext, "svd\0", 4);
return(VCD_VER_SVCD);
}
return(VCD_VER_UNKNOWN);
}
/*************************************************
Function Name: get_vcd_info
Purpose: Loads and parses the INFO.VCD file.
Theory: Loads the INFO.VCD and ENTRIES.VCD
files and from that information dtermines
if it is a VCD 1.1, VCD 2.0, SVCD, or VCD
and takes appropriate action.
Arguments: none
Returns: error
*************************************************/
CHAR get_vcd_info(void)
{
UBYTE load_status;
char vcd_dir[10];
char vcd_ext[4];
VCD_VER vcd_type;
vcd_type = find_vcd_type(&vcd_dir[0], &vcd_ext[0]);
if (vcd_type == VCD_VER_UNKNOWN)
{
DBGPRINT(DBG_ON(DBG_ERROR), ("VCD type is UNKNOWN\n"));
return(-1);
}
load_status = load_vcd_info(vcd_dir, vcd_ext);
if (load_status == 0xff)
{
return(-1);
}
load_status = load_vcd_entry(vcd_dir, vcd_ext);
if (load_status == 0xff)
{
return(-1);
}
DBGPRINT(DBG_ON(DBG_TRACE), ("$$$$$$$ - g_info_vcd.ver = 0x%X\n", g_info_vcd.ver));
VERSION_FLG = 1;
/* load tracks.svd if it's an svcd */
if (vcd_type == VCD_VER_SVCD)
{
load_status = load_tracks_svd();
if (load_status == 0xff)
{
return(-1);
}
DBGPRINT(DBG_ON(DBG_TRACE), ("g_tracks_svd.ver = 0x%X\n", g_tracks_svd.ver));
if ( (g_tracks_svd.ver == 0x0100) || (g_tracks_svd.ver == 0x7420) )/* 0x7420 is a CVD hack based on current info */
{
VERSION_FLG = 2;
}
}
if (vcd_type == VCD_VER_HQVCD)
{
VERSION_FLG = 2;
}
/* if it's a simple vcd (no psd) */
if ( ( (g_info_vcd.ver != 0x0200) && (VERSION_FLG == 1) ) || (g_info_vcd.psd_size == 0) )
{
if ( (g_info_vcd.ver == 0x0200) || (VERSION_FLG > 1) )
{
/* force it back into VCD 1.1 */
g_info_vcd.ver = 0x01F1;
}
goto simple_vcd;
}
/*
* it's (possibly) a vcd with menus (or an svcd or hqvcd) - parse these tables
*/
DBGPRINT(DBG_ON(DBG_TRACE), ("LOAD_LOT\n"));
load_status = load_vcd_lot(vcd_dir, vcd_ext);
if (load_status == 0xff)
{
/* force it back into VCD 1.1 */
g_info_vcd.ver = 0x01F1;
goto simple_vcd;
}
DBGPRINT(DBG_ON(DBG_TRACE), ("LOAD_PSD\n"));
load_status = load_vcd_psd(vcd_dir, vcd_ext);
if (load_status == 0xff)
{
/* force it back into VCD 1.1 */
g_info_vcd.ver = 0x01F1;
goto simple_vcd;
}
/* tables were successfully parsed - play using playlists */
DBGPRINT(DBG_ON(DBG_TRACE), ("$$$$$$ PSD VCD!\n"));
return (1);
simple_vcd:
DBGPRINT(DBG_ON(DBG_TRACE), ("$$$$$$ NO PSD!\n"));
return (0);
}
/*************************************************
Function Name: stop_on_error
Purpose: Stop all playback.
Theory: If an error happens during navigation
data loading, this will stop all
playback and put the system into a
STOP state.
Arguments: none
Returns: nothing
*************************************************/
void stop_on_error(void)
{
ULONG out_msg[4];
DBGPRINT(DBG_ON(DBG_TRACE), ("stop_on_error: ENTER\n"));
logo_display();
pbc_stop_com(); /* Stop Set */
out_msg[0] = VDVD_STATUS_STOP;
out_msg[1] = 2;
if (UsrEventHandler(out_msg) != USR_SUCCESS)
{
DbgPrint(("\nUsrEventHandler FAILURE, %s, %d\n\n", __FILE__, __LINE__));
}
}
/*************************************************
Function Name: pbc_apause
Purpose: Send a timeout message to the VCD task.
Theory: When the auto pause timer expires, this sends
a message to the VCD task to notify of a
timeout.
Arguments: none
Returns: nothing
*************************************************/
void pbc_apause(void)
{
ULONG msg[4];
DBGPRINT(DBG_ON(DBG_TRACE), ("pbc_apause: ENTER\n"));
msg[0] = MSG_TIM_OUT;
OS_MsgQSend(queue_vcd, (char *)&msg[0], VCD_MSG_SIZE, OS_NO_WAIT, OS_MSG_PRI_NORMAL);
}
/*************************************************
Function Name: msf_modify
Purpose: Perform a math operation on a MSF number.
Theory: MSF numbers have no strict base so to do
adds or subtracts we need to do some in
depth checking.
Arguments: MSF value, number to modify with, operation to
perform
Returns: new MSF value
*************************************************/
ULONG msf_modify(ULONG msf, ULONG num, UBYTE op)
{
UBYTE msf_arr[3], num_arr[3];
ULONG temp_num;
DBGPRINT(DBG_ON(DBG_TRACE), ("msf_modify: Perform a math operation on a MSF number\n"));
msf_arr[0] = com_bcdtobin( (UBYTE)((msf & 0xFF0000) >> 16) );
msf_arr[1] = com_bcdtobin( (UBYTE)((msf & 0xFF00) >> 8) );
msf_arr[2] = com_bcdtobin( (UBYTE)(msf & 0xFF) );
num_arr[0] = (UBYTE)(num / 4500);
temp_num = num - (num_arr[0] * 4500);
num_arr[1] = (UBYTE)(temp_num / 75);
temp_num = temp_num - (num_arr[1] * 75);
num_arr[2] = (UBYTE)(temp_num);
if (op == ADD_MSF)
{
msf_arr[2] += num_arr[2];
msf_arr[1] += num_arr[1];
msf_arr[0] += num_arr[0];
}
else
{
if (num_arr[2] > msf_arr[2])
{
if (msf_arr[1] > 0)
{
msf_arr[1]--;
msf_arr[2] += 75;
}
else
{
msf_arr[0]--;
msf_arr[1] += 59;
msf_arr[2] += 75;
}
}
msf_arr[2] -= num_arr[2];
if (num_arr[1] > msf_arr[1])
{
msf_arr[0]--;
msf_arr[1] += 60;
}
msf_arr[1] -= num_arr[1];
msf_arr[0] -= num_arr[0];
}
num_arr[2] = msf_arr[2] / 75;
if (num_arr[2])
{
msf_arr[1] += num_arr[2];
msf_arr[2] -= (num_arr[2] * 75);
}
num_arr[1] = msf_arr[1] / 60;
if (num_arr[1])
{
msf_arr[0] += num_arr[1];
msf_arr[1] -= (num_arr[1] * 60);
}
msf_arr[0] = com_bintobcd(msf_arr[0]);
msf_arr[1] = com_bintobcd(msf_arr[1]);
msf_arr[2] = com_bintobcd(msf_arr[2]);
return (combine_msf(&msf_arr[0]));
}
/*************************************************
Function Name: com_bcd_chk
Purpose: Check if valid BCD number
Theory: Looks at a BCD number to make sure
each nibble is not more than 0x9.
Arguments: BCD number
Returns: valid BCD number or not
*************************************************/
UBYTE com_bcd_chk(UBYTE bcd)
{
if ((bcd & 0x0F) > 9)
{
DBGPRINT(DBG_ON(DBG_TRACE), ("com_bcd_chk: INVALID!!!\n"));
return (0xff);
}
if (((bcd & 0x0F0) >> 4) > 9)
{
DBGPRINT(DBG_ON(DBG_TRACE), ("com_bcd_chk: INVALID!!!\n"));
return (0xff);
}
return (0);
}
/*************************************************
Function Name: vcdReadToc
Purpose: Read the VCD table of contents.
Arguments: none
Returns: 0 for success. otherwise for failure
*************************************************/
static int vcdReadToc(void)
{
#define LDR_BUF_SIZE 2048
LOADER_ERR err;
int entries;
int x;
ULONG tocsize;
BYTE first; /* first track no. */
BYTE last; /* last track no. */
BYTE last_track = 0; /* last track # */
BYTE bLdrBuffer[LDR_BUF_SIZE];
const BYTE TRACK_MAX = 99; /* maximum track number */
const BYTE SESS_MIN = 1; /* minimum session number */
const BYTE SESS_MAX = 40; /* maximum session number */
const BYTE FORMAT_TRK = 0x0; /* get track info - Mt.Fuji spec. Table 365 */
const BYTE FORMAT_SESS = 0x1; /* get session info */
const BYTE FORMAT_FULL = 0x2; /* get all info */
const BYTE TRK_DESC_SIZE = 10; /* in FORMAT_TRK each track descriptor returned is 10 bytes in size */
const BYTE SESS_DESC_SIZE = 10; /* in FORMAT_SESS each track descriptor returned is 10 bytes in size */
const BYTE FULL_DESC_SIZE = 11; /* in FORMAT_FULL each track descriptor returned is 11 bytes in size */
const BYTE READ_MSF = 0x2; /* Mt.Fuji spec. Table 364 byte 1, bit 1 */
const BYTE READ_LBN = 0x0; /* Mt.Fuji spec. Table 364 byte 1, bit 1 */
UNUSED_PARAM(SESS_MIN);
UNUSED_PARAM(SESS_MAX);
UNUSED_PARAM(FORMAT_TRK);
UNUSED_PARAM(FORMAT_SESS);
UNUSED_PARAM(FORMAT_FULL);
UNUSED_PARAM(TRK_DESC_SIZE);
UNUSED_PARAM(SESS_DESC_SIZE);
UNUSED_PARAM(READ_MSF);
UNUSED_PARAM(READ_LBN);
/* start by clearing the buffer */
memset(bLdrBuffer, 0, LDR_BUF_SIZE);
/* find the toc size */
err = LoaderGetTOC (tLoader, LOADER_TOC_CMD_FULL_TOC, 0, LOADER_TOC_MSF, bLdrBuffer, 4);
if (LOADER_SUCCESS != err)
{
DBGPRINT(DBG_ON(DBG_ERROR), ("LoaderGetTOC() - FAILURE reading TOC data\n"));
return (-1);
}
/* set and check track data for session #1 */
tocsize = MAKE_WORD(bLdrBuffer) + 2; /* data length not included so add 2 */
first = bLdrBuffer[2]; /* first complete session */
last = bLdrBuffer[3]; /* last complete session */
if (1 != first) /* No first session found */
{
DBGPRINT(DBG_ON(DBG_ERROR), ("LoaderGetTOC() - First Session Not Found\n"));
return (-1);
}
if (1 != last) /* multi-session disc */
{
DBGPRINT(DBG_ON(DBG_ERROR), ("LoaderGetTOC() - MULTI_SESSION DISC (%i sessions)\n", last - first + 1));
}
DBGPRINT(DBG_ON(DBG_TRACE), ("TOC DATA size = %i, first session = %i, last session = %i\n", tocsize, first, last));
/* get the data for all tracks */
err = LoaderGetTOC (tLoader, LOADER_TOC_CMD_FULL_TOC, 1, LOADER_TOC_MSF, bLdrBuffer, tocsize);
if (LOADER_SUCCESS != err)
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -