mirror of https://github.com/PCSX2/pcsx2.git
GS-HW: Don't bilinear dirty rects by default, added as upscale hack.
This commit is contained in:
parent
fa439a465d
commit
2b49614df9
bin/resources
pcsx2-qt/Settings
pcsx2
|
@ -3448,6 +3448,7 @@ SCES-51635:
|
||||||
halfPixelOffset: 2 # Fixes lighting/shadows.
|
halfPixelOffset: 2 # Fixes lighting/shadows.
|
||||||
preloadFrameData: 1 # Fixes sun flickering.
|
preloadFrameData: 1 # Fixes sun flickering.
|
||||||
autoFlush: 1 # Fixes sun through objects.
|
autoFlush: 1 # Fixes sun through objects.
|
||||||
|
bilinearUpscale: 1 # Smooths out sun glare textures like native.
|
||||||
SCES-51648:
|
SCES-51648:
|
||||||
name: "Everquest - Online Adventures"
|
name: "Everquest - Online Adventures"
|
||||||
region: "PAL-E-I"
|
region: "PAL-E-I"
|
||||||
|
@ -46538,6 +46539,7 @@ SLUS-21127:
|
||||||
halfPixelOffset: 2 # Fixes lighting/shadows.
|
halfPixelOffset: 2 # Fixes lighting/shadows.
|
||||||
preloadFrameData: 1 # Fixes sun flickering.
|
preloadFrameData: 1 # Fixes sun flickering.
|
||||||
autoFlush: 1 # Fixes sun through objects.
|
autoFlush: 1 # Fixes sun through objects.
|
||||||
|
bilinearUpscale: 1 # Smooths out sun glare textures like native.
|
||||||
SLUS-21128:
|
SLUS-21128:
|
||||||
name: "Blitz - The League"
|
name: "Blitz - The League"
|
||||||
region: "NTSC-U"
|
region: "NTSC-U"
|
||||||
|
|
|
@ -224,7 +224,7 @@ GraphicsSettingsWidget::GraphicsSettingsWidget(SettingsDialog* dialog, QWidget*
|
||||||
SettingWidgetBinder::BindWidgetToBoolSetting(sif, m_ui.alignSprite, "EmuCore/GS", "UserHacks_align_sprite_X", false);
|
SettingWidgetBinder::BindWidgetToBoolSetting(sif, m_ui.alignSprite, "EmuCore/GS", "UserHacks_align_sprite_X", false);
|
||||||
SettingWidgetBinder::BindWidgetToBoolSetting(sif, m_ui.mergeSprite, "EmuCore/GS", "UserHacks_merge_pp_sprite", false);
|
SettingWidgetBinder::BindWidgetToBoolSetting(sif, m_ui.mergeSprite, "EmuCore/GS", "UserHacks_merge_pp_sprite", false);
|
||||||
SettingWidgetBinder::BindWidgetToBoolSetting(sif, m_ui.wildHack, "EmuCore/GS", "UserHacks_WildHack", false);
|
SettingWidgetBinder::BindWidgetToBoolSetting(sif, m_ui.wildHack, "EmuCore/GS", "UserHacks_WildHack", false);
|
||||||
|
SettingWidgetBinder::BindWidgetToBoolSetting(sif, m_ui.bilinearHack, "EmuCore/GS", "UserHacks_BilinearHack", false);
|
||||||
//////////////////////////////////////////////////////////////////////////
|
//////////////////////////////////////////////////////////////////////////
|
||||||
// Texture Replacements
|
// Texture Replacements
|
||||||
//////////////////////////////////////////////////////////////////////////
|
//////////////////////////////////////////////////////////////////////////
|
||||||
|
@ -587,6 +587,9 @@ GraphicsSettingsWidget::GraphicsSettingsWidget(SettingsDialog* dialog, QWidget*
|
||||||
dialog->registerWidgetHelp(m_ui.wildHack, tr("Wild Arms Hack"), tr("Unchecked"),
|
dialog->registerWidgetHelp(m_ui.wildHack, tr("Wild Arms Hack"), tr("Unchecked"),
|
||||||
tr("Lowers the GS precision to avoid gaps between pixels when upscaling. Fixes the text on Wild Arms games."));
|
tr("Lowers the GS precision to avoid gaps between pixels when upscaling. Fixes the text on Wild Arms games."));
|
||||||
|
|
||||||
|
dialog->registerWidgetHelp(m_ui.bilinearHack, tr("Bilinear Upscale"), tr("Unchecked"),
|
||||||
|
tr("Can smooth out textures due to be bilinear filtered when upscaling. E.g. Brave sun glare."));
|
||||||
|
|
||||||
dialog->registerWidgetHelp(m_ui.mergeSprite, tr("Merge Sprite"), tr("Unchecked"),
|
dialog->registerWidgetHelp(m_ui.mergeSprite, tr("Merge Sprite"), tr("Unchecked"),
|
||||||
tr("Replaces post-processing multiple paving sprites by a single fat sprite. It reduces various upscaling lines."));
|
tr("Replaces post-processing multiple paving sprites by a single fat sprite. It reduces various upscaling lines."));
|
||||||
}
|
}
|
||||||
|
@ -1075,6 +1078,7 @@ void GraphicsSettingsWidget::resetManualHardwareFixes()
|
||||||
check_bool("EmuCore/GS", "UserHacks_align_sprite_X", false);
|
check_bool("EmuCore/GS", "UserHacks_align_sprite_X", false);
|
||||||
check_bool("EmuCore/GS", "UserHacks_merge_pp_sprite", false);
|
check_bool("EmuCore/GS", "UserHacks_merge_pp_sprite", false);
|
||||||
check_bool("EmuCore/GS", "UserHacks_WildHack", false);
|
check_bool("EmuCore/GS", "UserHacks_WildHack", false);
|
||||||
|
check_bool("EmuCore/GS", "UserHacks_BilinearHack", false);
|
||||||
}
|
}
|
||||||
|
|
||||||
if (changed)
|
if (changed)
|
||||||
|
|
|
@ -7,7 +7,7 @@
|
||||||
<x>0</x>
|
<x>0</x>
|
||||||
<y>0</y>
|
<y>0</y>
|
||||||
<width>720</width>
|
<width>720</width>
|
||||||
<height>466</height>
|
<height>476</height>
|
||||||
</rect>
|
</rect>
|
||||||
</property>
|
</property>
|
||||||
<property name="windowTitle">
|
<property name="windowTitle">
|
||||||
|
@ -58,7 +58,7 @@
|
||||||
<item>
|
<item>
|
||||||
<widget class="QTabWidget" name="tabs">
|
<widget class="QTabWidget" name="tabs">
|
||||||
<property name="currentIndex">
|
<property name="currentIndex">
|
||||||
<number>0</number>
|
<number>4</number>
|
||||||
</property>
|
</property>
|
||||||
<property name="documentMode">
|
<property name="documentMode">
|
||||||
<bool>true</bool>
|
<bool>true</bool>
|
||||||
|
@ -1222,6 +1222,13 @@
|
||||||
</property>
|
</property>
|
||||||
</widget>
|
</widget>
|
||||||
</item>
|
</item>
|
||||||
|
<item row="1" column="1">
|
||||||
|
<widget class="QCheckBox" name="bilinearHack">
|
||||||
|
<property name="text">
|
||||||
|
<string>Bilinear Dirty Upscale</string>
|
||||||
|
</property>
|
||||||
|
</widget>
|
||||||
|
</item>
|
||||||
</layout>
|
</layout>
|
||||||
</item>
|
</item>
|
||||||
</layout>
|
</layout>
|
||||||
|
|
|
@ -677,6 +677,7 @@ struct Pcsx2Config
|
||||||
UserHacks_DisableSafeFeatures : 1,
|
UserHacks_DisableSafeFeatures : 1,
|
||||||
UserHacks_MergePPSprite : 1,
|
UserHacks_MergePPSprite : 1,
|
||||||
UserHacks_WildHack : 1,
|
UserHacks_WildHack : 1,
|
||||||
|
UserHacks_BilinearHack : 1,
|
||||||
UserHacks_TargetPartialInvalidation : 1,
|
UserHacks_TargetPartialInvalidation : 1,
|
||||||
UserHacks_EstimateTextureRegion : 1,
|
UserHacks_EstimateTextureRegion : 1,
|
||||||
FXAA : 1,
|
FXAA : 1,
|
||||||
|
|
|
@ -169,6 +169,7 @@ The clamp modes are also numerically based.
|
||||||
* alignSprite [`0` or `1`] {Off or On} Default: Off (`0`)
|
* alignSprite [`0` or `1`] {Off or On} Default: Off (`0`)
|
||||||
* mergeSprite [`0` or `1`] {Off or On} Default: Off (`0`)
|
* mergeSprite [`0` or `1`] {Off or On} Default: Off (`0`)
|
||||||
* wildArmsHack [`0` or `1`] {Off or On} Default: Off (`0`)
|
* wildArmsHack [`0` or `1`] {Off or On} Default: Off (`0`)
|
||||||
|
* bilinearUpscale [`0` or `1`] {Off or On} Default: Off (`0`)
|
||||||
* skipDrawStart [Value between `0` to `10000`] {0-10000} Default: Off (`0`)
|
* skipDrawStart [Value between `0` to `10000`] {0-10000} Default: Off (`0`)
|
||||||
* skipDrawEnd [Value between `0` to `10000`] {0-10000} Default: Off (`0`)
|
* skipDrawEnd [Value between `0` to `10000`] {0-10000} Default: Off (`0`)
|
||||||
* halfPixelOffset [`0` or `1` or `2` or `3`] {Off, Normal Vertex, Special Texture or Special Texture Aggressive} Default: Off (`0`)
|
* halfPixelOffset [`0` or `1` or `2` or `3`] {Off, Normal Vertex, Special Texture or Special Texture Aggressive} Default: Off (`0`)
|
||||||
|
|
|
@ -171,6 +171,11 @@
|
||||||
"minimum": 0,
|
"minimum": 0,
|
||||||
"maximum": 1
|
"maximum": 1
|
||||||
},
|
},
|
||||||
|
"bilinearUpscale": {
|
||||||
|
"type": "integer",
|
||||||
|
"minimum": 0,
|
||||||
|
"maximum": 1
|
||||||
|
},
|
||||||
"estimateTextureRegion": {
|
"estimateTextureRegion": {
|
||||||
"type": "integer",
|
"type": "integer",
|
||||||
"minimum": 0,
|
"minimum": 0,
|
||||||
|
|
|
@ -3234,6 +3234,9 @@ void FullscreenUI::DrawGraphicsSettingsPage()
|
||||||
DrawToggleSetting(bsi, "Wild Arms Hack",
|
DrawToggleSetting(bsi, "Wild Arms Hack",
|
||||||
"Lowers the GS precision to avoid gaps between pixels when upscaling. Fixes the text on Wild Arms games.", "EmuCore/GS",
|
"Lowers the GS precision to avoid gaps between pixels when upscaling. Fixes the text on Wild Arms games.", "EmuCore/GS",
|
||||||
"UserHacks_WildHack", false, manual_hw_fixes);
|
"UserHacks_WildHack", false, manual_hw_fixes);
|
||||||
|
DrawToggleSetting(bsi, "Bilinear Upscale",
|
||||||
|
"Can smooth out textures due to be bilinear filtered when upscaling. E.g. Brave sun glare.", "EmuCore/GS",
|
||||||
|
"UserHacks_BilinearHack", false, manual_hw_fixes);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -415,6 +415,8 @@ void ImGuiManager::DrawSettingsOverlay()
|
||||||
APPEND("TexRT={} ", static_cast<int>(GSConfig.UserHacks_TextureInsideRt));
|
APPEND("TexRT={} ", static_cast<int>(GSConfig.UserHacks_TextureInsideRt));
|
||||||
if (GSConfig.UserHacks_WildHack)
|
if (GSConfig.UserHacks_WildHack)
|
||||||
APPEND("WA ");
|
APPEND("WA ");
|
||||||
|
if (GSConfig.UserHacks_BilinearHack)
|
||||||
|
APPEND("BLU ");
|
||||||
if (GSConfig.UserHacks_MergePPSprite)
|
if (GSConfig.UserHacks_MergePPSprite)
|
||||||
APPEND("MS ");
|
APPEND("MS ");
|
||||||
if (GSConfig.UserHacks_AlignSpriteX)
|
if (GSConfig.UserHacks_AlignSpriteX)
|
||||||
|
|
|
@ -1426,14 +1426,14 @@ GSTextureCache::Target* GSTextureCache::LookupTarget(const GIFRegTEX0& TEX0, con
|
||||||
GL_INS("Preloading the RT DATA");
|
GL_INS("Preloading the RT DATA");
|
||||||
eerect = eerect.rintersect(newrect);
|
eerect = eerect.rintersect(newrect);
|
||||||
dst->UpdateValidity(newrect);
|
dst->UpdateValidity(newrect);
|
||||||
AddDirtyRectTarget(dst, eerect, TEX0.PSM, TEX0.TBW, rgba/*, GSLocalMemory::m_psm[TEX0.PSM].trbpp >= 16*/);
|
AddDirtyRectTarget(dst, eerect, TEX0.PSM, TEX0.TBW, rgba, GSLocalMemory::m_psm[TEX0.PSM].trbpp >= 16);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
GL_INS("Preloading the RT DATA");
|
GL_INS("Preloading the RT DATA");
|
||||||
dst->UpdateValidity(newrect);
|
dst->UpdateValidity(newrect);
|
||||||
AddDirtyRectTarget(dst, newrect, TEX0.PSM, TEX0.TBW, rgba/*, GSLocalMemory::m_psm[TEX0.PSM].trbpp >= 16*/);
|
AddDirtyRectTarget(dst, newrect, TEX0.PSM, TEX0.TBW, rgba, GSLocalMemory::m_psm[TEX0.PSM].trbpp >= 16);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
dst->m_is_frame = is_frame;
|
dst->m_is_frame = is_frame;
|
||||||
|
@ -4313,6 +4313,7 @@ void GSTextureCache::Target::Update(bool reset_age)
|
||||||
// Bilinear filtering this is probably not a good thing, at least in native, but upscaling Nearest can be gross and messy.
|
// Bilinear filtering this is probably not a good thing, at least in native, but upscaling Nearest can be gross and messy.
|
||||||
// It's needed for depth, though.. filtering depth doesn't make much sense, but SMT3 needs it..
|
// It's needed for depth, though.. filtering depth doesn't make much sense, but SMT3 needs it..
|
||||||
const bool upscaled = (m_scale != 1.0f);
|
const bool upscaled = (m_scale != 1.0f);
|
||||||
|
const bool override_linear = upscaled && GSConfig.UserHacks_BilinearHack;
|
||||||
const bool linear = (m_type == RenderTarget && upscaled);
|
const bool linear = (m_type == RenderTarget && upscaled);
|
||||||
|
|
||||||
GSDevice::MultiStretchRect* drects = static_cast<GSDevice::MultiStretchRect*>(
|
GSDevice::MultiStretchRect* drects = static_cast<GSDevice::MultiStretchRect*>(
|
||||||
|
@ -4344,7 +4345,8 @@ void GSTextureCache::Target::Update(bool reset_age)
|
||||||
drect.src = t;
|
drect.src = t;
|
||||||
drect.src_rect = GSVector4(r - t_offset) / t_sizef;
|
drect.src_rect = GSVector4(r - t_offset) / t_sizef;
|
||||||
drect.dst_rect = GSVector4(r) * GSVector4(m_scale);
|
drect.dst_rect = GSVector4(r) * GSVector4(m_scale);
|
||||||
drect.linear = linear && m_dirty[i].req_linear;
|
drect.linear = linear && (m_dirty[i].req_linear || override_linear);
|
||||||
|
|
||||||
// Copy the new GS memory content into the destination texture.
|
// Copy the new GS memory content into the destination texture.
|
||||||
if (m_type == RenderTarget)
|
if (m_type == RenderTarget)
|
||||||
{
|
{
|
||||||
|
|
|
@ -421,7 +421,7 @@ public:
|
||||||
void Read(Source* t, const GSVector4i& r);
|
void Read(Source* t, const GSVector4i& r);
|
||||||
void RemoveAll();
|
void RemoveAll();
|
||||||
void ReadbackAll();
|
void ReadbackAll();
|
||||||
void AddDirtyRectTarget(Target* target, GSVector4i rect, u32 psm, u32 bw, RGBAMask rgba, bool req_linear = true);
|
void AddDirtyRectTarget(Target* target, GSVector4i rect, u32 psm, u32 bw, RGBAMask rgba, bool req_linear = false);
|
||||||
bool CanTranslate(u32 bp, u32 bw, u32 spsm, GSVector4i r, u32 dbp, u32 dpsm, u32 dbw);
|
bool CanTranslate(u32 bp, u32 bw, u32 spsm, GSVector4i r, u32 dbp, u32 dpsm, u32 dbw);
|
||||||
GSVector4i TranslateAlignedRectByPage(u32 sbp, u32 spsm, u32 sbw, GSVector4i src_r, u32 dbp, u32 dpsm, u32 bw, bool is_invalidation = false);
|
GSVector4i TranslateAlignedRectByPage(u32 sbp, u32 spsm, u32 sbw, GSVector4i src_r, u32 dbp, u32 dpsm, u32 bw, bool is_invalidation = false);
|
||||||
void DirtyRectByPage(u32 sbp, u32 spsm, u32 sbw, Target* t, GSVector4i src_r, u32 dbp, u32 dpsm, u32 bw);
|
void DirtyRectByPage(u32 sbp, u32 spsm, u32 sbw, Target* t, GSVector4i src_r, u32 dbp, u32 dpsm, u32 bw);
|
||||||
|
|
|
@ -352,6 +352,7 @@ static const char* s_gs_hw_fix_names[] = {
|
||||||
"alignSprite",
|
"alignSprite",
|
||||||
"mergeSprite",
|
"mergeSprite",
|
||||||
"wildArmsHack",
|
"wildArmsHack",
|
||||||
|
"bilinearUpscale",
|
||||||
"estimateTextureRegion",
|
"estimateTextureRegion",
|
||||||
"PCRTCOffsets",
|
"PCRTCOffsets",
|
||||||
"PCRTCOverscan",
|
"PCRTCOverscan",
|
||||||
|
@ -588,6 +589,9 @@ bool GameDatabaseSchema::GameEntry::configMatchesHWFix(const Pcsx2Config::GSOpti
|
||||||
case GSHWFixId::WildArmsHack:
|
case GSHWFixId::WildArmsHack:
|
||||||
return (config.UpscaleMultiplier <= 1.0f || static_cast<int>(config.UserHacks_WildHack) == value);
|
return (config.UpscaleMultiplier <= 1.0f || static_cast<int>(config.UserHacks_WildHack) == value);
|
||||||
|
|
||||||
|
case GSHWFixId::BilinearUpscale:
|
||||||
|
return (config.UpscaleMultiplier <= 1.0f || static_cast<int>(config.UserHacks_BilinearHack) == value);
|
||||||
|
|
||||||
case GSHWFixId::EstimateTextureRegion:
|
case GSHWFixId::EstimateTextureRegion:
|
||||||
return (static_cast<int>(config.UserHacks_EstimateTextureRegion) == value);
|
return (static_cast<int>(config.UserHacks_EstimateTextureRegion) == value);
|
||||||
|
|
||||||
|
@ -727,6 +731,10 @@ u32 GameDatabaseSchema::GameEntry::applyGSHardwareFixes(Pcsx2Config::GSOptions&
|
||||||
config.UserHacks_WildHack = (value > 0);
|
config.UserHacks_WildHack = (value > 0);
|
||||||
break;
|
break;
|
||||||
|
|
||||||
|
case GSHWFixId::BilinearUpscale:
|
||||||
|
config.UserHacks_BilinearHack = (value > 0);
|
||||||
|
break;
|
||||||
|
|
||||||
case GSHWFixId::EstimateTextureRegion:
|
case GSHWFixId::EstimateTextureRegion:
|
||||||
config.UserHacks_EstimateTextureRegion = (value > 0);
|
config.UserHacks_EstimateTextureRegion = (value > 0);
|
||||||
break;
|
break;
|
||||||
|
|
|
@ -71,6 +71,7 @@ namespace GameDatabaseSchema
|
||||||
AlignSprite,
|
AlignSprite,
|
||||||
MergeSprite,
|
MergeSprite,
|
||||||
WildArmsHack,
|
WildArmsHack,
|
||||||
|
BilinearUpscale,
|
||||||
EstimateTextureRegion,
|
EstimateTextureRegion,
|
||||||
PCRTCOffsets,
|
PCRTCOffsets,
|
||||||
PCRTCOverscan,
|
PCRTCOverscan,
|
||||||
|
|
|
@ -443,6 +443,7 @@ Pcsx2Config::GSOptions::GSOptions()
|
||||||
UserHacks_DisableSafeFeatures = false;
|
UserHacks_DisableSafeFeatures = false;
|
||||||
UserHacks_MergePPSprite = false;
|
UserHacks_MergePPSprite = false;
|
||||||
UserHacks_WildHack = false;
|
UserHacks_WildHack = false;
|
||||||
|
UserHacks_BilinearHack = false;
|
||||||
|
|
||||||
DumpReplaceableTextures = false;
|
DumpReplaceableTextures = false;
|
||||||
DumpReplaceableMipmaps = false;
|
DumpReplaceableMipmaps = false;
|
||||||
|
@ -656,6 +657,7 @@ void Pcsx2Config::GSOptions::LoadSave(SettingsWrapper& wrap)
|
||||||
GSSettingBoolEx(UserHacks_DisableSafeFeatures, "UserHacks_Disable_Safe_Features");
|
GSSettingBoolEx(UserHacks_DisableSafeFeatures, "UserHacks_Disable_Safe_Features");
|
||||||
GSSettingBoolEx(UserHacks_MergePPSprite, "UserHacks_merge_pp_sprite");
|
GSSettingBoolEx(UserHacks_MergePPSprite, "UserHacks_merge_pp_sprite");
|
||||||
GSSettingBoolEx(UserHacks_WildHack, "UserHacks_WildHack");
|
GSSettingBoolEx(UserHacks_WildHack, "UserHacks_WildHack");
|
||||||
|
GSSettingBoolEx(UserHacks_BilinearHack, "UserHacks_BilinearHack");
|
||||||
GSSettingIntEnumEx(UserHacks_TextureInsideRt, "UserHacks_TextureInsideRt");
|
GSSettingIntEnumEx(UserHacks_TextureInsideRt, "UserHacks_TextureInsideRt");
|
||||||
GSSettingBoolEx(UserHacks_TargetPartialInvalidation, "UserHacks_TargetPartialInvalidation");
|
GSSettingBoolEx(UserHacks_TargetPartialInvalidation, "UserHacks_TargetPartialInvalidation");
|
||||||
GSSettingBoolEx(UserHacks_EstimateTextureRegion, "UserHacks_EstimateTextureRegion");
|
GSSettingBoolEx(UserHacks_EstimateTextureRegion, "UserHacks_EstimateTextureRegion");
|
||||||
|
@ -773,6 +775,7 @@ void Pcsx2Config::GSOptions::MaskUserHacks()
|
||||||
UserHacks_AlignSpriteX = false;
|
UserHacks_AlignSpriteX = false;
|
||||||
UserHacks_MergePPSprite = false;
|
UserHacks_MergePPSprite = false;
|
||||||
UserHacks_WildHack = false;
|
UserHacks_WildHack = false;
|
||||||
|
UserHacks_BilinearHack = false;
|
||||||
UserHacks_DisableSafeFeatures = false;
|
UserHacks_DisableSafeFeatures = false;
|
||||||
UserHacks_HalfBottomOverride = -1;
|
UserHacks_HalfBottomOverride = -1;
|
||||||
UserHacks_HalfPixelOffset = 0;
|
UserHacks_HalfPixelOffset = 0;
|
||||||
|
@ -803,6 +806,7 @@ void Pcsx2Config::GSOptions::MaskUpscalingHacks()
|
||||||
UserHacks_AlignSpriteX = false;
|
UserHacks_AlignSpriteX = false;
|
||||||
UserHacks_MergePPSprite = false;
|
UserHacks_MergePPSprite = false;
|
||||||
UserHacks_WildHack = false;
|
UserHacks_WildHack = false;
|
||||||
|
UserHacks_BilinearHack = false;
|
||||||
UserHacks_HalfPixelOffset = 0;
|
UserHacks_HalfPixelOffset = 0;
|
||||||
UserHacks_RoundSprite = 0;
|
UserHacks_RoundSprite = 0;
|
||||||
UserHacks_TCOffsetX = 0;
|
UserHacks_TCOffsetX = 0;
|
||||||
|
|
Loading…
Reference in New Issue