📄 theater.cpp
字号:
static const comb_cntl1 comb_cntl1_secam[] = { { 1, 0, 1, 0, 2, 0, 0 }, { 1, X, 0, 0, 2, 0, 0 } }; static const comb_cntl2 comb_cntl2_secam[] = { { 0xFF, 0xFF, 0xFF, 0xFF }, { 0xFF, 0xFF, 0xFF, 0xFF } }; static const comb_line_length comb_line_length_secam[] = { { 0x46A, 0 }, { 0x46A, 0 } };#undef X static const comb_settings comb_settings_list[] = { { comb_types_ntsc_m, comb_cntl0_ntsc_m, comb_cntl1_ntsc_m, comb_cntl2_ntsc_m, comb_line_length_ntsc_m }, { comb_types_ntsc_m, comb_cntl0_ntsc_m, comb_cntl1_ntsc_m, comb_cntl2_ntsc_m, comb_line_length_ntsc_m }, { comb_types_ntsc_433, comb_cntl0_ntsc_433, comb_cntl1_ntsc_433, comb_cntl2_ntsc_433, comb_line_length_ntsc_433 }, { comb_types_pal_m, comb_cntl0_pal_m, comb_cntl1_pal_m, comb_cntl2_pal_m, comb_line_length_pal_m }, { comb_types_pal_n, comb_cntl0_pal_n, comb_cntl1_pal_n, comb_cntl2_pal_n, comb_line_length_pal_n }, { comb_types_pal_nc, comb_cntl0_pal_nc, comb_cntl1_pal_nc, comb_cntl2_pal_nc, comb_line_length_pal_nc }, { comb_types_pal, comb_cntl0_pal, comb_cntl1_pal, comb_cntl2_pal, comb_line_length_pal }, { comb_types_pal_60, comb_cntl0_pal_60, comb_cntl1_pal_60, comb_cntl2_pal_60, comb_line_length_pal_60 }, { comb_types_secam, comb_cntl0_secam, comb_cntl1_secam, comb_cntl2_secam, comb_line_length_secam } }; int min_type, max_type, type; const comb_settings *settings; int i = 0; PRINT(("CTheater::SetCombFilter(%c, %c)\n", "NJ4MNCB6S"[standard], "TCS"[source])); // I don't really understand what the different types mean; // what is particularly strange is that many types are defined for few standards only if( source == C_THEATER_TUNER || source == C_THEATER_COMPOSITE ) { min_type = _3Tap_2D_adaptive_Comb; max_type = _3Tap_C_combed_Y_combed; } else { min_type = YC_mode_Comb_filter_off; max_type = YC_mode_3Tap_YV_filter; } settings = &comb_settings_list[standard]; for( type = min_type; type <= max_type; ++type ) { for( i = 0; settings->types[i]; ++i ) { if( settings->types[i] == type ) break; } if( settings->types[i] != 0 ) break; } if( type > max_type ) { PRINT(("CTheater::SetCombFilter() - No settings for this standard and input type combination!!!\n")); return; } SetRegister(VIP_COMB_CNTL0, *(const int32 *)(settings->cntl0 + i)); SetRegister(VIP_COMB_CNTL1, *(const int32 *)(settings->cntl1 + i)); SetRegister(VIP_COMB_CNTL2, *(const int32 *)(settings->cntl2 + i)); SetRegister(VIP_COMB_LINE_LENGTH, *(const int32 *)(settings->line_length + i)); // reset the comb filter SetRegister(VIP_COMB_CNTL1, Register(VIP_COMB_CNTL1) ^ COMB_SYNCLPFRST); SetRegister(VIP_COMB_CNTL1, Register(VIP_COMB_CNTL1) ^ COMB_SYNCLPFRST);}// setup luma processorvoid CTheater::SetLuminanceProcessor(theater_standard standard){ static const uint16 synctip_ref0[] = { 0x037, 0x037, 0x037, 0x037, 0x037, 0x037, 0x037, 0x037, 0x037 }; static const uint16 synctip_ref1[] = { 0x029, 0x029, 0x029, 0x029, 0x029, 0x026, 0x026, 0x026, 0x026 }; static const uint16 clamp_ref[] = { 0x03B, 0x03B, 0x03B, 0x03B, 0x03B, 0x03B, 0x03B, 0x03B, 0x03B }; static const uint16 agc_peakwhite[] = { 0x0FF, 0x0FF, 0x0FF, 0x0FF, 0x0FF, 0x0FF, 0x0FF, 0x0FF, 0x0FF }; static const uint16 vbi_peakwhite[] = { 0x0D2, 0x0D2, 0xD2, 0x0D2, 0x0D2, 0x0C6, 0x0C6, 0x0C6, 0x0C6 }; static const uint16 wpa_threshold[] = { 0x406, 0x406, 0x4FC, 0x406, 0x59C, 0x488, 0x59C, 0x59C, 0x57A }; static const uint16 wpa_trigger_lo[] = { 0x0B3, 0x0B3, 0x0B3, 0x0B3, 0x096, 0x096, 0x096, 0x0B3, 0x096 }; static const uint16 wpa_trigger_hi[] = { 0x21B, 0x21B, 0x21B, 0x21B, 0x1C2, 0x1C2, 0x1C2, 0x21B, 0x1C2 }; static const uint16 lp_lockout_start[] = { 0x206, 0x206, 0x206, 0x206, 0x263, 0x263, 0x263, 0x206, 0x263 }; // PAL: changed 0x2c to 0x0c; NTSC: changed 0x21 to 0x0b static const uint16 lp_lockout_end[] = { 0x00B, 0x00B, 0x00B, 0x00B, 0x00C, 0x00C, 0x00C, 0x00B, 0x00C }; PRINT(("CTheater::SetLuminanceProcessor(%c)\n", "NJ4MNCB6S"[standard])); SetRegister(VIP_LP_AGC_CLAMP_CNTL0, SYNCTIP_REF0, synctip_ref0[standard] << 0); SetRegister(VIP_LP_AGC_CLAMP_CNTL0, SYNCTIP_REF1, (uint32)synctip_ref1[standard] << 8); SetRegister(VIP_LP_AGC_CLAMP_CNTL0, CLAMP_REF, (uint32)clamp_ref[standard] << 16); SetRegister(VIP_LP_AGC_CLAMP_CNTL0, AGC_PEAKWHITE, (uint32)agc_peakwhite[standard] << 24); SetRegister(VIP_LP_AGC_CLAMP_CNTL1, VBI_PEAKWHITE, (uint32)vbi_peakwhite[standard] << 0); SetRegister(VIP_LP_WPA_CNTL0, WPA_THRESHOLD, wpa_threshold[standard] << 0); SetRegister(VIP_LP_WPA_CNTL1, WPA_TRIGGER_LO, wpa_trigger_lo[standard] << 0); SetRegister(VIP_LP_WPA_CNTL1, WPA_TRIGGER_HI, (uint32)wpa_trigger_hi[standard] << 16); SetRegister(VIP_LP_VERT_LOCKOUT, LP_LOCKOUT_START, lp_lockout_start[standard] << 0); SetRegister(VIP_LP_VERT_LOCKOUT, LP_LOCKOUT_END, (uint32)lp_lockout_end[standard] << 16);}// setup brightness and contrastvoid CTheater::SetLuminanceLevels(theater_standard standard, int brightness, int contrast){ double ref0, setup, gain; ref0 = Register(VIP_LP_AGC_CLAMP_CNTL0, SYNCTIP_REF0); switch (standard) { case C_THEATER_NTSC: case C_THEATER_PAL_M: case C_THEATER_NTSC_443: setup = 7.5 * ref0 / 40.0; gain = 219.0 / (92.5 * ref0 / 40.0); break; case C_THEATER_NTSC_JAPAN: setup = 0.0; gain = 219.0 / (100.0 * ref0 / 40.0); break; case C_THEATER_PAL_BDGHI: case C_THEATER_PAL_N: case C_THEATER_SECAM: case C_THEATER_PAL_60: case C_THEATER_PAL_NC: setup = 0.0; gain = 219.0 / (100.0 * ref0 / 43.0); break; default: setup = 0.0; gain = 0.0; break; } if (contrast <= -100) contrast = -99; /* set luminance processor constrast (7:0) */ SetRegister(VIP_LP_CONTRAST, CONTRAST, int(64.0 * ((contrast + 100) / 100.0) * gain) << 0); /* set luminance processor brightness (13:0) */ SetRegister(VIP_LP_BRIGHTNESS, BRIGHTNESS, int(16.0 * ((brightness - setup) + 16.0 / ((contrast + 100) * gain / 100.0))) & BRIGHTNESS);}// setup chroma demodulatorvoid CTheater::SetChromaProcessor(theater_standard standard){ PRINT(("CTheater::SetChromaProcessor(%c)\n", "NJ4MNCB6S"[standard])); static const uint32 ch_dto_inc[] = { 0x400000, 0x400000, 0x400000, 0x400000, 0x400000, 0x400000, 0x400000, 0x400000, 0x3E7A28 }; static const uint8 ch_pll_sgain[] = { 1, 1, 1, 1, 1, 1, 1, 1, 5 }; static const uint8 ch_pll_fgain[] = { 2, 2, 2, 2, 2, 2, 2, 2, 6 }; static const uint8 ch_height[] = { 0xCD, 0xCD, 0xCD, 0x91, 0x91, 0x9C, 0x9C, 0x9C, 0x66 }; static const uint8 ch_kill_level[] = { 0x0C0, 0xC0, 0xC0, 0x8C, 0x8C, 0x90, 0x90, 0x90, 0x60 }; static const uint8 ch_agc_error_lim[] = { 2, 2, 2, 2, 2, 2, 2, 2, 3 }; static const uint8 ch_agc_filter_en[] = { 0, 0, 0, 0, 0, 0, 1, 0, 0 }; static const uint8 ch_agc_loop_speed[] = { 0, 0, 0, 0, 0, 0, 0, 0, 0 }; static const uint16 cr_burst_gain[] = { 0x7A, 0x71, 0x7A, 0x7A, 0x7A, 0x7A, 0x7A, 0x7A, 0x1FF }; static const uint16 cb_burst_gain[] = { 0xAC, 0x9F, 0xAC, 0xAC, 0xAC, 0xAB, 0xAB, 0xAB, 0x1FF }; static const uint16 crdr_active_gain[] = { 0x7A, 0x71, 0x7A, 0x7A, 0x7A, 0x7A, 0x7A, 0x7A, 0x11C }; static const uint16 cbdb_active_gain[] = { 0xAC, 0x9F, 0xAC, 0xAC, 0xAC, 0xAB, 0xAB, 0xAB, 0x15A }; static const uint16 cp_vert_lockout_start[] = { 0x207, 0x207, 0x207, 0x207, 0x269, 0x269, 0x269, 0x207, 0x269 }; static const uint8 cp_vert_lockout_end[] = { 0x00E, 0x00E, 0x00E, 0x00E, 0x00E, 0x012, 0x012, 0x00E, 0x012 }; SetRegister(VIP_CP_PLL_CNTL0, CH_DTO_INC, ch_dto_inc[standard] << 0); SetRegister(VIP_CP_PLL_CNTL0, CH_PLL_SGAIN, (uint32)ch_pll_sgain[standard] << 24); SetRegister(VIP_CP_PLL_CNTL0, CH_PLL_FGAIN, (uint32)ch_pll_fgain[standard] << 28); SetRegister(VIP_CP_AGC_CNTL, CH_HEIGHT, ch_height[standard] << 0); SetRegister(VIP_CP_AGC_CNTL, CH_KILL_LEVEL, (uint32)ch_kill_level[standard] << 8); SetRegister(VIP_CP_AGC_CNTL, CH_AGC_ERROR_LIM, (uint32)ch_agc_error_lim[standard] << 16); SetRegister(VIP_CP_AGC_CNTL, CH_AGC_FILTER_EN, (uint32)ch_agc_filter_en[standard] << 18); SetRegister(VIP_CP_AGC_CNTL, CH_AGC_LOOP_SPEED, (uint32)ch_agc_loop_speed[standard] << 19); SetRegister(VIP_CP_BURST_GAIN, CR_BURST_GAIN, cr_burst_gain[standard] << 0); SetRegister(VIP_CP_BURST_GAIN, CB_BURST_GAIN, (uint32)cb_burst_gain[standard] << 16); SetRegister(VIP_CP_ACTIVE_GAIN, CRDR_ACTIVE_GAIN, crdr_active_gain[standard] << 0); SetRegister(VIP_CP_ACTIVE_GAIN, CBDB_ACTIVE_GAIN, (uint32)cbdb_active_gain[standard] << 16); SetRegister(VIP_CP_VERT_LOCKOUT, CP_LOCKOUT_START, cp_vert_lockout_start[standard] << 0); SetRegister(VIP_CP_VERT_LOCKOUT, CP_LOCKOUT_END, (uint32)cp_vert_lockout_end[standard] << 16);}// set colour saturation and hue.// hue makes sense for NTSC only and seems to act as saturation for PALvoid CTheater::SetChromaLevels(theater_standard standard, int saturation, int hue){ int ref0; double gain, CRgain, CBgain; /* compute Cr/Cb gains */ ref0 = Register(VIP_LP_AGC_CLAMP_CNTL0, SYNCTIP_REF0); switch (standard) { case C_THEATER_NTSC: case C_THEATER_NTSC_443: case C_THEATER_PAL_M: CRgain = (40.0 / ref0) * (100.0 / 92.5) * (1.0 / 0.877) * (112.0 / 70.1) / 1.5; CBgain = (40.0 / ref0) * (100.0 / 92.5) * (1.0 / 0.492) * (112.0 / 88.6) / 1.5; break; case C_THEATER_NTSC_JAPAN: CRgain = (40.0 / ref0) * (100.0 / 100.0) * (1.0 / 0.877) * (112.0 / 70.1) / 1.5; CBgain = (40.0 / ref0) * (100.0 / 100.0) * (1.0 / 0.492) * (112.0 / 88.6) / 1.5; break; case C_THEATER_PAL_BDGHI: case C_THEATER_PAL_60: case C_THEATER_PAL_NC: case C_THEATER_PAL_N: CRgain = (43.0 / ref0) * (100.0 / 92.5) * (1.0 / 0.877) * (112.0 / 70.1) / 1.5; CBgain = (43.0 / ref0) * (100.0 / 92.5) * (1.0 / 0.492) * (112.0 / 88.6) / 1.5; break; case C_THEATER_SECAM: CRgain = 32.0 * 32768.0 / 280000.0 / (33554432.0 / 35.46985) * (1.597 / 1.902) / 1.5; CBgain = 32.0 * 32768.0 / 230000.0 / (33554432.0 / 35.46985) * (1.267 / 1.505) / 1.5; break; default: PRINT(("CTheater::SetChromaLevels() - Bad standard\n")); CRgain = 0.0; CBgain = 0.0; break; } if (saturation >= 0) gain = 1.0 + 4.9 * saturation / 100.0; else gain = 1.0 + saturation / 100.0; SetRegister(VIP_CP_ACTIVE_GAIN, CRDR_ACTIVE_GAIN, int(128 * CRgain * gain) << 0); SetRegister(VIP_CP_ACTIVE_GAIN, CBDB_ACTIVE_GAIN, int(128 * CBgain * gain) << 16); if (hue >= 0) hue = (256 * hue) / 360; else hue = (256 * (hue + 360)) / 360; SetRegister(VIP_CP_HUE_CNTL, HUE_ADJ, hue << 0);}// these values are used by scaler as wellstatic const uint16 h_active_start[] = { 0x06b, 0x06B, 0x07E, 0x067, 0x09A, 0x07D, 0x09A, 0x084, 0x095 };static const uint16 h_active_end[] = { 0x363, 0x363, 0x42A, 0x363, 0x439, 0x439, 0x439, 0x363, 0x439 };static const uint16 v_active_start[] = { 0x025, 0x025, 0x025, 0x025, 0x02E, 0x02E, 0x02E, 0x025, 0x02E };// PAL height is too small (572 instead of 576 lines), but changing 0x269 to 0x26d// leads to trouble, and the last 2 lines seem to be used for VBI data // (read: garbage) anywaystatic const uint16 v_active_end[] = { 0x204, 0x204, 0x204, 0x204, 0x269, 0x269, 0x269, 0x204, 0x269 };static const uint16 h_vbi_wind_start[] = { 0x064, 0x064, 0x064, 0x064, 0x084, 0x084, 0x084, 0x064, 0x084 };static const uint16 h_vbi_wind_end[] = { 0x366, 0x366, 0x366, 0x366, 0x41F, 0x41F, 0x41F, 0x366, 0x41F };static const uint16 v_vbi_wind_start[] = { 0x00b, 0x00b, 0x00b, 0x00b, 0x008, 0x008, 0x008, 0x00b, 0x008 };static const uint16 v_vbi_wind_end[] = { 0x024, 0x024, 0x024, 0x024, 0x02d, 0x02d, 0x02d, 0x024, 0x02d }; void CTheater::getActiveRange( theater_standard standard, CRadeonRect &rect ){ rect.SetTo( h_active_start[standard], v_active_start[standard], h_active_end[standard], v_active_end[standard] );}void CTheater::getVBIRange( theater_standard standard, CRadeonRect &rect ){ rect.SetTo( h_vbi_wind_start[standard], v_vbi_wind_start[standard], h_vbi_wind_end[standard], v_vbi_wind_end[standard] );}// program clipping enginevoid CTheater::SetClipWindow(theater_standard standard, bool vbi){ // set horizontal active window SetRegister(VIP_H_ACTIVE_WINDOW, H_ACTIVE_START, h_active_start[standard] << 0); SetRegister(VIP_H_ACTIVE_WINDOW, H_ACTIVE_END, (uint32)h_active_end[standard] << 16); // set vertical active window SetRegister(VIP_V_ACTIVE_WINDOW, V_ACTIVE_START, v_active_start[standard] << 0); SetRegister(VIP_V_ACTIVE_WINDOW, V_ACTIVE_END, (uint32)v_active_end[standard] << 16); // set horizontal VBI window SetRegister(VIP_H_VBI_WINDOW, H_VBI_WIND_START, h_vbi_wind_start[standard] << 0); SetRegister(VIP_H_VBI_WINDOW, H_VBI_WIND_END, (uint32)h_vbi_wind_end[standard] << 16); // set vertical VBI window SetRegister(VIP_V_VBI_WINDOW, V_VBI_WIND_START, v_vbi_wind_start[standard] << 0); SetRegister(VIP_V_VBI_WINDOW, V_VBI_WIND_END, (uint32)v_vbi_wind_end[standard] << 16); // set VBI scaler control SetRegister(VIP_VBI_SCALER_CONTROL, (1 << 16) & VBI_SCALING_RATIO); // enable/disable VBI capture SetRegister(VIP_VBI_CONTROL, VBI_CAPTURE_ENABLE, vbi ? VBI_CAPTURE_EN : VBI_CAPTURE_DIS); PRINT(("CTheater::SetClipWindow(active=%d/%d/%d/%d, vbi=%d/%d/%d/%d)\n", Register(VIP_H_ACTIVE_WINDOW, H_ACTIVE_START) >> 0, Register(VIP_H_ACTIVE_WINDOW, H_ACTIVE_END) >> 16, Register(VIP_V_ACTIVE_WINDOW, V_ACTIVE_START) >> 0, Register(VIP_V_ACTIVE_WINDOW, V_ACTIVE_END) >> 16, Register(VIP_H_VBI_WINDOW, H_VBI_WIND_START) >> 0, Register(VIP_H_VBI_WINDOW, H_VBI_WIND_END) >> 16, Register(VIP_V_VBI_WINDOW, V_VBI_WIND_START) >> 0, Register(VIP_V_VBI_WINDOW, V_VBI_WIND_END) >> 16)); }// setup capture scaler.void CTheater::SetScaler(theater_standard standard, int hactive, int vactive, bool deinterlace){ int oddOffset, evenOffset; uint16 h_active_width, v_active_height; // ASSERT(vactive <= 511); // TK: Gatos uses different values here h_active_width = h_active_end[standard] - h_active_start[standard] + 1; v_active_height = v_active_end[standard] - v_active_start[standard] + 1; // for PAL, we have 572 lines only, but need 576 lines; // my attempts to find those missing lines all failed, so if the application requests // 576 lines, we had to upscale the video which is not supported by hardware; // solution: restrict to 572 lines - the scaler will fill out the missing lines with black if( vactive > v_active_height ) vactive = v_active_height; if (deinterlace) { // progressive scan evenOffset = oddOffset = 512 - (int) ((512 * vactive) / v_active_height); } else { // interlaced evenOffset = (int) ((512 * vactive) / v_active_height); oddOffset = 2048 - evenOffset; } // set scale input window SetRegister(VIP_SCALER_IN_WINDOW, H_IN_WIND_START, h_active_start[standard] << 0); SetRegister(VIP_SCALER_IN_WINDOW, V_IN_WIND_START, (uint32)v_active_start[standard] << 16); SetRegister(VIP_SCALER_OUT_WINDOW, H_OUT_WIND_WIDTH, hactive << 0); SetRegister(VIP_SCALER_OUT_WINDOW, V_OUT_WIND_HEIGHT, (vactive / 2) << 16); SetRegister(VIP_H_SCALER_CONTROL, H_SCALE_RATIO, (((uint32)h_active_width << 16) / hactive) << 0); SetRegister(VIP_V_SCALER_CONTROL, V_SCALE_RATIO, ((vactive << 11) / v_active_height) << 0); // enable horizontal and vertical scaler SetRegister(VIP_H_SCALER_CONTROL, H_BYPASS, h_active_width == hactive ? H_BYPASS : 0); SetRegister(VIP_V_SCALER_CONTROL, V_BYPASS, v_active_height == vactive ? V_BYPASS : 0); // set deinterlace control SetRegister(VIP_V_SCALER_CONTROL, V_DEINTERLACE_ON, deinterlace ? V_DEINTERLACE_ON : 0); SetRegister(VIP_V_DEINTERLACE_CONTROL, EVENF_OFFSET, evenOffset << 0); SetRegister(VIP_V_DEINTERLACE_CONTROL, ODDF_OFFSET, oddOffset << 11); SetRegister(VIP_V_SCALER_CONTROL, V_DEINTERLACE_ON, deinterlace ? V_DEINTERLACE_ON : 0); PRINT(("CTheater::SetScaler(active=%d/%d/%d/%d, scale=%d/%d)\n", Register(VIP_SCALER_IN_WINDOW, H_IN_WIND_START) >> 0, Register(VIP_SCALER_IN_WINDOW, V_IN_WIND_START) >> 16, hactive, vactive, Register(VIP_H_SCALER_CONTROL, H_SCALE_RATIO), Register(VIP_V_SCALER_CONTROL, V_SCALE_RATIO)));}int CTheater::Register(int index){ return fPort.Register(fDevice, index);}int CTheater::Register(int index, int mask){ return fPort.Register(fDevice, index) & mask;}void CTheater::SetRegister(int index, int value){ fPort.SetRegister(fDevice, index, value);}void CTheater::SetRegister(int index, int mask, int value){ if ((value & ~mask) != 0) PRINT(("WARNING: CTheater::SetRegister(0x%04x, 0x%08x, 0x%08x)\n", index, mask, value)); fPort.SetRegister(fDevice, index, (fPort.Register(fDevice, index) & ~mask) | (value & mask));}int CTheater::CurrentLine(){ return Register(VIP_VS_LINE_COUNT) & VS_LINE_COUNT;}void CTheater::PrintToStream(){ PRINT(("<<< Rage Theater Registers >>>\n")); for (int index = 0x0400; index <= 0x06ff; index += 4) { int value = Register(index); PRINT(("REG_0x%04x = 0x%08x\n", index, value)); } }
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -