📄 pcivideo.cpp
字号:
value = ReadLocalDWORD( 0x00 ) & 0x80;
return( (value) ? TRUE : FALSE );
}
/*******************************************************************************
Start the current RISC program.
*******************************************************************************/
void PCI_VIDEO::RunRisc( void )
{
Odd->RunRisc();
}
/*******************************************************************************
Stop the current RISC program.
*******************************************************************************/
void PCI_VIDEO::HaltRisc( void )
{
Odd->HaltRisc();
}
DWORD PCI_VIDEO::GetInterruptStatus(void)
{
DWORD value;
value = ReadLocalDWORD( 0x100 );
return value;
}
void PCI_VIDEO::SetInterruptStatus(DWORD value)
{
WriteLocalDWORD( 0x100, value);
}
DWORD PCI_VIDEO::GetInterruptMask(void)
{
DWORD value;
value = ReadLocalDWORD( 0x104 );
return value & 0x0FFFFFFF;
}
void PCI_VIDEO::SetInterruptMask(DWORD value)
{
WriteLocalDWORD( 0x104, value & 0x0FFFFFFF);
}
void PCI_VIDEO::SetPLL()
{
WriteLocalDWORD( 0xf0, 0xf9);
WriteLocalDWORD( 0xf4, 0xdc);
WriteLocalDWORD( 0xf8, 0x8e);
WriteLocalDWORD( 0x84, 0x08);
}
void PCI_VIDEO::SetOutputFormat(int bpp)
{
if( bpp == 8 )
{
Even->SetColorFormat( ColorFormatRGB8 );
Odd->SetColorFormat( ColorFormatRGB8 );
}
else if( bpp == 15 )
{
Even->SetColorFormat( ColorFormatRGB15 );
Odd->SetColorFormat( ColorFormatRGB15 );
}
else if( bpp == 16 )
{
Even->SetColorFormat( ColorFormatRGB16 );
Odd->SetColorFormat( ColorFormatRGB16 );
}
else if( bpp == 24 )
{
Even->SetColorFormat( ColorFormatRGB24 );
Odd->SetColorFormat( ColorFormatRGB24 );
}
else if( bpp == 32 )
{
Even->SetColorFormat( ColorFormatRGB32 );
Odd->SetColorFormat( ColorFormatRGB32 );
}
}
void PCI_VIDEO::CreateRiscWxH(DWORD buffer, int width, int height, int bpp, int offset)
{
int i;
DWORD risc_main[1024];
int risc_loc = 0;
width *= ((++bpp)>>3);
risc_main[risc_loc++] = RESYNC|VRE_STAT;
risc_main[risc_loc++] = 0x0;
if( offset == 0 )
risc_main[risc_loc++] = RESYNC|FM1_STAT|RESET_RISCS_1111;
else
risc_main[risc_loc++] = RESYNC|FM1_STAT|SET_RISCS_0001|RESET_RISCS_1110;
risc_main[risc_loc++] = 0x0;
if( height > 240 )
{
for (i = 0; i < height; i+=2)
{
risc_main[risc_loc++] = WRITE | SOL | EOL | width;
risc_main[risc_loc++] = buffer + width*i;
}
}
else
{
for (i = 0; i < height; i++)
{
risc_main[risc_loc++] = WRITE | SOL | EOL | width;
risc_main[risc_loc++] = buffer + width*i;
}
}
risc_main[risc_loc++] = RESYNC|VRO_STAT;
risc_main[risc_loc++] = 0x0;
risc_main[risc_loc++] = JUMP;
risc_main[risc_loc++] = Even->GetRiscAddr() + offset;
Odd->SetRisc( risc_main, risc_loc * 4, offset );
/* now do Even field */
risc_loc = 0;
risc_main[risc_loc++] = RESYNC|FM1_STAT;
risc_main[risc_loc++] = 0x0;
/* create risc program */
if( height > 240 )
{
for (i = 1; i < height; i+=2)
{
risc_main[risc_loc++] = WRITE | SOL | EOL | width;
risc_main[risc_loc++] = buffer + width*i;
}
}
else
{
for (i = 0; i < height; i++)
{
risc_main[risc_loc++] = WRITE | SOL | EOL | width;
risc_main[risc_loc++] = buffer + width*i;
}
}
risc_main[risc_loc++] = RESYNC|VRE_STAT;
risc_main[risc_loc++] = 0x0;
risc_main[risc_loc++] = JUMP;
risc_main[risc_loc++] = Odd->GetRiscAddr()+ 8 + offset;
Even->SetRisc( risc_main, risc_loc * 4, offset );
}
void PCI_VIDEO::CreateRiscWxH_I(DWORD buffer, int width, int height, int bpp, int offset )
{
int i;
DWORD risc_main[1024];
int risc_loc = 0;
width *= ((++bpp)>>3);
risc_main[risc_loc++] = RESYNC|VRE_STAT;
risc_main[risc_loc++] = 0x0;
if( offset == 0 )
risc_main[risc_loc++] = RESYNC|FM1_STAT|RESET_RISCS_1111;
else
risc_main[risc_loc++] = RESYNC|FM1_STAT|SET_RISCS_0001|RESET_RISCS_1110;
risc_main[risc_loc++] = 0x0;
/* Create odd risc program for width by height output */
for (i = 0; i < (height+1)/2; i++)
{
risc_main[risc_loc++] = WRITE | SOL | EOL | width;
risc_main[risc_loc++] = buffer + width*i;
}
risc_main[risc_loc++] = RESYNC|VRO_STAT;
risc_main[risc_loc++] = 0x0;
risc_main[risc_loc++] = JUMP | IRQ;
risc_main[risc_loc++] = Even->GetRiscAddr() + offset;
Odd->SetRisc( risc_main, risc_loc * 4, offset );
/* now do Even field */
risc_loc = 0;
risc_main[risc_loc++] = RESYNC|FM1_STAT;
risc_main[risc_loc++] = 0x0;
/* Create even risc program for width by height output */
for (i = 0; i < height/2; i++)
{
risc_main[risc_loc++] = WRITE | SOL | EOL | width;
risc_main[risc_loc++] = buffer + width*i + 1;
}
risc_main[risc_loc++] = RESYNC|VRE_STAT;
risc_main[risc_loc++] = 0x0;
risc_main[risc_loc++] = JUMP | IRQ;
risc_main[risc_loc++] = Odd->GetRiscAddr()+ 8 + offset;
Even->SetRisc( risc_main, risc_loc * 4, offset );
}
void PCI_VIDEO::Scale(int width, int height, int field )
{
int value;
WORD Clkx1_HACTIVE;
WORD Clkx1_HDELAY;
WORD Min_Pixels;
WORD Active_lines_per_field;
int VActive;
WORD AnalogWin_top = 0; /* ??? */
WORD AnalogWin_left = 0;
VIDEO_FIELD *vid_field;
if( field == FieldEven )
vid_field = Even;
else
vid_field = Odd;
if( GetVideoFormat() == VideoFormatAuto )
SetVideoFormat( VideoFormatNTSC );
if( GetVideoFormat() == VideoFormatNTSC )
{
Clkx1_HACTIVE = 730;
Clkx1_HDELAY = 148;
Min_Pixels = 44;
Active_lines_per_field = 240;
VActive = 0x1F4;
}
else
{
Clkx1_HACTIVE = 914;
Clkx1_HDELAY = 190;
Min_Pixels = 48;
Active_lines_per_field = 284;
VActive = 0x238;
SetAGCDelay( 0x7F );
SetBurstDelay( 0x72 );
}
if( height > Active_lines_per_field )
height /= 2;
WORD Min_UncroppedPixels = Min_Pixels + 20;
// WORD Min_UncroppedPixels = Min_Pixels + 100;
WORD Max_Pixels = ((Clkx1_HACTIVE < 774) ? Clkx1_HACTIVE - 6 : 768);
WORD Min_Lines = (Active_lines_per_field / 16 + 1) * 2;
WORD Max_Lines = Active_lines_per_field;
WORD Max_VFilter1_Pixels = ((Clkx1_HACTIVE > 796) ? 384 : (Clkx1_HACTIVE * 14 / 29));
WORD Max_VFilter2_Pixels = Clkx1_HACTIVE * 8 / 33;
WORD Max_VFilter3_Pixels = Clkx1_HACTIVE * 8 / 33;
WORD Max_VFilter1_Lines = Active_lines_per_field;
WORD Max_VFilter2_Lines = Active_lines_per_field / 2;
WORD Max_VFilter3_Lines = Active_lines_per_field * 2 / 5;
// Calculate Hactive
WORD m_HActive = min( Max_Pixels, max( (WORD)width, Min_Pixels ) );
vid_field->SetHActive( m_HActive );
// No calculation needed for VActive register since it based on the UNSCALED image
vid_field->SetVActive( VActive );
// Calculate Vertical Scaling
WORD m_lines = min( Max_Lines, max( (WORD)height, Min_Lines ) );
WORD LPB_VScale_Factor = (WORD) ( 1 + ( m_lines - 1 ) / Active_lines_per_field );
m_lines = (WORD) ( ( m_lines + LPB_VScale_Factor - 1 ) / LPB_VScale_Factor );
value = (WORD) ( ( 0x10000L - ((DWORD)Active_lines_per_field * 512L / (DWORD)m_lines) + 512L ) & 0x1FFFL );
vid_field->SetVScale( value );
// Set the Vertical Filter
// this is to remove junk lines at the top of video. flag set to off
// when image hight is above CIF
DWORD m_VFilter;
if ( VFilterFlag_ == Off )
{
m_VFilter = 0;
}
else
{
if ( ( m_HActive <= Max_VFilter3_Pixels ) &&
( m_lines <= Max_VFilter3_Lines ) )
m_VFilter = 3;
else if ( ( m_HActive <= Max_VFilter2_Pixels ) &&
( m_lines <= Max_VFilter2_Lines ) )
m_VFilter = 2;
else if ( ( m_HActive <= Max_VFilter1_Pixels ) &&
( m_lines <= Max_VFilter1_Lines ) )
m_VFilter = 1;
else
m_VFilter = 0;
}
vid_field->SetVerticalFilter( m_VFilter );
WORD VDelay, moreDelay;
// increase VDelay will eliminate garbage lines at top of image
switch ( m_VFilter )
{
case 3:
moreDelay = 4;
break;
case 2:
moreDelay = 2;
break;
case 1:
case 0:
default:
moreDelay = 0;
break;
}
if ( GetVideoFormat() == VideoFormatNTSC )
VDelay = 0x001A + moreDelay; // NTSC
else
VDelay = 0x0026 + moreDelay; // PAL/SECAM
// now add the cropping region into VDelay register; i.e. skip some pixels
// before we start taking them as real image
VDelay += (WORD)( ( (DWORD)Max_Lines * (DWORD)AnalogWin_top + m_lines - 1 ) / (DWORD)m_lines * 2 );
vid_field->SetVDelay( VDelay );
// calculations here requires calculation of HActive first!
WORD m_pixels = m_HActive;
if ( m_pixels < Min_UncroppedPixels )
m_pixels += (WORD) ( ( Min_UncroppedPixels - m_pixels + 9 ) / 10 );
DWORD a = (DWORD)m_pixels * (DWORD)Clkx1_HDELAY;
DWORD b = (DWORD)Clkx1_HACTIVE * 2L;
WORD HDelay = (WORD) ( ( a + (DWORD)Clkx1_HACTIVE * 2 - 1) / b * 2L );
// now add the cropping region into HDelay register; i.e. skip some pixels
// before we start taking them as real image
HDelay += (WORD)AnalogWin_left;
// HDelay must be even or else color would be wrong
HDelay &= ~01;
vid_field->SetHDelay( HDelay );
// since we increase HDelay, we should decrease HActive by the same amount
m_HActive -= (WORD)AnalogWin_left;
vid_field->SetHActive( m_HActive );
value = (WORD) ( ( ( (DWORD)Clkx1_HACTIVE * 4096L ) / (DWORD)m_pixels ) - 4096L );
vid_field->SetHScale( value );
if ( GetVideoFormat() != VideoFormatSECAM )
value = HFilterAutoFormat;
else // SECAM
if ( m_pixels < Clkx1_HACTIVE / 7 )
value = HFilterICON;
else
value = HFilterQCIF;
vid_field->SetHorizontalFilter( value );
}
void PCI_VIDEO::StartScaleVideo(DWORD buffer, int width, int height, int bpp )
{
int offset = 0;
if( height > 576 )
height = 576;
if( width > 768 )
width = 768;
Odd->HaltRisc();
SetOutputFormat(bpp);
if( height > 240 )
CreateRiscWxH_I( buffer, width, height, bpp, offset );
else
CreateRiscWxH( buffer, width, height, bpp, offset );
if( height > 240 )
{
Scale(width, (height+1)/2, FieldOdd );
Scale(width, height/2, FieldEven );
}
else
{
Scale(width, height, FieldOdd );
Scale(width, height, FieldEven );
}
}
void PCI_VIDEO::CreateRisc384x288(DWORD dwOdd, DWORD dwEven, int bpp)
{
int i;
DWORD risc_main[1024];
int risc_loc = 0;
int width = 384 * ((++bpp)>>3);
risc_main[risc_loc++] = RESYNC | VRE_STAT;
risc_main[risc_loc++] = 0x0;
risc_main[risc_loc++] = RESYNC | FM1_STAT;
risc_main[risc_loc++] = 0x0;
for (i = 0; i < 288; i++)
{
risc_main[risc_loc++] = WRITE | SOL | EOL | width;
risc_main[risc_loc++] = dwOdd + width*i;
}
risc_main[risc_loc++] = RESYNC | VRO_STAT | SET_RISCS_0001;
risc_main[risc_loc++] = 0x0;
risc_main[risc_loc++] = JUMP | IRQ;
risc_main[risc_loc++] = Even->GetRiscAddr();
Odd->SetRisc( risc_main, risc_loc * 4, 0 );
/* now do Even field */
risc_loc = 0;
risc_main[risc_loc++] = RESYNC | FM1_STAT;
risc_main[risc_loc++] = 0x0;
/* create risc program */
for (i = 0; i < 288; i++)
{
risc_main[risc_loc++] = WRITE | SOL | EOL | width;
risc_main[risc_loc++] = dwEven + width*i;
}
risc_main[risc_loc++] = RESYNC | VRE_STAT | RESET_RISCS_0001;
risc_main[risc_loc++] = 0x0;
risc_main[risc_loc++] = JUMP | IRQ;
risc_main[risc_loc++] = Odd->GetRiscAddr()+ 8;
Even->SetRisc( risc_main, risc_loc * 4, 0);
}
void PCI_VIDEO::Scale384x288x16()
{
WORD HSCALE;
WORD HDELAY;
WORD HACTIVE;
WORD VSCALE;
WORD VDELAY;
WORD VACTIVE;
SetVideoFormat( VideoFormatPAL );
SetOutputFormat(16);
SetAGCDelay( 0x7F );
SetBurstDelay( 0x72 );
HSCALE = 0x1615;
HDELAY = 0x50;
HACTIVE = 0x180;
VSCALE = 0x0000;
VDELAY = 0x20;
VACTIVE = 0x240;
Odd->SetHScale(HSCALE);
Even->SetHScale(HSCALE);
Odd->SetHDelay(HDELAY);
Even->SetHDelay(HDELAY);
Odd->SetHActive(HACTIVE);
Even->SetHActive(HACTIVE);
Odd->SetVScale(VSCALE);
Even->SetVScale(VSCALE);
Odd->SetVDelay(VDELAY);
Even->SetVDelay(VDELAY);
Odd->SetVActive(VACTIVE);
Even->SetVActive(VACTIVE);
Odd->SetVerticalFilter( 1 );
Even->SetVerticalFilter( 1 );
SetPLL();
}
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -