mirror of https://github.com/PCSX2/pcsx2.git
GS: Add audio capture and custom resolution
This commit is contained in:
parent
6834367a3e
commit
88c1f00b62
|
@ -963,7 +963,7 @@ void MainWindow::onToolsVideoCaptureToggled(bool checked)
|
|||
}
|
||||
|
||||
const QString container(QString::fromStdString(
|
||||
Host::GetStringSettingValue("EmuCore/GS", "VideoCaptureContainer", Pcsx2Config::GSOptions::DEFAULT_VIDEO_CAPTURE_CONTAINER)));
|
||||
Host::GetStringSettingValue("EmuCore/GS", "CaptureContainer", Pcsx2Config::GSOptions::DEFAULT_CAPTURE_CONTAINER)));
|
||||
const QString filter(tr("%1 Files (*.%2)").arg(container.toUpper()).arg(container));
|
||||
|
||||
QString path(QStringLiteral("%1.%2").arg(QString::fromStdString(GSGetBaseVideoFilename())).arg(container));
|
||||
|
|
|
@ -861,6 +861,10 @@ void EmuThread::beginCapture(const QString& path)
|
|||
GetMTGS().RunOnGSThread([path = path.toStdString()]() {
|
||||
GSBeginCapture(std::move(path));
|
||||
});
|
||||
|
||||
// Sync GS thread. We want to start adding audio at the same time as video.
|
||||
// TODO: This could be up to 64 frames behind... use the pts to adjust it.
|
||||
GetMTGS().WaitGS(false, false, false);
|
||||
}
|
||||
|
||||
void EmuThread::endCapture()
|
||||
|
|
|
@ -97,7 +97,8 @@ GraphicsSettingsWidget::GraphicsSettingsWidget(SettingsDialog* dialog, QWidget*
|
|||
SettingWidgetBinder::BindWidgetToEnumSetting(sif, m_ui.fmvAspectRatio, "EmuCore/GS", "FMVAspectRatioSwitch",
|
||||
Pcsx2Config::GSOptions::FMVAspectRatioSwitchNames, FMVAspectRatioSwitchType::Off);
|
||||
SettingWidgetBinder::BindWidgetToIntSetting(sif, m_ui.interlacing, "EmuCore/GS", "deinterlace_mode", DEFAULT_INTERLACE_MODE);
|
||||
SettingWidgetBinder::BindWidgetToIntSetting(sif, m_ui.bilinearFiltering, "EmuCore/GS", "linear_present_mode", static_cast<int>(GSPostBilinearMode::BilinearSmooth));
|
||||
SettingWidgetBinder::BindWidgetToIntSetting(
|
||||
sif, m_ui.bilinearFiltering, "EmuCore/GS", "linear_present_mode", static_cast<int>(GSPostBilinearMode::BilinearSmooth));
|
||||
SettingWidgetBinder::BindWidgetToBoolSetting(sif, m_ui.widescreenPatches, "EmuCore", "EnableWideScreenPatches", false);
|
||||
SettingWidgetBinder::BindWidgetToBoolSetting(sif, m_ui.noInterlacingPatches, "EmuCore", "EnableNoInterlacingPatches", false);
|
||||
SettingWidgetBinder::BindWidgetToBoolSetting(sif, m_ui.integerScaling, "EmuCore/GS", "IntegerScaling", false);
|
||||
|
@ -105,8 +106,10 @@ GraphicsSettingsWidget::GraphicsSettingsWidget(SettingsDialog* dialog, QWidget*
|
|||
SettingWidgetBinder::BindWidgetToBoolSetting(sif, m_ui.PCRTCOverscan, "EmuCore/GS", "pcrtc_overscan", false);
|
||||
SettingWidgetBinder::BindWidgetToBoolSetting(sif, m_ui.PCRTCAntiBlur, "EmuCore/GS", "pcrtc_antiblur", true);
|
||||
SettingWidgetBinder::BindWidgetToBoolSetting(sif, m_ui.DisableInterlaceOffset, "EmuCore/GS", "disable_interlace_offset", false);
|
||||
SettingWidgetBinder::BindWidgetToIntSetting(sif, m_ui.screenshotSize, "EmuCore/GS", "ScreenshotSize", static_cast<int>(GSScreenshotSize::WindowResolution));
|
||||
SettingWidgetBinder::BindWidgetToIntSetting(sif, m_ui.screenshotFormat, "EmuCore/GS", "ScreenshotFormat", static_cast<int>(GSScreenshotFormat::PNG));
|
||||
SettingWidgetBinder::BindWidgetToIntSetting(
|
||||
sif, m_ui.screenshotSize, "EmuCore/GS", "ScreenshotSize", static_cast<int>(GSScreenshotSize::WindowResolution));
|
||||
SettingWidgetBinder::BindWidgetToIntSetting(
|
||||
sif, m_ui.screenshotFormat, "EmuCore/GS", "ScreenshotFormat", static_cast<int>(GSScreenshotFormat::PNG));
|
||||
SettingWidgetBinder::BindWidgetToIntSetting(sif, m_ui.screenshotQuality, "EmuCore/GS", "ScreenshotQuality", 50);
|
||||
SettingWidgetBinder::BindWidgetToFloatSetting(sif, m_ui.stretchY, "EmuCore/GS", "StretchY", 100.0f);
|
||||
SettingWidgetBinder::BindWidgetToIntSetting(sif, m_ui.cropLeft, "EmuCore/GS", "CropLeft", 0);
|
||||
|
@ -114,7 +117,8 @@ GraphicsSettingsWidget::GraphicsSettingsWidget(SettingsDialog* dialog, QWidget*
|
|||
SettingWidgetBinder::BindWidgetToIntSetting(sif, m_ui.cropRight, "EmuCore/GS", "CropRight", 0);
|
||||
SettingWidgetBinder::BindWidgetToIntSetting(sif, m_ui.cropBottom, "EmuCore/GS", "CropBottom", 0);
|
||||
|
||||
connect(m_ui.fullscreenModes, QOverload<int>::of(&QComboBox::currentIndexChanged), this, &GraphicsSettingsWidget::onFullscreenModeChanged);
|
||||
connect(
|
||||
m_ui.fullscreenModes, QOverload<int>::of(&QComboBox::currentIndexChanged), this, &GraphicsSettingsWidget::onFullscreenModeChanged);
|
||||
|
||||
//////////////////////////////////////////////////////////////////////////
|
||||
// OSD Settings
|
||||
|
@ -147,55 +151,33 @@ GraphicsSettingsWidget::GraphicsSettingsWidget(SettingsDialog* dialog, QWidget*
|
|||
//////////////////////////////////////////////////////////////////////////
|
||||
// HW Settings
|
||||
//////////////////////////////////////////////////////////////////////////
|
||||
static const char* upscale_entries[] = {
|
||||
"Native (PS2) (Default)",
|
||||
"1.25x Native",
|
||||
"1.5x Native",
|
||||
"1.75x Native",
|
||||
"2x Native (~720p)",
|
||||
"2.25x Native",
|
||||
"2.5x Native",
|
||||
"2.75x Native",
|
||||
"3x Native (~1080p)",
|
||||
"3.5x Native",
|
||||
"4x Native (~1440p/2K)",
|
||||
"5x Native (~1620p)",
|
||||
"6x Native (~2160p/4K)",
|
||||
"7x Native (~2520p)",
|
||||
"8x Native (~2880p/5K)",
|
||||
nullptr};
|
||||
static const char* upscale_entries[] = {"Native (PS2) (Default)", "1.25x Native", "1.5x Native", "1.75x Native", "2x Native (~720p)",
|
||||
"2.25x Native", "2.5x Native", "2.75x Native", "3x Native (~1080p)", "3.5x Native", "4x Native (~1440p/2K)", "5x Native (~1620p)",
|
||||
"6x Native (~2160p/4K)", "7x Native (~2520p)", "8x Native (~2880p/5K)", nullptr};
|
||||
static const char* upscale_values[] = {
|
||||
"1",
|
||||
"1.25",
|
||||
"1.5",
|
||||
"1.75",
|
||||
"2",
|
||||
"2.25",
|
||||
"2.5",
|
||||
"2.75",
|
||||
"3",
|
||||
"3.5",
|
||||
"4",
|
||||
"5",
|
||||
"6",
|
||||
"7",
|
||||
"8",
|
||||
nullptr };
|
||||
SettingWidgetBinder::BindWidgetToEnumSetting(sif, m_ui.upscaleMultiplier, "EmuCore/GS", "upscale_multiplier", upscale_entries, upscale_values, "1.0");
|
||||
SettingWidgetBinder::BindWidgetToIntSetting(sif, m_ui.textureFiltering, "EmuCore/GS", "filter", static_cast<int>(BiFiltering::PS2));
|
||||
SettingWidgetBinder::BindWidgetToIntSetting(sif, m_ui.trilinearFiltering, "EmuCore/GS", "TriFilter", static_cast<int>(TriFiltering::Automatic), -1);
|
||||
"1", "1.25", "1.5", "1.75", "2", "2.25", "2.5", "2.75", "3", "3.5", "4", "5", "6", "7", "8", nullptr};
|
||||
SettingWidgetBinder::BindWidgetToEnumSetting(
|
||||
sif, m_ui.anisotropicFiltering, "EmuCore/GS", "MaxAnisotropy", s_anisotropic_filtering_entries, s_anisotropic_filtering_values, "0");
|
||||
sif, m_ui.upscaleMultiplier, "EmuCore/GS", "upscale_multiplier", upscale_entries, upscale_values, "1.0");
|
||||
SettingWidgetBinder::BindWidgetToIntSetting(sif, m_ui.textureFiltering, "EmuCore/GS", "filter", static_cast<int>(BiFiltering::PS2));
|
||||
SettingWidgetBinder::BindWidgetToIntSetting(
|
||||
sif, m_ui.trilinearFiltering, "EmuCore/GS", "TriFilter", static_cast<int>(TriFiltering::Automatic), -1);
|
||||
SettingWidgetBinder::BindWidgetToEnumSetting(sif, m_ui.anisotropicFiltering, "EmuCore/GS", "MaxAnisotropy",
|
||||
s_anisotropic_filtering_entries, s_anisotropic_filtering_values, "0");
|
||||
SettingWidgetBinder::BindWidgetToIntSetting(sif, m_ui.dithering, "EmuCore/GS", "dithering_ps2", 2);
|
||||
SettingWidgetBinder::BindWidgetToIntSetting(sif, m_ui.mipmapping, "EmuCore/GS", "mipmap_hw", static_cast<int>(HWMipmapLevel::Automatic), -1);
|
||||
SettingWidgetBinder::BindWidgetToIntSetting(sif, m_ui.crcFixLevel, "EmuCore/GS", "crc_hack_level", static_cast<int>(CRCHackLevel::Automatic), -1);
|
||||
SettingWidgetBinder::BindWidgetToIntSetting(sif, m_ui.blending, "EmuCore/GS", "accurate_blending_unit", static_cast<int>(AccBlendLevel::Basic));
|
||||
SettingWidgetBinder::BindWidgetToIntSetting(
|
||||
sif, m_ui.mipmapping, "EmuCore/GS", "mipmap_hw", static_cast<int>(HWMipmapLevel::Automatic), -1);
|
||||
SettingWidgetBinder::BindWidgetToIntSetting(
|
||||
sif, m_ui.crcFixLevel, "EmuCore/GS", "crc_hack_level", static_cast<int>(CRCHackLevel::Automatic), -1);
|
||||
SettingWidgetBinder::BindWidgetToIntSetting(
|
||||
sif, m_ui.blending, "EmuCore/GS", "accurate_blending_unit", static_cast<int>(AccBlendLevel::Basic));
|
||||
SettingWidgetBinder::BindWidgetToBoolSetting(sif, m_ui.gpuPaletteConversion, "EmuCore/GS", "paltex", false);
|
||||
SettingWidgetBinder::BindWidgetToIntSetting(sif, m_ui.texturePreloading, "EmuCore/GS", "texture_preloading",
|
||||
static_cast<int>(TexturePreloadingLevel::Off));
|
||||
SettingWidgetBinder::BindWidgetToIntSetting(
|
||||
sif, m_ui.texturePreloading, "EmuCore/GS", "texture_preloading", static_cast<int>(TexturePreloadingLevel::Off));
|
||||
|
||||
connect(m_ui.trilinearFiltering, QOverload<int>::of(&QComboBox::currentIndexChanged), this, &GraphicsSettingsWidget::onTrilinearFilteringChanged);
|
||||
connect(m_ui.gpuPaletteConversion, QOverload<int>::of(&QCheckBox::stateChanged), this, &GraphicsSettingsWidget::onGpuPaletteConversionChanged);
|
||||
connect(m_ui.trilinearFiltering, QOverload<int>::of(&QComboBox::currentIndexChanged), this,
|
||||
&GraphicsSettingsWidget::onTrilinearFilteringChanged);
|
||||
connect(m_ui.gpuPaletteConversion, QOverload<int>::of(&QCheckBox::stateChanged), this,
|
||||
&GraphicsSettingsWidget::onGpuPaletteConversionChanged);
|
||||
onTrilinearFilteringChanged();
|
||||
onGpuPaletteConversionChanged(m_ui.gpuPaletteConversion->checkState());
|
||||
|
||||
|
@ -213,7 +195,8 @@ GraphicsSettingsWidget::GraphicsSettingsWidget(SettingsDialog* dialog, QWidget*
|
|||
SettingWidgetBinder::BindWidgetToBoolSetting(sif, m_ui.disableDepthEmulation, "EmuCore/GS", "UserHacks_DisableDepthSupport", false);
|
||||
SettingWidgetBinder::BindWidgetToBoolSetting(sif, m_ui.disableSafeFeatures, "EmuCore/GS", "UserHacks_Disable_Safe_Features", false);
|
||||
SettingWidgetBinder::BindWidgetToBoolSetting(sif, m_ui.preloadFrameData, "EmuCore/GS", "preload_frame_with_gs_data", false);
|
||||
SettingWidgetBinder::BindWidgetToBoolSetting(sif, m_ui.disablePartialInvalidation, "EmuCore/GS", "UserHacks_DisablePartialInvalidation", false);
|
||||
SettingWidgetBinder::BindWidgetToBoolSetting(
|
||||
sif, m_ui.disablePartialInvalidation, "EmuCore/GS", "UserHacks_DisablePartialInvalidation", false);
|
||||
SettingWidgetBinder::BindWidgetToBoolSetting(sif, m_ui.textureInsideRt, "EmuCore/GS", "UserHacks_TextureInsideRt", false);
|
||||
|
||||
//////////////////////////////////////////////////////////////////////////
|
||||
|
@ -234,7 +217,8 @@ GraphicsSettingsWidget::GraphicsSettingsWidget(SettingsDialog* dialog, QWidget*
|
|||
SettingWidgetBinder::BindWidgetToBoolSetting(sif, m_ui.dumpReplaceableMipmaps, "EmuCore/GS", "DumpReplaceableMipmaps", false);
|
||||
SettingWidgetBinder::BindWidgetToBoolSetting(sif, m_ui.dumpTexturesWithFMVActive, "EmuCore/GS", "DumpTexturesWithFMVActive", false);
|
||||
SettingWidgetBinder::BindWidgetToBoolSetting(sif, m_ui.loadTextureReplacements, "EmuCore/GS", "LoadTextureReplacements", false);
|
||||
SettingWidgetBinder::BindWidgetToBoolSetting(sif, m_ui.loadTextureReplacementsAsync, "EmuCore/GS", "LoadTextureReplacementsAsync", true);
|
||||
SettingWidgetBinder::BindWidgetToBoolSetting(
|
||||
sif, m_ui.loadTextureReplacementsAsync, "EmuCore/GS", "LoadTextureReplacementsAsync", true);
|
||||
SettingWidgetBinder::BindWidgetToBoolSetting(sif, m_ui.precacheTextureReplacements, "EmuCore/GS", "PrecacheTextureReplacements", false);
|
||||
SettingWidgetBinder::BindWidgetToFolderSetting(sif, m_ui.texturesDirectory, m_ui.texturesBrowse, m_ui.texturesOpen, m_ui.texturesReset,
|
||||
"Folders", "Textures", Path::Combine(EmuFolders::DataRoot, "textures"));
|
||||
|
@ -248,10 +232,12 @@ GraphicsSettingsWidget::GraphicsSettingsWidget(SettingsDialog* dialog, QWidget*
|
|||
SettingWidgetBinder::BindWidgetToBoolSetting(sif, m_ui.threadedPresentation, "EmuCore/GS", "DisableThreadedPresentation", false);
|
||||
SettingWidgetBinder::BindWidgetToIntSetting(sif, m_ui.overrideTextureBarriers, "EmuCore/GS", "OverrideTextureBarriers", -1, -1);
|
||||
SettingWidgetBinder::BindWidgetToIntSetting(sif, m_ui.overrideGeometryShader, "EmuCore/GS", "OverrideGeometryShaders", -1, -1);
|
||||
SettingWidgetBinder::BindWidgetToIntSetting(sif, m_ui.gsDumpCompression, "EmuCore/GS", "GSDumpCompression", static_cast<int>(GSDumpCompressionMethod::Zstandard));
|
||||
SettingWidgetBinder::BindWidgetToIntSetting(
|
||||
sif, m_ui.gsDumpCompression, "EmuCore/GS", "GSDumpCompression", static_cast<int>(GSDumpCompressionMethod::Zstandard));
|
||||
SettingWidgetBinder::BindWidgetToBoolSetting(sif, m_ui.disableFramebufferFetch, "EmuCore/GS", "DisableFramebufferFetch", false);
|
||||
SettingWidgetBinder::BindWidgetToBoolSetting(sif, m_ui.disableDualSource, "EmuCore/GS", "DisableDualSourceBlend", false);
|
||||
SettingWidgetBinder::BindWidgetToIntSetting(sif, m_ui.gsDownloadMode, "EmuCore/GS", "HWDownloadMode", static_cast<int>(GSHardwareDownloadMode::Enabled));
|
||||
SettingWidgetBinder::BindWidgetToIntSetting(
|
||||
sif, m_ui.gsDownloadMode, "EmuCore/GS", "HWDownloadMode", static_cast<int>(GSHardwareDownloadMode::Enabled));
|
||||
|
||||
//////////////////////////////////////////////////////////////////////////
|
||||
// SW Settings
|
||||
|
@ -315,27 +301,53 @@ GraphicsSettingsWidget::GraphicsSettingsWidget(SettingsDialog* dialog, QWidget*
|
|||
|
||||
// Capture settings
|
||||
{
|
||||
for (const char** container = Pcsx2Config::GSOptions::VideoCaptureContainers; *container; container++)
|
||||
for (const char** container = Pcsx2Config::GSOptions::CaptureContainers; *container; container++)
|
||||
{
|
||||
const QString name(QString::fromUtf8(*container));
|
||||
m_ui.videoCaptureContainer->addItem(name.toUpper(), name);
|
||||
m_ui.captureContainer->addItem(name.toUpper(), name);
|
||||
}
|
||||
|
||||
SettingWidgetBinder::BindWidgetToFolderSetting(sif, m_ui.videoDumpingDirectory, m_ui.videoDumpingDirectoryBrowse, m_ui.videoDumpingDirectoryOpen, m_ui.videoDumpingDirectoryReset,
|
||||
"Folders", "Videos", Path::Combine(EmuFolders::DataRoot, "videos"));
|
||||
SettingWidgetBinder::BindWidgetToFolderSetting(sif, m_ui.videoDumpingDirectory, m_ui.videoDumpingDirectoryBrowse,
|
||||
m_ui.videoDumpingDirectoryOpen, m_ui.videoDumpingDirectoryReset, "Folders", "Videos",
|
||||
Path::Combine(EmuFolders::DataRoot, "videos"));
|
||||
|
||||
SettingWidgetBinder::BindWidgetToStringSetting(sif, m_ui.videoCaptureContainer, "EmuCore/GS", "VideoCaptureContainer");
|
||||
connect(m_ui.videoCaptureContainer, &QComboBox::currentIndexChanged, this, &GraphicsSettingsWidget::onVideoCaptureContainerChanged);
|
||||
SettingWidgetBinder::BindWidgetToStringSetting(sif, m_ui.captureContainer, "EmuCore/GS", "CaptureContainer");
|
||||
connect(m_ui.captureContainer, &QComboBox::currentIndexChanged, this, &GraphicsSettingsWidget::onCaptureContainerChanged);
|
||||
|
||||
SettingWidgetBinder::BindWidgetToBoolSetting(sif, m_ui.enableVideoCapture, "EmuCore/GS", "EnableVideoCapture", true);
|
||||
SettingWidgetBinder::BindWidgetToIntSetting(
|
||||
sif, m_ui.videoCaptureBitrate, "EmuCore/GS", "VideoCaptureBitrate", Pcsx2Config::GSOptions::DEFAULT_VIDEO_CAPTURE_BITRATE);
|
||||
|
||||
SettingWidgetBinder::BindWidgetToBoolSetting(sif, m_ui.enableVideoCaptureArguments, "EmuCore/GS", "EnableVideoCaptureParameters", false);
|
||||
SettingWidgetBinder::BindWidgetToIntSetting(
|
||||
sif, m_ui.videoCaptureWidth, "EmuCore/GS", "VideoCaptureWidth", Pcsx2Config::GSOptions::DEFAULT_VIDEO_CAPTURE_WIDTH);
|
||||
SettingWidgetBinder::BindWidgetToIntSetting(
|
||||
sif, m_ui.videoCaptureHeight, "EmuCore/GS", "VideoCaptureHeight", Pcsx2Config::GSOptions::DEFAULT_VIDEO_CAPTURE_HEIGHT);
|
||||
SettingWidgetBinder::BindWidgetToBoolSetting(
|
||||
sif, m_ui.videoCaptureResolutionAuto, "EmuCore/GS", "VideoCaptureAutoResolution", true);
|
||||
SettingWidgetBinder::BindWidgetToBoolSetting(
|
||||
sif, m_ui.enableVideoCaptureArguments, "EmuCore/GS", "EnableVideoCaptureParameters", false);
|
||||
SettingWidgetBinder::BindWidgetToStringSetting(sif, m_ui.videoCaptureArguments, "EmuCore/GS", "VideoCaptureParameters");
|
||||
connect(m_ui.enableVideoCaptureArguments, &QCheckBox::stateChanged, this, &GraphicsSettingsWidget::onEnableVideoCaptureArgumentsChanged);
|
||||
connect(m_ui.enableVideoCapture, &QCheckBox::stateChanged, this, &GraphicsSettingsWidget::onEnableVideoCaptureChanged);
|
||||
connect(
|
||||
m_ui.videoCaptureResolutionAuto, &QCheckBox::stateChanged, this, &GraphicsSettingsWidget::onVideoCaptureAutoResolutionChanged);
|
||||
connect(m_ui.enableVideoCaptureArguments, &QCheckBox::stateChanged, this,
|
||||
&GraphicsSettingsWidget::onEnableVideoCaptureArgumentsChanged);
|
||||
|
||||
onVideoCaptureContainerChanged();
|
||||
SettingWidgetBinder::BindWidgetToBoolSetting(sif, m_ui.enableAudioCapture, "EmuCore/GS", "EnableAudioCapture", true);
|
||||
SettingWidgetBinder::BindWidgetToIntSetting(
|
||||
sif, m_ui.audioCaptureBitrate, "EmuCore/GS", "AudioCaptureBitrate", Pcsx2Config::GSOptions::DEFAULT_AUDIO_CAPTURE_BITRATE);
|
||||
SettingWidgetBinder::BindWidgetToBoolSetting(
|
||||
sif, m_ui.enableAudioCaptureArguments, "EmuCore/GS", "EnableAudioCaptureParameters", false);
|
||||
SettingWidgetBinder::BindWidgetToStringSetting(sif, m_ui.audioCaptureArguments, "EmuCore/GS", "AudioCaptureParameters");
|
||||
connect(m_ui.enableAudioCapture, &QCheckBox::stateChanged, this, &GraphicsSettingsWidget::onEnableAudioCaptureChanged);
|
||||
connect(m_ui.enableAudioCaptureArguments, &QCheckBox::stateChanged, this,
|
||||
&GraphicsSettingsWidget::onEnableAudioCaptureArgumentsChanged);
|
||||
|
||||
onCaptureContainerChanged();
|
||||
onEnableVideoCaptureChanged();
|
||||
onEnableVideoCaptureArgumentsChanged();
|
||||
onVideoCaptureAutoResolutionChanged();
|
||||
onEnableAudioCaptureChanged();
|
||||
onEnableAudioCaptureArgumentsChanged();
|
||||
}
|
||||
|
||||
// Display tab
|
||||
|
@ -350,39 +362,45 @@ GraphicsSettingsWidget::GraphicsSettingsWidget(SettingsDialog* dialog, QWidget*
|
|||
tr("Disables interlacing offset which may reduce blurring in some situations."));
|
||||
|
||||
dialog->registerWidgetHelp(m_ui.bilinearFiltering, tr("Bilinear Filtering"), tr("Bilinear (Smooth)"),
|
||||
tr("Enables bilinear post processing filter. Smooths the overall picture as it is displayed on the screen. Corrects positioning between pixels."));
|
||||
tr("Enables bilinear post processing filter. Smooths the overall picture as it is displayed on the screen. Corrects "
|
||||
"positioning between pixels."));
|
||||
|
||||
dialog->registerWidgetHelp(m_ui.PCRTCOffsets, tr("Screen Offsets"), tr("Unchecked"),
|
||||
tr("Enables PCRTC Offsets which position the screen as the game requests. Useful for some games such as WipEout Fusion for its screen shake effect, but can make the picture blurry."));
|
||||
tr("Enables PCRTC Offsets which position the screen as the game requests. Useful for some games such as WipEout Fusion for its "
|
||||
"screen shake effect, but can make the picture blurry."));
|
||||
|
||||
dialog->registerWidgetHelp(m_ui.PCRTCOverscan, tr("Show Overscan"), tr("Unchecked"),
|
||||
tr("Enables the option to show the overscan area on games which draw more than the safe area of the screen."));
|
||||
|
||||
dialog->registerWidgetHelp(m_ui.fmvAspectRatio, tr("FMV Aspect Ratio"), tr("Off (Default)"),
|
||||
tr("Overrides the FMV aspect ratio."));
|
||||
|
||||
dialog->registerWidgetHelp(m_ui.fmvAspectRatio, tr("FMV Aspect Ratio"), tr("Off (Default)"), tr("Overrides the FMV aspect ratio."));
|
||||
|
||||
dialog->registerWidgetHelp(m_ui.PCRTCAntiBlur, tr("Anti-Blur"), tr("Checked"),
|
||||
tr("Enables internal Anti-Blur hacks. Less accurate to PS2 rendering but will make a lot of games look less blurry."));
|
||||
|
||||
|
||||
dialog->registerWidgetHelp(m_ui.vsync, tr("VSync"), tr("Unchecked"),
|
||||
tr("Enable this option to match PCSX2's refresh rate with your current monitor or screen. VSync is automatically disabled when it is not possible (eg. running at non-100% speed)."));
|
||||
tr("Enable this option to match PCSX2's refresh rate with your current monitor or screen. VSync is automatically disabled when "
|
||||
"it is not possible (eg. running at non-100% speed)."));
|
||||
|
||||
dialog->registerWidgetHelp(m_ui.integerScaling, tr("Integer Scaling"), tr("Unchecked"),
|
||||
tr("Adds padding to the display area to ensure that the ratio between pixels on the host to pixels in the console is an integer number. May result in a sharper image in some 2D games."));
|
||||
|
||||
tr("Adds padding to the display area to ensure that the ratio between pixels on the host to pixels in the console is an "
|
||||
"integer number. May result in a sharper image in some 2D games."));
|
||||
|
||||
dialog->registerWidgetHelp(m_ui.aspectRatio, tr("Aspect Ratio"), tr("Auto Standard (4:3/3:2 Progressive)"),
|
||||
tr("Changes the aspect ratio used to display the console's output to the screen. The default is Auto Standard (4:3/3:2 Progressive) which automatically adjusts the aspect ratio to match how a game would be shown on a typical TV of the era."));
|
||||
tr("Changes the aspect ratio used to display the console's output to the screen. The default is Auto Standard (4:3/3:2 "
|
||||
"Progressive) which automatically adjusts the aspect ratio to match how a game would be shown on a typical TV of the era."));
|
||||
|
||||
dialog->registerWidgetHelp(m_ui.interlacing, tr("Deinterlacing"), tr("Automatic (Default)"), tr(""));
|
||||
|
||||
dialog->registerWidgetHelp(m_ui.screenshotSize, tr("Screenshot Size"), tr("Screen Resolution"),
|
||||
tr("Determines the resolution at which screenshots will be saved. Internal resolutions preserve more detail at the cost of file size."));
|
||||
tr("Determines the resolution at which screenshots will be saved. Internal resolutions preserve more detail at the cost of "
|
||||
"file size."));
|
||||
|
||||
dialog->registerWidgetHelp(m_ui.screenshotFormat, tr("Screenshot Format"), tr("PNG"),
|
||||
tr("Selects the format which will be used to save screenshots. JPEG produces smaller files, but loses detail."));
|
||||
|
||||
dialog->registerWidgetHelp(m_ui.screenshotQuality, tr("Screenshot Quality"), tr("50%"),
|
||||
tr("Selects the quality at which screenshots will be compressed. Higher values preserve more detail for JPEG, and reduce file size for PNG."));
|
||||
tr("Selects the quality at which screenshots will be compressed. Higher values preserve more detail for JPEG, and reduce file "
|
||||
"size for PNG."));
|
||||
|
||||
dialog->registerWidgetHelp(m_ui.stretchY, tr("Stretch Height"), tr("100%"), tr(""));
|
||||
|
||||
|
@ -403,11 +421,11 @@ GraphicsSettingsWidget::GraphicsSettingsWidget(SettingsDialog* dialog, QWidget*
|
|||
// Hardware
|
||||
dialog->registerWidgetHelp(m_ui.upscaleMultiplier, tr("Internal Resolution"), tr("Native (PS2) (Default)"), tr(""));
|
||||
|
||||
dialog->registerWidgetHelp(m_ui.mipmapping, tr("Mipmapping"), tr("Automatic (Default)"),
|
||||
tr("Control the accuracy level of the mipmapping emulation."));
|
||||
dialog->registerWidgetHelp(
|
||||
m_ui.mipmapping, tr("Mipmapping"), tr("Automatic (Default)"), tr("Control the accuracy level of the mipmapping emulation."));
|
||||
|
||||
dialog->registerWidgetHelp(m_ui.textureFiltering, tr("Texture Filtering"), tr("Bilinear (PS2)"),
|
||||
tr("Control the texture filtering of the emulation."));
|
||||
dialog->registerWidgetHelp(
|
||||
m_ui.textureFiltering, tr("Texture Filtering"), tr("Bilinear (PS2)"), tr("Control the texture filtering of the emulation."));
|
||||
|
||||
dialog->registerWidgetHelp(m_ui.trilinearFiltering, tr("Trilinear Filtering"), tr("Automatic (Default)"),
|
||||
tr("Control the texture tri-filtering of the emulation."));
|
||||
|
@ -426,7 +444,8 @@ GraphicsSettingsWidget::GraphicsSettingsWidget(SettingsDialog* dialog, QWidget*
|
|||
|
||||
dialog->registerWidgetHelp(m_ui.blending, tr("Blending Accuracy"), tr("Basic (Recommended)"),
|
||||
tr("Control the accuracy level of the GS blending unit emulation.<br> "
|
||||
"The higher the setting, the more blending is emulated in the shader accurately, and the higher the speed penalty will be.<br> "
|
||||
"The higher the setting, the more blending is emulated in the shader accurately, and the higher the speed penalty will "
|
||||
"be.<br> "
|
||||
"Do note that Direct3D's blending is reduced in capability compared to OpenGL/Vulkan"));
|
||||
|
||||
dialog->registerWidgetHelp(m_ui.texturePreloading, tr("Texture Preloading"), tr("Full (Hash Cache)"),
|
||||
|
@ -453,15 +472,16 @@ GraphicsSettingsWidget::GraphicsSettingsWidget(SettingsDialog* dialog, QWidget*
|
|||
// Software
|
||||
dialog->registerWidgetHelp(m_ui.extraSWThreads, tr("Extra Rendering Threads"), tr("2 threads"),
|
||||
tr("Number of rendering threads: 0 for single thread, 2 or more for multithread (1 is for debugging). "
|
||||
"If you have 4 threads on your CPU pick 2 or 3. You can calculate how to get the best performance (amount of CPU threads - 2). "
|
||||
"If you have 4 threads on your CPU pick 2 or 3. You can calculate how to get the best performance (amount of CPU threads - "
|
||||
"2). "
|
||||
"7+ threads will not give much more performance and could perhaps even lower it."));
|
||||
|
||||
dialog->registerWidgetHelp(m_ui.swAutoFlush, tr("Auto Flush"), tr("Checked"),
|
||||
tr("Force a primitive flush when a framebuffer is also an input texture. "
|
||||
"Fixes some processing effects such as the shadows in the Jak series and radiosity in GTA:SA."));
|
||||
|
||||
dialog->registerWidgetHelp(m_ui.swMipmap, tr("Mipmapping"), tr("Checked"),
|
||||
tr("Enables mipmapping, which some games require to render correctly."));
|
||||
dialog->registerWidgetHelp(
|
||||
m_ui.swMipmap, tr("Mipmapping"), tr("Checked"), tr("Enables mipmapping, which some games require to render correctly."));
|
||||
}
|
||||
|
||||
// Hardware Fixes tab
|
||||
|
@ -490,7 +510,8 @@ GraphicsSettingsWidget::GraphicsSettingsWidget(SettingsDialog* dialog, QWidget*
|
|||
dialog->registerWidgetHelp(m_ui.disableSafeFeatures, tr("Disable Safe Features"), tr("Unchecked"),
|
||||
tr("This option disables multiple safe features. "
|
||||
"Disables accurate Unscale Point and Line rendering which can help Xenosaga games. "
|
||||
"Disables accurate GS Memory Clearing to be done on the CPU, and let the GPU handle it, which can help Kingdom Hearts games."));
|
||||
"Disables accurate GS Memory Clearing to be done on the CPU, and let the GPU handle it, which can help Kingdom Hearts "
|
||||
"games."));
|
||||
|
||||
dialog->registerWidgetHelp(m_ui.disablePartialInvalidation, tr("Disable Partial Invalidation"), tr("Unchecked"),
|
||||
tr("By default, the texture cache handles partial invalidations. Unfortunately it is very costly to compute CPU wise. "
|
||||
|
@ -516,13 +537,16 @@ GraphicsSettingsWidget::GraphicsSettingsWidget(SettingsDialog* dialog, QWidget*
|
|||
|
||||
dialog->registerWidgetHelp(m_ui.roundSprite, tr("Round Sprite"), tr("Off (Default)"),
|
||||
tr("Corrects the sampling of 2D sprite textures when upscaling. "
|
||||
"Fixes lines in sprites of games like Ar tonelico when upscaling. Half option is for flat sprites, Full is for all sprites."));
|
||||
"Fixes lines in sprites of games like Ar tonelico when upscaling. Half option is for flat sprites, Full is for all "
|
||||
"sprites."));
|
||||
|
||||
dialog->registerWidgetHelp(m_ui.textureOffsetX, tr("Texture Offsets X"), tr("0"),
|
||||
tr("Offset for the ST/UV texture coordinates. Fixes some odd texture issues and might fix some post processing alignment too."));
|
||||
tr("Offset for the ST/UV texture coordinates. Fixes some odd texture issues and might fix some post processing alignment "
|
||||
"too."));
|
||||
|
||||
dialog->registerWidgetHelp(m_ui.textureOffsetY, tr("Texture Offsets Y"), tr("0"),
|
||||
tr("Offset for the ST/UV texture coordinates. Fixes some odd texture issues and might fix some post processing alignment too."));
|
||||
tr("Offset for the ST/UV texture coordinates. Fixes some odd texture issues and might fix some post processing alignment "
|
||||
"too."));
|
||||
|
||||
dialog->registerWidgetHelp(m_ui.alignSprite, tr("Align Sprite"), tr("Unchecked"),
|
||||
tr("Fixes issues with upscaling(vertical lines) in Namco games like Ace Combat, Tekken, Soul Calibur, etc."));
|
||||
|
@ -556,10 +580,11 @@ GraphicsSettingsWidget::GraphicsSettingsWidget(SettingsDialog* dialog, QWidget*
|
|||
dialog->registerWidgetHelp(m_ui.casSharpness, tr("Sharpness"), tr("50%"), tr(""));
|
||||
|
||||
dialog->registerWidgetHelp(m_ui.shadeBoost, tr("Shade Boost"), tr("Unchecked"),
|
||||
tr("Enables saturation, contrast, and brightness to be adjusted. Values of brightness, saturation, and contrast are at default 50."));
|
||||
tr("Enables saturation, contrast, and brightness to be adjusted. Values of brightness, saturation, and contrast are at default "
|
||||
"50."));
|
||||
|
||||
dialog->registerWidgetHelp(m_ui.fxaa, tr("FXAA"), tr("Unchecked"),
|
||||
tr("Applies the FXAA anti-aliasing algorithm to improve the visual quality of games."));
|
||||
dialog->registerWidgetHelp(
|
||||
m_ui.fxaa, tr("FXAA"), tr("Unchecked"), tr("Applies the FXAA anti-aliasing algorithm to improve the visual quality of games."));
|
||||
|
||||
dialog->registerWidgetHelp(m_ui.shadeBoostBrightness, tr("Brightness"), tr("50"), tr(""));
|
||||
|
||||
|
@ -572,8 +597,8 @@ GraphicsSettingsWidget::GraphicsSettingsWidget(SettingsDialog* dialog, QWidget*
|
|||
|
||||
// OSD tab
|
||||
{
|
||||
dialog->registerWidgetHelp(m_ui.osdScale, tr("OSD Scale"), tr("100%"),
|
||||
tr("Scales the size of the onscreen OSD from 100% to 500%."));
|
||||
dialog->registerWidgetHelp(
|
||||
m_ui.osdScale, tr("OSD Scale"), tr("100%"), tr("Scales the size of the onscreen OSD from 100% to 500%."));
|
||||
|
||||
dialog->registerWidgetHelp(m_ui.osdShowMessages, tr("Show OSD Messages"), tr("Checked"),
|
||||
tr("Shows on-screen-display messages when events occur such as save states being "
|
||||
|
@ -588,11 +613,9 @@ GraphicsSettingsWidget::GraphicsSettingsWidget(SettingsDialog* dialog, QWidget*
|
|||
dialog->registerWidgetHelp(m_ui.osdShowResolution, tr("Show Resolution"), tr("Unchecked"),
|
||||
tr("Shows the resolution of the game in the top-right corner of the display."));
|
||||
|
||||
dialog->registerWidgetHelp(m_ui.osdShowCPU, tr("Show CPU Usage"), tr("Unchecked"),
|
||||
tr("Shows host's CPU utilization."));
|
||||
dialog->registerWidgetHelp(m_ui.osdShowCPU, tr("Show CPU Usage"), tr("Unchecked"), tr("Shows host's CPU utilization."));
|
||||
|
||||
dialog->registerWidgetHelp(m_ui.osdShowGPU, tr("Show GPU Usage"), tr("Unchecked"),
|
||||
tr("Shows host's GPU utilization."));
|
||||
dialog->registerWidgetHelp(m_ui.osdShowGPU, tr("Show GPU Usage"), tr("Unchecked"), tr("Shows host's GPU utilization."));
|
||||
|
||||
dialog->registerWidgetHelp(m_ui.osdShowGSStats, tr("Show Statistics"), tr("Unchecked"),
|
||||
tr("Shows counters for internal graphical utilization, useful for debugging."));
|
||||
|
@ -601,23 +624,23 @@ GraphicsSettingsWidget::GraphicsSettingsWidget(SettingsDialog* dialog, QWidget*
|
|||
tr("Shows OSD icon indicators for emulation states such as Pausing, Turbo, Fast Forward, and Slow Motion."));
|
||||
|
||||
dialog->registerWidgetHelp(m_ui.osdShowSettings, tr("Show Settings"), tr("Unchecked"),
|
||||
tr("Displays various settings and the current values of those settings, useful for debugging."));
|
||||
tr("Displays various settings and the current values of those settings, useful for debugging."));
|
||||
|
||||
dialog->registerWidgetHelp(m_ui.osdShowInputs, tr("Show Inputs"), tr("Unchecked"),
|
||||
tr("Shows the current controler state of the system in the bottom left corner of the display."));
|
||||
tr("Shows the current controler state of the system in the bottom left corner of the display."));
|
||||
|
||||
dialog->registerWidgetHelp(m_ui.osdShowFrameTimes, tr("Show Frame Times"), tr("Unchecked"),
|
||||
tr("Displays a graph showing the average frametimes."));
|
||||
dialog->registerWidgetHelp(
|
||||
m_ui.osdShowFrameTimes, tr("Show Frame Times"), tr("Unchecked"), tr("Displays a graph showing the average frametimes."));
|
||||
|
||||
dialog->registerWidgetHelp(m_ui.warnAboutUnsafeSettings, tr("Warn About Unsafe Settings"),
|
||||
tr("Checked"), tr("Displays warnings when settings are enabled which may break games."));
|
||||
dialog->registerWidgetHelp(m_ui.warnAboutUnsafeSettings, tr("Warn About Unsafe Settings"), tr("Checked"),
|
||||
tr("Displays warnings when settings are enabled which may break games."));
|
||||
}
|
||||
|
||||
// Recording tab
|
||||
{
|
||||
dialog->registerWidgetHelp(m_ui.enableVideoCaptureArguments, tr("Enable Extra Arguments"), tr("Unchecked"), tr(""));
|
||||
|
||||
dialog->registerWidgetHelp(m_ui.videoCaptureArguments, tr("Extra Arguments"), tr("Leave It Blank"),
|
||||
dialog->registerWidgetHelp(m_ui.videoCaptureArguments, tr("Extra Arguments"), tr("Leave It Blank"),
|
||||
tr("Parameters passed to selected video codec.<br> "
|
||||
"You must use '=' to separate key from value and ':' to separate two pairs from each other.<br> "
|
||||
"For example: \"crf = 21 : preset = veryfast\""));
|
||||
|
@ -645,8 +668,10 @@ GraphicsSettingsWidget::GraphicsSettingsWidget(SettingsDialog* dialog, QWidget*
|
|||
dialog->registerWidgetHelp(m_ui.disableFramebufferFetch, tr("Disable Frame Buffer Fetch"), tr("Unchecked"), tr(""));
|
||||
|
||||
dialog->registerWidgetHelp(m_ui.skipPresentingDuplicateFrames, tr("Skip Presenting Duplicate Frames"), tr("Unchecked"),
|
||||
tr("Detects when idle frames are being presented in 25/30fps games, and skips presenting those frames. The frame is still rendered, it just means "
|
||||
"the GPU has more time to complete it (this is NOT frame skipping). Can smooth our frame time fluctuations when the CPU/GPU are near maximum "
|
||||
tr("Detects when idle frames are being presented in 25/30fps games, and skips presenting those frames. The frame is still "
|
||||
"rendered, it just means "
|
||||
"the GPU has more time to complete it (this is NOT frame skipping). Can smooth our frame time fluctuations when the CPU/GPU "
|
||||
"are near maximum "
|
||||
"utilization, but makes frame pacing more inconsistent and can increase input lag."));
|
||||
|
||||
dialog->registerWidgetHelp(m_ui.threadedPresentation, tr("Disable Threaded Presentation"), tr("Unchecked"),
|
||||
|
@ -725,9 +750,8 @@ void GraphicsSettingsWidget::onFullscreenModeChanged(int index)
|
|||
|
||||
void GraphicsSettingsWidget::onTrilinearFilteringChanged()
|
||||
{
|
||||
const bool forced_bilinear =
|
||||
(m_dialog->getEffectiveIntValue("EmuCore/GS", "TriFilter", static_cast<int>(TriFiltering::Automatic))
|
||||
>= static_cast<int>(TriFiltering::Forced));
|
||||
const bool forced_bilinear = (m_dialog->getEffectiveIntValue("EmuCore/GS", "TriFilter", static_cast<int>(TriFiltering::Automatic)) >=
|
||||
static_cast<int>(TriFiltering::Forced));
|
||||
m_ui.textureFiltering->setDisabled(forced_bilinear);
|
||||
}
|
||||
|
||||
|
@ -739,16 +763,15 @@ void GraphicsSettingsWidget::onShadeBoostChanged()
|
|||
m_ui.shadeBoostSaturation->setEnabled(enabled);
|
||||
}
|
||||
|
||||
void GraphicsSettingsWidget::onVideoCaptureContainerChanged()
|
||||
void GraphicsSettingsWidget::onCaptureContainerChanged()
|
||||
{
|
||||
const std::string container(
|
||||
m_dialog->getEffectiveStringValue("EmuCore/GS", "VideoCaptureContainer", Pcsx2Config::GSOptions::DEFAULT_VIDEO_CAPTURE_CONTAINER));
|
||||
m_dialog->getEffectiveStringValue("EmuCore/GS", "CaptureContainer", Pcsx2Config::GSOptions::DEFAULT_CAPTURE_CONTAINER));
|
||||
|
||||
m_ui.videoCaptureCodec->disconnect();
|
||||
m_ui.videoCaptureCodec->clear();
|
||||
const std::vector<std::pair<std::string, std::string>> vcapture_formats(GSCapture::GetVideoCodecList(container.c_str()));
|
||||
m_ui.videoCaptureCodec->addItem(tr("Default"), QString());
|
||||
for (const auto& [format, name] : vcapture_formats)
|
||||
for (const auto& [format, name] : GSCapture::GetVideoCodecList(container.c_str()))
|
||||
{
|
||||
const QString qformat(QString::fromStdString(format));
|
||||
const QString qname(QString::fromStdString(name));
|
||||
|
@ -757,6 +780,25 @@ void GraphicsSettingsWidget::onVideoCaptureContainerChanged()
|
|||
|
||||
SettingWidgetBinder::BindWidgetToStringSetting(
|
||||
m_dialog->getSettingsInterface(), m_ui.videoCaptureCodec, "EmuCore/GS", "VideoCaptureCodec");
|
||||
|
||||
m_ui.audioCaptureCodec->disconnect();
|
||||
m_ui.audioCaptureCodec->clear();
|
||||
m_ui.audioCaptureCodec->addItem(tr("Default"), QString());
|
||||
for (const auto& [format, name] : GSCapture::GetAudioCodecList(container.c_str()))
|
||||
{
|
||||
const QString qformat(QString::fromStdString(format));
|
||||
const QString qname(QString::fromStdString(name));
|
||||
m_ui.audioCaptureCodec->addItem(QStringLiteral("%1 [%2]").arg(qformat).arg(qname), qformat);
|
||||
}
|
||||
|
||||
SettingWidgetBinder::BindWidgetToStringSetting(
|
||||
m_dialog->getSettingsInterface(), m_ui.audioCaptureCodec, "EmuCore/GS", "AudioCaptureCodec");
|
||||
}
|
||||
|
||||
void GraphicsSettingsWidget::onEnableVideoCaptureChanged()
|
||||
{
|
||||
const bool enabled = m_dialog->getEffectiveBoolValue("EmuCore/GS", "EnableVideoCapture", true);
|
||||
m_ui.videoCaptureOptions->setEnabled(enabled);
|
||||
}
|
||||
|
||||
void GraphicsSettingsWidget::onEnableVideoCaptureArgumentsChanged()
|
||||
|
@ -765,6 +807,25 @@ void GraphicsSettingsWidget::onEnableVideoCaptureArgumentsChanged()
|
|||
m_ui.videoCaptureArguments->setEnabled(enabled);
|
||||
}
|
||||
|
||||
void GraphicsSettingsWidget::onVideoCaptureAutoResolutionChanged()
|
||||
{
|
||||
const bool enabled = !m_dialog->getEffectiveBoolValue("EmuCore/GS", "VideoCaptureAutoResolution", true);
|
||||
m_ui.videoCaptureWidth->setEnabled(enabled);
|
||||
m_ui.videoCaptureHeight->setEnabled(enabled);
|
||||
}
|
||||
|
||||
void GraphicsSettingsWidget::onEnableAudioCaptureChanged()
|
||||
{
|
||||
const bool enabled = m_dialog->getEffectiveBoolValue("EmuCore/GS", "EnableAudioCapture", true);
|
||||
m_ui.audioCaptureOptions->setEnabled(enabled);
|
||||
}
|
||||
|
||||
void GraphicsSettingsWidget::onEnableAudioCaptureArgumentsChanged()
|
||||
{
|
||||
const bool enabled = m_dialog->getEffectiveBoolValue("EmuCore/GS", "EnableAudioCaptureParameters", false);
|
||||
m_ui.audioCaptureArguments->setEnabled(enabled);
|
||||
}
|
||||
|
||||
void GraphicsSettingsWidget::onGpuPaletteConversionChanged(int state)
|
||||
{
|
||||
const bool enabled = state == Qt::CheckState::PartiallyChecked ? Host::GetBaseBoolSettingValue("EmuCore/GS", "paltex", false) : state;
|
||||
|
@ -791,7 +852,8 @@ void GraphicsSettingsWidget::updateRendererDependentOptions()
|
|||
const bool is_sw_dx = false;
|
||||
#endif
|
||||
|
||||
const bool is_hardware = (type == GSRendererType::DX11 || type == GSRendererType::DX12 || type == GSRendererType::OGL || type == GSRendererType::VK || type == GSRendererType::Metal);
|
||||
const bool is_hardware = (type == GSRendererType::DX11 || type == GSRendererType::DX12 || type == GSRendererType::OGL ||
|
||||
type == GSRendererType::VK || type == GSRendererType::Metal);
|
||||
const bool is_software = (type == GSRendererType::SW);
|
||||
const bool hw_fixes = (is_hardware && m_ui.enableHWFixes->checkState() == Qt::Checked);
|
||||
const int prev_tab = m_ui.tabs->currentIndex();
|
||||
|
|
|
@ -43,8 +43,12 @@ private Q_SLOTS:
|
|||
void onGpuPaletteConversionChanged(int state);
|
||||
void onFullscreenModeChanged(int index);
|
||||
void onShadeBoostChanged();
|
||||
void onVideoCaptureContainerChanged();
|
||||
void onCaptureContainerChanged();
|
||||
void onEnableVideoCaptureChanged();
|
||||
void onEnableVideoCaptureArgumentsChanged();
|
||||
void onVideoCaptureAutoResolutionChanged();
|
||||
void onEnableAudioCaptureChanged();
|
||||
void onEnableAudioCaptureArgumentsChanged();
|
||||
|
||||
private:
|
||||
GSRendererType getEffectiveRenderer() const;
|
||||
|
|
|
@ -6,8 +6,8 @@
|
|||
<rect>
|
||||
<x>0</x>
|
||||
<y>0</y>
|
||||
<width>861</width>
|
||||
<height>501</height>
|
||||
<width>720</width>
|
||||
<height>466</height>
|
||||
</rect>
|
||||
</property>
|
||||
<property name="windowTitle">
|
||||
|
@ -1663,8 +1663,7 @@
|
|||
<item>
|
||||
<layout class="QHBoxLayout" name="horizontalLayout_8">
|
||||
<item>
|
||||
<widget class="QLineEdit" name="videoDumpingDirectory">
|
||||
</widget>
|
||||
<widget class="QLineEdit" name="videoDumpingDirectory"/>
|
||||
</item>
|
||||
<item>
|
||||
<widget class="QPushButton" name="videoDumpingDirectoryBrowse">
|
||||
|
@ -1693,81 +1692,224 @@
|
|||
</widget>
|
||||
</item>
|
||||
<item>
|
||||
<widget class="QGroupBox" name="videoCaptureOptions">
|
||||
<widget class="QGroupBox" name="groupBox_2">
|
||||
<property name="title">
|
||||
<string>Capture Options</string>
|
||||
<string>Capture Setup</string>
|
||||
</property>
|
||||
<layout class="QFormLayout" name="videoCaptureFormLayout">
|
||||
<layout class="QFormLayout" name="formLayout_3">
|
||||
<item row="0" column="0">
|
||||
<widget class="QLabel" name="videoCaptureCodecLabel">
|
||||
<widget class="QLabel" name="captureContainerLabel">
|
||||
<property name="text">
|
||||
<string>Video Codec:</string>
|
||||
<string>Container:</string>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item row="0" column="1">
|
||||
<widget class="QComboBox" name="videoCaptureCodec"/>
|
||||
<widget class="QComboBox" name="captureContainer"/>
|
||||
</item>
|
||||
<item row="1" column="0">
|
||||
<spacer name="horizontalSpacer">
|
||||
<property name="orientation">
|
||||
<enum>Qt::Horizontal</enum>
|
||||
<item row="1" column="0" colspan="2">
|
||||
<layout class="QGridLayout" name="gridLayout_10" columnstretch="1,1">
|
||||
<property name="horizontalSpacing">
|
||||
<number>20</number>
|
||||
</property>
|
||||
<property name="sizeHint" stdset="0">
|
||||
<size>
|
||||
<width>40</width>
|
||||
<height>20</height>
|
||||
</size>
|
||||
<property name="verticalSpacing">
|
||||
<number>10</number>
|
||||
</property>
|
||||
</spacer>
|
||||
</item>
|
||||
<item row="1" column="1">
|
||||
<layout class="QHBoxLayout" name="horizontalLayout_9" stretch="0,0,0,0">
|
||||
<item>
|
||||
<widget class="QLabel" name="videoCaptureContainerLabel">
|
||||
<item row="1" column="1">
|
||||
<widget class="QWidget" name="audioCaptureOptions" native="true">
|
||||
<layout class="QFormLayout" name="formLayout_10">
|
||||
<property name="leftMargin">
|
||||
<number>0</number>
|
||||
</property>
|
||||
<property name="topMargin">
|
||||
<number>0</number>
|
||||
</property>
|
||||
<property name="rightMargin">
|
||||
<number>0</number>
|
||||
</property>
|
||||
<property name="bottomMargin">
|
||||
<number>0</number>
|
||||
</property>
|
||||
<item row="0" column="0">
|
||||
<widget class="QLabel" name="audioCaptureCodecLabel">
|
||||
<property name="text">
|
||||
<string>Codec:</string>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item row="0" column="1">
|
||||
<widget class="QComboBox" name="audioCaptureCodec"/>
|
||||
</item>
|
||||
<item row="1" column="0">
|
||||
<widget class="QLabel" name="audioCaptureBitrateLabel">
|
||||
<property name="text">
|
||||
<string>Bitrate:</string>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item row="1" column="1">
|
||||
<widget class="QSpinBox" name="audioCaptureBitrate">
|
||||
<property name="suffix">
|
||||
<string> kbps</string>
|
||||
</property>
|
||||
<property name="minimum">
|
||||
<number>16</number>
|
||||
</property>
|
||||
<property name="maximum">
|
||||
<number>2048</number>
|
||||
</property>
|
||||
<property name="singleStep">
|
||||
<number>1</number>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item row="2" column="0" colspan="2">
|
||||
<widget class="QCheckBox" name="enableAudioCaptureArguments">
|
||||
<property name="text">
|
||||
<string>Extra Arguments</string>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item row="3" column="0" colspan="2">
|
||||
<widget class="QLineEdit" name="audioCaptureArguments"/>
|
||||
</item>
|
||||
</layout>
|
||||
</widget>
|
||||
</item>
|
||||
<item row="0" column="1">
|
||||
<widget class="QCheckBox" name="enableAudioCapture">
|
||||
<property name="text">
|
||||
<string>Container:</string>
|
||||
<string>Capture Audio</string>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item>
|
||||
<widget class="QComboBox" name="videoCaptureContainer"/>
|
||||
</item>
|
||||
<item>
|
||||
<widget class="QLabel" name="videoCaptureBitrateLabel">
|
||||
<property name="text">
|
||||
<string>Bitrate:</string>
|
||||
</property>
|
||||
<item row="1" column="0">
|
||||
<widget class="QWidget" name="videoCaptureOptions" native="true">
|
||||
<layout class="QFormLayout" name="formLayout_6">
|
||||
<property name="leftMargin">
|
||||
<number>0</number>
|
||||
</property>
|
||||
<property name="topMargin">
|
||||
<number>0</number>
|
||||
</property>
|
||||
<property name="rightMargin">
|
||||
<number>0</number>
|
||||
</property>
|
||||
<property name="bottomMargin">
|
||||
<number>0</number>
|
||||
</property>
|
||||
<item row="0" column="0">
|
||||
<widget class="QLabel" name="videoCaptureCodecLabel">
|
||||
<property name="text">
|
||||
<string>Codec:</string>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item row="0" column="1">
|
||||
<widget class="QComboBox" name="videoCaptureCodec"/>
|
||||
</item>
|
||||
<item row="1" column="0">
|
||||
<widget class="QLabel" name="videoCaptureBitrateLabel">
|
||||
<property name="text">
|
||||
<string>Bitrate:</string>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item row="1" column="1">
|
||||
<widget class="QSpinBox" name="videoCaptureBitrate">
|
||||
<property name="suffix">
|
||||
<string> kbps</string>
|
||||
</property>
|
||||
<property name="minimum">
|
||||
<number>100</number>
|
||||
</property>
|
||||
<property name="maximum">
|
||||
<number>100000</number>
|
||||
</property>
|
||||
<property name="singleStep">
|
||||
<number>100</number>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item row="2" column="0">
|
||||
<widget class="QLabel" name="videoCaptureResolutionLabel">
|
||||
<property name="text">
|
||||
<string>Resolution:</string>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item row="2" column="1">
|
||||
<layout class="QHBoxLayout" name="horizontalLayout_10" stretch="1,0,1,0">
|
||||
<item>
|
||||
<widget class="QSpinBox" name="videoCaptureWidth">
|
||||
<property name="minimum">
|
||||
<number>320</number>
|
||||
</property>
|
||||
<property name="maximum">
|
||||
<number>32768</number>
|
||||
</property>
|
||||
<property name="singleStep">
|
||||
<number>16</number>
|
||||
</property>
|
||||
<property name="value">
|
||||
<number>640</number>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item>
|
||||
<widget class="QLabel" name="label_46">
|
||||
<property name="text">
|
||||
<string>x</string>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item>
|
||||
<widget class="QSpinBox" name="videoCaptureHeight">
|
||||
<property name="minimum">
|
||||
<number>240</number>
|
||||
</property>
|
||||
<property name="maximum">
|
||||
<number>32768</number>
|
||||
</property>
|
||||
<property name="singleStep">
|
||||
<number>16</number>
|
||||
</property>
|
||||
<property name="value">
|
||||
<number>240</number>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item>
|
||||
<widget class="QCheckBox" name="videoCaptureResolutionAuto">
|
||||
<property name="text">
|
||||
<string>Auto</string>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
</layout>
|
||||
</item>
|
||||
<item row="3" column="0" colspan="2">
|
||||
<widget class="QCheckBox" name="enableVideoCaptureArguments">
|
||||
<property name="text">
|
||||
<string>Extra Arguments</string>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item row="4" column="0" colspan="2">
|
||||
<widget class="QLineEdit" name="videoCaptureArguments"/>
|
||||
</item>
|
||||
</layout>
|
||||
</widget>
|
||||
</item>
|
||||
<item>
|
||||
<widget class="QSpinBox" name="videoCaptureBitrate">
|
||||
<property name="suffix">
|
||||
<string> kbps</string>
|
||||
</property>
|
||||
<property name="minimum">
|
||||
<number>100</number>
|
||||
</property>
|
||||
<property name="maximum">
|
||||
<number>100000</number>
|
||||
</property>
|
||||
<property name="singleStep">
|
||||
<number>100</number>
|
||||
<item row="0" column="0">
|
||||
<widget class="QCheckBox" name="enableVideoCapture">
|
||||
<property name="text">
|
||||
<string>Capture Video</string>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
</layout>
|
||||
</item>
|
||||
<item row="2" column="0">
|
||||
<widget class="QCheckBox" name="enableVideoCaptureArguments">
|
||||
<property name="text">
|
||||
<string>Enable Extra Arguments</string>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item row="2" column="1">
|
||||
<widget class="QLineEdit" name="videoCaptureArguments"/>
|
||||
</item>
|
||||
</layout>
|
||||
</widget>
|
||||
</item>
|
||||
|
|
|
@ -605,15 +605,18 @@ struct Pcsx2Config
|
|||
{
|
||||
static const char* AspectRatioNames[];
|
||||
static const char* FMVAspectRatioSwitchNames[];
|
||||
static const char* VideoCaptureContainers[];
|
||||
static const char* CaptureContainers[];
|
||||
|
||||
static const char* GetRendererName(GSRendererType type);
|
||||
|
||||
static constexpr float DEFAULT_FRAME_RATE_NTSC = 59.94f;
|
||||
static constexpr float DEFAULT_FRAME_RATE_PAL = 50.00f;
|
||||
|
||||
static constexpr u32 DEFAULT_VIDEO_CAPTURE_BITRATE = 6000;
|
||||
static const char* DEFAULT_VIDEO_CAPTURE_CONTAINER;
|
||||
static constexpr int DEFAULT_VIDEO_CAPTURE_BITRATE = 6000;
|
||||
static constexpr int DEFAULT_VIDEO_CAPTURE_WIDTH = 640;
|
||||
static constexpr int DEFAULT_VIDEO_CAPTURE_HEIGHT = 480;
|
||||
static constexpr int DEFAULT_AUDIO_CAPTURE_BITRATE = 160;
|
||||
static const char* DEFAULT_CAPTURE_CONTAINER;
|
||||
|
||||
union
|
||||
{
|
||||
|
@ -680,7 +683,11 @@ struct Pcsx2Config
|
|||
LoadTextureReplacements : 1,
|
||||
LoadTextureReplacementsAsync : 1,
|
||||
PrecacheTextureReplacements : 1,
|
||||
EnableVideoCaptureParameters : 1;
|
||||
EnableVideoCapture : 1,
|
||||
EnableVideoCaptureParameters : 1,
|
||||
VideoCaptureAutoResolution : 1,
|
||||
EnableAudioCapture : 1,
|
||||
EnableAudioCaptureParameters : 1;
|
||||
};
|
||||
};
|
||||
|
||||
|
@ -753,10 +760,15 @@ struct Pcsx2Config
|
|||
GSScreenshotFormat ScreenshotFormat{GSScreenshotFormat::PNG};
|
||||
int ScreenshotQuality{50};
|
||||
|
||||
std::string VideoCaptureContainer{DEFAULT_VIDEO_CAPTURE_CONTAINER};
|
||||
std::string CaptureContainer{DEFAULT_CAPTURE_CONTAINER};
|
||||
std::string VideoCaptureCodec;
|
||||
int VideoCaptureBitrate{DEFAULT_VIDEO_CAPTURE_BITRATE};
|
||||
std::string VideoCaptureParameters;
|
||||
std::string AudioCaptureCodec;
|
||||
std::string AudioCaptureParameters;
|
||||
int VideoCaptureBitrate{DEFAULT_VIDEO_CAPTURE_BITRATE};
|
||||
int VideoCaptureWidth{DEFAULT_VIDEO_CAPTURE_WIDTH};
|
||||
int VideoCaptureHeight{DEFAULT_VIDEO_CAPTURE_HEIGHT};
|
||||
int AudioCaptureBitrate{DEFAULT_AUDIO_CAPTURE_BITRATE};
|
||||
|
||||
std::string Adapter;
|
||||
std::string HWDumpDirectory;
|
||||
|
|
|
@ -949,16 +949,20 @@ BEGIN_HOTKEY_LIST(g_gs_hotkeys)
|
|||
{"ToggleVideoCapture", "Graphics", "Toggle Video Capture", [](s32 pressed) {
|
||||
if (!pressed)
|
||||
{
|
||||
GetMTGS().RunOnGSThread([]() {
|
||||
if (GSCapture::IsCapturing())
|
||||
{
|
||||
g_gs_renderer->EndCapture();
|
||||
return;
|
||||
}
|
||||
if (GSCapture::IsCapturing())
|
||||
{
|
||||
GetMTGS().RunOnGSThread([]() { g_gs_renderer->EndCapture(); });
|
||||
GetMTGS().WaitGS(false, false, false);
|
||||
return;
|
||||
}
|
||||
|
||||
std::string filename(fmt::format("{}.{}", GSGetBaseVideoFilename(), GSConfig.VideoCaptureContainer));
|
||||
GetMTGS().RunOnGSThread([]() {
|
||||
std::string filename(fmt::format("{}.{}", GSGetBaseVideoFilename(), GSConfig.CaptureContainer));
|
||||
g_gs_renderer->BeginCapture(std::move(filename));
|
||||
});
|
||||
|
||||
// Sync GS thread. We want to start adding audio at the same time as video.
|
||||
GetMTGS().WaitGS(false, false, false);
|
||||
}
|
||||
}},
|
||||
{"GSDumpSingleFrame", "Graphics", "Save Single Frame GS Dump", [](s32 pressed) {
|
||||
|
|
File diff suppressed because it is too large
Load Diff
|
@ -31,12 +31,18 @@ class GSDownloadTexture;
|
|||
namespace GSCapture
|
||||
{
|
||||
bool BeginCapture(float fps, GSVector2i recommendedResolution, float aspect, std::string filename);
|
||||
bool DeliverFrame(GSTexture* stex);
|
||||
bool DeliverVideoFrame(GSTexture* stex);
|
||||
void DeliverAudioPacket(const s16* frames); // SndOutPacketSize
|
||||
void EndCapture();
|
||||
|
||||
bool IsCapturing();
|
||||
bool IsCapturingVideo();
|
||||
bool IsCapturingAudio();
|
||||
const Threading::ThreadHandle& GetEncoderThreadHandle();
|
||||
GSVector2i GetSize();
|
||||
|
||||
std::vector<std::pair<std::string, std::string>> GetVideoCodecList(const char* container);
|
||||
using CodecName = std::pair<std::string, std::string>; // shortname,longname
|
||||
using CodecList = std::vector<CodecName>;
|
||||
CodecList GetVideoCodecList(const char* container);
|
||||
CodecList GetAudioCodecList(const char* container);
|
||||
}; // namespace GSCapture
|
||||
|
|
|
@ -795,7 +795,7 @@ void GSRenderer::VSync(u32 field, bool registers_written)
|
|||
}
|
||||
|
||||
// capture
|
||||
if (GSCapture::IsCapturing())
|
||||
if (GSCapture::IsCapturingVideo())
|
||||
{
|
||||
if (GSTexture* current = g_gs_device->GetCurrent())
|
||||
{
|
||||
|
@ -808,13 +808,13 @@ void GSRenderer::VSync(u32 field, bool registers_written)
|
|||
if (temp)
|
||||
{
|
||||
g_gs_device->StretchRect(current, temp, GSVector4(0, 0, size.x, size.y));
|
||||
GSCapture::DeliverFrame(temp);
|
||||
GSCapture::DeliverVideoFrame(temp);
|
||||
g_gs_device->Recycle(temp);
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
GSCapture::DeliverFrame(current);
|
||||
GSCapture::DeliverVideoFrame(current);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -949,7 +949,11 @@ void GSTranslateWindowToDisplayCoordinates(float window_x, float window_y, float
|
|||
|
||||
bool GSRenderer::BeginCapture(std::string filename)
|
||||
{
|
||||
return GSCapture::BeginCapture(GetTvRefreshRate(), GetInternalResolution(),
|
||||
const GSVector2i capture_resolution(GSConfig.VideoCaptureAutoResolution ?
|
||||
GetInternalResolution() :
|
||||
GSVector2i(GSConfig.VideoCaptureWidth, GSConfig.VideoCaptureHeight));
|
||||
|
||||
return GSCapture::BeginCapture(GetTvRefreshRate(), capture_resolution,
|
||||
GetCurrentAspectRatioFloat(GetVideoMode() == GSVideoMode::SDTV_480P || (GSConfig.PCRTCOverscan && GSConfig.PCRTCOffsets)),
|
||||
std::move(filename));
|
||||
}
|
||||
|
|
|
@ -360,12 +360,14 @@ const char* Pcsx2Config::GSOptions::FMVAspectRatioSwitchNames[] = {
|
|||
"16:9",
|
||||
nullptr};
|
||||
|
||||
const char* Pcsx2Config::GSOptions::VideoCaptureContainers[] = {
|
||||
const char* Pcsx2Config::GSOptions::CaptureContainers[] = {
|
||||
"mp4",
|
||||
"mkv",
|
||||
"avi",
|
||||
"wav",
|
||||
"mp3",
|
||||
nullptr};
|
||||
const char* Pcsx2Config::GSOptions::DEFAULT_VIDEO_CAPTURE_CONTAINER = "mp4";
|
||||
const char* Pcsx2Config::GSOptions::DEFAULT_CAPTURE_CONTAINER = "mp4";
|
||||
|
||||
const char* Pcsx2Config::GSOptions::GetRendererName(GSRendererType type)
|
||||
{
|
||||
|
@ -440,7 +442,10 @@ Pcsx2Config::GSOptions::GSOptions()
|
|||
LoadTextureReplacementsAsync = true;
|
||||
PrecacheTextureReplacements = false;
|
||||
|
||||
EnableVideoCapture = true;
|
||||
EnableVideoCaptureParameters = false;
|
||||
EnableAudioCapture = true;
|
||||
EnableAudioCaptureParameters = false;
|
||||
}
|
||||
|
||||
bool Pcsx2Config::GSOptions::operator==(const GSOptions& right) const
|
||||
|
@ -524,10 +529,15 @@ bool Pcsx2Config::GSOptions::OptionsAreEqual(const GSOptions& right) const
|
|||
OpEqu(ScreenshotFormat) &&
|
||||
OpEqu(ScreenshotQuality) &&
|
||||
|
||||
OpEqu(VideoCaptureContainer) &&
|
||||
OpEqu(CaptureContainer) &&
|
||||
OpEqu(VideoCaptureCodec) &&
|
||||
OpEqu(VideoCaptureBitrate) &&
|
||||
OpEqu(VideoCaptureParameters) &&
|
||||
OpEqu(AudioCaptureCodec) &&
|
||||
OpEqu(AudioCaptureParameters) &&
|
||||
OpEqu(VideoCaptureBitrate) &&
|
||||
OpEqu(VideoCaptureWidth) &&
|
||||
OpEqu(VideoCaptureHeight) &&
|
||||
OpEqu(AudioCaptureBitrate) &&
|
||||
|
||||
OpEqu(Adapter) &&
|
||||
|
||||
|
@ -649,7 +659,11 @@ void Pcsx2Config::GSOptions::LoadSave(SettingsWrapper& wrap)
|
|||
GSSettingBool(LoadTextureReplacements);
|
||||
GSSettingBool(LoadTextureReplacementsAsync);
|
||||
GSSettingBool(PrecacheTextureReplacements);
|
||||
GSSettingBool(EnableVideoCapture);
|
||||
GSSettingBool(EnableVideoCaptureParameters);
|
||||
GSSettingBool(VideoCaptureAutoResolution);
|
||||
GSSettingBool(EnableAudioCapture);
|
||||
GSSettingBool(EnableAudioCaptureParameters);
|
||||
|
||||
GSSettingIntEnumEx(LinearPresent, "linear_present_mode");
|
||||
GSSettingIntEnumEx(InterlaceMode, "deinterlace_mode");
|
||||
|
@ -699,10 +713,15 @@ void Pcsx2Config::GSOptions::LoadSave(SettingsWrapper& wrap)
|
|||
GSSettingIntEx(SaveN, "saven");
|
||||
GSSettingIntEx(SaveL, "savel");
|
||||
|
||||
GSSettingStringEx(VideoCaptureContainer, "VideoCaptureContainer");
|
||||
GSSettingStringEx(CaptureContainer, "CaptureContainer");
|
||||
GSSettingStringEx(VideoCaptureCodec, "VideoCaptureCodec");
|
||||
GSSettingIntEx(VideoCaptureBitrate, "VideoCaptureBitrate");
|
||||
GSSettingStringEx(VideoCaptureParameters, "VideoCaptureParameters");
|
||||
GSSettingStringEx(AudioCaptureCodec, "AudioCaptureCodec");
|
||||
GSSettingStringEx(AudioCaptureParameters, "AudioCaptureParameters");
|
||||
GSSettingIntEx(VideoCaptureBitrate, "VideoCaptureBitrate");
|
||||
GSSettingIntEx(VideoCaptureWidth, "VideoCaptureWidth");
|
||||
GSSettingIntEx(VideoCaptureHeight, "VideoCaptureHeight");
|
||||
GSSettingIntEx(AudioCaptureBitrate, "AudioCaptureBitrate");
|
||||
|
||||
GSSettingString(Adapter);
|
||||
GSSettingString(HWDumpDirectory);
|
||||
|
|
|
@ -17,6 +17,8 @@
|
|||
|
||||
#include "SPU2/Global.h"
|
||||
#include "SPU2/spu2.h"
|
||||
#include "GS/GSCapture.h"
|
||||
#include "GS/GSVector.h"
|
||||
|
||||
#include "common/Assertions.h"
|
||||
#include "common/Timer.h"
|
||||
|
@ -25,6 +27,8 @@
|
|||
|
||||
const StereoOut32 StereoOut32::Empty(0, 0);
|
||||
|
||||
static bool s_audio_capture_active = false;
|
||||
|
||||
//Uncomment the next line to use the old time stretcher
|
||||
//#define SPU2X_USE_OLD_STRETCHER
|
||||
//#define SPU2X_HANDLE_STRETCH_OVERRUNS
|
||||
|
@ -463,6 +467,16 @@ void SPU2::SetOutputPaused(bool paused)
|
|||
s_output_module->SetPaused(paused);
|
||||
}
|
||||
|
||||
void SPU2::SetAudioCaptureActive(bool active)
|
||||
{
|
||||
s_audio_capture_active = active;
|
||||
}
|
||||
|
||||
bool SPU2::IsAudioCaptureActive()
|
||||
{
|
||||
return s_audio_capture_active;
|
||||
}
|
||||
|
||||
void SndBuffer::Write(StereoOut16 Sample)
|
||||
{
|
||||
#ifdef PCSX2_DEVBUILD
|
||||
|
@ -470,9 +484,6 @@ void SndBuffer::Write(StereoOut16 Sample)
|
|||
WaveDump::WriteCore(1, CoreSrc_External, Sample);
|
||||
#endif
|
||||
|
||||
if (WavRecordEnabled)
|
||||
RecordWrite(Sample);
|
||||
|
||||
s_staging_buffer[s_staging_progress++] = Sample;
|
||||
|
||||
// If we haven't accumulated a full packet yet, do nothing more:
|
||||
|
@ -480,6 +491,10 @@ void SndBuffer::Write(StereoOut16 Sample)
|
|||
return;
|
||||
s_staging_progress = 0;
|
||||
|
||||
// We want to capture audio *before* time stretching.
|
||||
if (s_audio_capture_active)
|
||||
GSCapture::DeliverAudioPacket(reinterpret_cast<const s16*>(s_staging_buffer.get()));
|
||||
|
||||
//Don't play anything directly after loading a savestate, avoids static killing your speakers.
|
||||
if (s_ss_freeze > 0)
|
||||
{
|
||||
|
|
|
@ -354,10 +354,3 @@ extern SndOutModule* XAudio2Out;
|
|||
extern SndOutModule* CubebOut;
|
||||
#endif
|
||||
|
||||
// =====================================================================================================
|
||||
|
||||
extern bool WavRecordEnabled;
|
||||
|
||||
extern bool RecordStart(const std::string* filename);
|
||||
extern void RecordStop();
|
||||
extern void RecordWrite(const StereoOut16& sample);
|
||||
|
|
|
@ -91,40 +91,3 @@ namespace WaveDump
|
|||
} // namespace WaveDump
|
||||
|
||||
#endif // PCSX2_DEVBUILD
|
||||
|
||||
bool WavRecordEnabled = false;
|
||||
|
||||
static std::unique_ptr<Common::WAVWriter> m_wavrecord;
|
||||
static std::mutex WavRecordMutex;
|
||||
|
||||
bool RecordStart(const std::string* filename)
|
||||
{
|
||||
std::unique_lock lock(WavRecordMutex);
|
||||
m_wavrecord.reset();
|
||||
m_wavrecord = std::make_unique<Common::WAVWriter>();
|
||||
if (!m_wavrecord->Open(m_wavrecord ? filename->c_str() : "audio_recording.wav", SampleRate, 2))
|
||||
{
|
||||
Console.Error("SPU2 couldn't open file for recording: %s.\nWavfile capture disabled.", filename ? filename->c_str() : "audio_recording.wav");
|
||||
m_wavrecord.reset();
|
||||
WavRecordEnabled = false;
|
||||
return false;
|
||||
}
|
||||
|
||||
WavRecordEnabled = true;
|
||||
return true;
|
||||
}
|
||||
|
||||
void RecordStop()
|
||||
{
|
||||
std::unique_lock lock(WavRecordMutex);
|
||||
WavRecordEnabled = false;
|
||||
m_wavrecord.reset();
|
||||
}
|
||||
|
||||
void RecordWrite(const StereoOut16& sample)
|
||||
{
|
||||
std::unique_lock lock(WavRecordMutex);
|
||||
if (!m_wavrecord)
|
||||
return;
|
||||
m_wavrecord->WriteFrames(reinterpret_cast<const s16*>(&sample), 2);
|
||||
}
|
||||
|
|
|
@ -18,11 +18,12 @@
|
|||
#include "SPU2/Debug.h"
|
||||
#include "SPU2/spu2.h"
|
||||
#include "SPU2/Dma.h"
|
||||
#include "GS.h"
|
||||
#include "GS/GSCapture.h"
|
||||
#include "R3000A.h"
|
||||
|
||||
namespace SPU2
|
||||
{
|
||||
static int GetConsoleSampleRate();
|
||||
static void InitSndBuffer();
|
||||
static void UpdateSampleRate();
|
||||
static void InternalReset(bool psxmode);
|
||||
|
@ -35,7 +36,7 @@ int SampleRate = 48000;
|
|||
|
||||
u32 lClocks = 0;
|
||||
|
||||
int SPU2::GetConsoleSampleRate()
|
||||
s32 SPU2::GetConsoleSampleRate()
|
||||
{
|
||||
return s_psxmode ? 44100 : 48000;
|
||||
}
|
||||
|
@ -129,6 +130,13 @@ void SPU2::UpdateSampleRate()
|
|||
SndBuffer::Cleanup();
|
||||
SampleRate = new_sample_rate;
|
||||
InitSndBuffer();
|
||||
|
||||
// Can't be capturing when the sample rate changes.
|
||||
if (IsAudioCaptureActive())
|
||||
{
|
||||
GetMTGS().RunOnGSThread(&GSEndCapture);
|
||||
GetMTGS().WaitGS(false, false, false);
|
||||
}
|
||||
}
|
||||
|
||||
void SPU2::InternalReset(bool psxmode)
|
||||
|
@ -336,18 +344,6 @@ void SPU2write(u32 rmem, u16 value)
|
|||
}
|
||||
}
|
||||
|
||||
// returns a non zero value if successful
|
||||
bool SPU2setupRecording(const std::string* filename)
|
||||
{
|
||||
return RecordStart(filename);
|
||||
}
|
||||
|
||||
void SPU2endRecording()
|
||||
{
|
||||
if (WavRecordEnabled)
|
||||
RecordStop();
|
||||
}
|
||||
|
||||
s32 SPU2freeze(FreezeAction mode, freezeData* data)
|
||||
{
|
||||
pxAssume(data != nullptr);
|
||||
|
|
|
@ -54,16 +54,18 @@ void SetDeviceSampleRateMultiplier(double multiplier);
|
|||
|
||||
/// Returns true if we're currently running in PSX mode.
|
||||
bool IsRunningPSXMode();
|
||||
|
||||
/// Returns the current sample rate the SPU2 is operating at.
|
||||
s32 GetConsoleSampleRate();
|
||||
|
||||
/// Tells SPU2 to forward audio packets to GSCapture.
|
||||
void SetAudioCaptureActive(bool active);
|
||||
bool IsAudioCaptureActive();
|
||||
} // namespace SPU2
|
||||
|
||||
void SPU2write(u32 mem, u16 value);
|
||||
u16 SPU2read(u32 mem);
|
||||
|
||||
// extended funcs
|
||||
// returns true if successful
|
||||
bool SPU2setupRecording(const std::string* filename);
|
||||
void SPU2endRecording();
|
||||
|
||||
void SPU2async(u32 cycles);
|
||||
s32 SPU2freeze(FreezeAction mode, freezeData* data);
|
||||
|
||||
|
|
Loading…
Reference in New Issue