📄 pbc.cpp
字号:
}
}
else
{ /* Play Nothing */
ret = 0x0FFFF;
}
return (ret);
}
/*************************************************
Function Name: pbc_track_play
Purpose: Track play process.
Theory: Does the actual TOC parsing and issues
play command to drive based on track
number desired.
Arguments: none
Returns: Track number valid or invalid
*************************************************/
USHORT pbc_track_play(USHORT tno, USHORT ptime)
{
ULONG playtime, start, end, msg[4];
UBYTE bcd_tno;
DBGPRINT(DBG_ON(DBG_ALL),("pbc_track_play: TNO = %i, ptime = %i\n", tno, ptime ));
bcd_tno = com_bintobcd((UBYTE) tno);
if (com_tno_time_get(bcd_tno, &s_msf[0], &e_msf[0]) == OS_OK)
{
if ((cd_max_tno != cd_max_tno_cdda))
{
if (tno == cd_max_tno_cdda)
{
/* the CDDA tracks on a VCD 2.0 disc begin with a front margin of 375 sectors,
* this needs to be removed from the video play region */
end = msf_modify(combine_msf(&e_msf[0]), 375, SUBTRACT_MSF);
e_msf[0] = (UBYTE)((end & 0xFF0000) >> 16);
e_msf[1] = (UBYTE)((end & 0xFF00) >> 8);
e_msf[2] = (UBYTE)(end & 0xFF);
}
}
if (ptime != PLY_TIM_EOF)
{
start = com_tno_time_bcdtobin(&s_msf[0]);
playtime = (ULONG) ptime *5;
start += (playtime - 1);
com_tno_time_bintobcd(start, &e_msf[0]);
}
if (g_toc_info.tno[tno - 1].cont & TOC_CONTROL_FIELD_DATA_TRACK)
{
/* CD-ROM */
cdda_track = 0;
/* this is the usual path for vcd video playback */
pbc_fe_playcd_req(PLAY_SET_PLAY, 0, FEA_PLAY_CD_ABO, &s_msf[0], &e_msf[0]);
}
else
{ /* CD-DA Track */
cdda_track = 1;
pbc_fe_playcd_req(PLAY_SET_CDDA, 0, FEA_PLAY_CD_ABO, &s_msf[0], &e_msf[0]);
}
if (g_play_kind != PKIND_PLAY)
{
msg[0] = VDVD_STATUS_PLAY;
if (UsrEventHandler(msg) != USR_SUCCESS)
{
DbgPrint(("\nUsrEventHandler FAILURE, %s, %d\n\n", __FILE__, __LINE__));
}
}
g_play_kind = PKIND_PLAY;
pbc_mode = PBC_MODE_PLAY;
return (OS_OK);
}
return (0xffff);
}
/*************************************************
Function Name: pbc_entry_play
Purpose: Entry play process.
Theory: Determines the read length based on
entry and track number, and then issues
the read command to the drive.
Arguments: entry number, play time
Returns: valid entry number or not
*************************************************/
USHORT pbc_entry_play(USHORT entry, USHORT ptime)
{
UBYTE tno, i;
ULONG playtime, start;
if (entry <= g_entry_vcd.entries_used)
{
tno = g_entry_vcd.entry[entry - 1].tno; /* TNO Get */
com_tno_time_get(tno, &s_msf[0], &e_msf[0]);
for (i = 0; i < 3; ++i)
{
s_msf[i] = g_entry_vcd.entry[entry - 1].sector[i];
}
if (ptime != PLY_TIM_EOF)
{
start = com_tno_time_bcdtobin(&s_msf[0]);
playtime = (ULONG) ptime *5;
start += (playtime - 1);
com_tno_time_bintobcd(start, &e_msf[0]);
}
g_track = com_bcdtobin(tno);
pbc_fe_playcd_req(PLAY_SET_PLAY, 0, FEA_PLAY_CD_ABO, &s_msf[0], &e_msf[0]);
g_play_kind = PKIND_PLAY;
pbc_mode = PBC_MODE_PLAY;
return (OS_OK);
}
return (0xffff);
}
/*************************************************
Function Name: pbc_seg_play
Purpose: Segment play process.
Theory: Issues a read command to the drive
based on the desired segment number
Arguments: segment number
Returns: nothing
*************************************************/
void pbc_seg_play(USHORT seg)
{
ULONG s_time, e_time;
USHORT i;
DbgPrint(("\nPlaying segment %i\n", seg ));
pbc_seg_item = g_info_vcd.seg_play_item[seg - 1];
s_time = com_tno_time_bcdtobin(&g_info_vcd.fseg_addr[0]);
s_time += (seg - 1) * 150; /* 1seg=150sectors */
e_time = s_time + 150;
i = 1;
while (1)
{
if (g_info_vcd.seg_play_item[(seg - 1) + i] & 0x20)
{
e_time += 150; /* MULTI SEGMENT PLAY */
++i;
}
else
{
break;
}
}
e_time -= 1;
com_tno_time_bintobcd(s_time, &s_msf[0]);
com_tno_time_bintobcd(e_time, &e_msf[0]);
g_track = 1; /* segments can only be in track 1 */
DbgPrint(("s[0]=%i, s[1]=%i, s[2]=%i\n", s_msf[0], s_msf[1], s_msf[2]));
DbgPrint(("e[0]=%i, e[1]=%i, e[2]=%i\n", e_msf[0], e_msf[1], e_msf[2]));
pbc_fe_playcd_req(PLAY_SET_PLAY, pbc_seg_item, FEA_PLAY_CD_ABO, &s_msf[0], &e_msf[0]);
g_play_kind = PKIND_PLAY;
pbc_mode = PBC_MODE_PLAY;
}
/*************************************************
Function Name: pbc_get_waite_time
Purpose: Determine proper wait time.
Theory: Based on the wait number from the
selection lists, determine the correct
time to wait during pauses.
Arguments: wait number
Returns: how long to wait (in seconds)
*************************************************/
ULONG pbc_get_waite_time(UBYTE wt)
{
ULONG time;
if (wt == 0)
{
time = 0;
}
else if (wt == 0x0FF)
{
time = 0x0FFFFFFFF;
}
else if (wt <= 60)
{
time = (ULONG) wt;
}
else
{
time = (wt - 60) * 10 + 60;
}
return (time);
}
/*************************************************
Function Name: pbc_loop_jump_chk
Purpose: Check for a loop jump.
Theory: Checks the selectionlist to see if
a loop jump exists.
Arguments: nothing
Returns: valid loop jump or not
*************************************************/
UBYTE pbc_loop_jump_chk(void)
{
SELECT_LIST slist;
if (*g_current_psd == SELECT_LIST_HD)
{
/* Selection List */
pbcParseSelectList(&slist, g_current_psd);
/*---< Jump Timing >---*/
if (slist.loop_jump & 0x80)
{
return (0xff);
}
}
return (OS_OK);
}
/*************************************************
Function Name: pbc_timeout_proc
Purpose: Handle a timeout message from a timer.
Arguments: message passed in from task loop
Returns: nothing
*************************************************/
void pbc_timeout_proc()
{
SELECT_LIST slist;
PLAY_LIST plist;
ULONG offset;
USHORT pin;
USHORT base;
ULONG msg_out[4];
UBYTE num;
UBYTE error;
error = 0;
/* wait timer for list timeout or auto-pause */
DBGPRINT(DBG_ON(DBG_TRACE), ("pbc_timeout_proc: TIM_PBC_PAUSE\n"));
if (pbc_mode == PBC_MODE_END)
{
/* in END mode it has to be a list timeout, there are no trigger bits in END */
if (*g_current_psd == PLAY_LIST_HD)
{
pbcParsePlayList(&plist, g_current_psd);
++pbc_play_item_num;
if (pbc_play_item_num >= plist.item_no)
{
offset = pbc_next_check(); /* Next List Check */
if (offset != 0x0FFFF)
{
offset *= g_info_vcd.offset;
error = pbc_list_play(offset);
if (error)
{
stop_on_error();
return;
}
}
}
else
{
pin = plist.pin[pbc_play_item_num]; /* Get PIN */
pbc_play_item(pin, plist.play_time); /* ITEM Play */
}
}
else if (*g_current_psd == SELECT_LIST_HD)
{
pbcParseSelectList(&slist, g_current_psd );
offset = slist.tout_list_off; /* Time Out List Check */
if (offset != 0x0FFFF)
{
offset *= g_info_vcd.offset;
error = pbc_list_play(offset);
if (error)
{
stop_on_error();
return;
}
}
else
{
if (slist.nos == 1)
{
offset = slist.bsn_off[slist.bsn - 1];
if (offset != 0x0FFFF)
{
offset *= g_info_vcd.offset;
error = pbc_list_play(offset);
if (error)
{
stop_on_error();
return;
}
}
}
else
{
base = slist.bsn - 1;
num = com_random_get(slist.nos);
offset = slist.bsn_off[(num - 1) - base];
if (offset != 0x0FFFF)
{
offset *= g_info_vcd.offset;
error = pbc_list_play(offset);
if (error)
{
stop_on_error();
return;
}
}
}
}
}
}
else if (pbc_mode == PBC_MODE_PLAY)
{
DBGPRINT(DBG_ON(DBG_TRACE), ("pbc_timeout_proc: PBC_MODE_PLAY\n"));
/* in PLAY mode it must be an auto-pause from a trigger bit */
if ((pbc_apause_tim) && /* Auto Pause */
(g_play_kind == PKIND_PAUSE))
{
g_play_kind = PKIND_PLAY;
ulPlaySpeed = 1000;
PEiStreamCtrlResume(tPE);
msg_out[0] = VDVD_STATUS_PLAY;
if (UsrEventHandler(msg_out) != USR_SUCCESS)
{
DbgPrint(("\nUsrEventHandler FAILURE, %s, %d\n\n", __FILE__, __LINE__));
}
}
}
}
/*
* play_location
* play a location from the location structure.
* used to implement bookmarking
*/
void play_location(NAV_VCD_LOCATION *pLocation)
{
ULONG msg[4];
UBYTE location[4];
ULONG locparam;
if (pLocation != NULL)
{
if (pbc_mode != PBC_MODE_STOP)
{
/* if not already stopped, get to the fullstop state */
msg[0] = VDVD_STATUS_STOP;
msg[1] = 1;
if (UsrEventHandler(msg) != USR_SUCCESS)
{
DbgPrint(("\nUsrEventHandler FAILURE, %s, %d\n\n", __FILE__, __LINE__));
}
pbc_stop_com();
}
/*
* Read bookmark data from location handle
*/
pbc_mode = pLocation->rsm.pbc_mode;
g_pbc_on = pLocation->rsm.g_pbc_on;
g_track = pLocation->rsm.g_track;
g_scene = pLocation->rsm.g_scene;
location[0] = pLocation->rsm.pbc_play_time[0];
location[1] = pLocation->rsm.pbc_play_time[1];
location[2] = pLocation->rsm.pbc_play_time[2];
location[3] = pLocation->rsm.pbc_play_time[3];
//what do do with this?
//g_random_mode = PMODE_NORMAL;
if (g_pbc_on && (g_track == 1) )
{
pbc_scene_play();
}
else
{
locparam = com_tno_time_bcdtobin(&location[1]) / 75;
pbc_timesearch(TRUE, locparam);
}
}
else
{
DbgPrint(("Location handle is NULL!"));
}
}
/*************************************************
Function Name: pbc_key_proc
Purpose: Passes key input.
Theory: Passes user key input based on the current
play state
Arguments: message from task loop
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -