mirror of
https://github.com/PCSX2/pcsx2.git
synced 2026-01-31 01:15:24 +01:00
Compare commits
16 Commits
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
de03d2f672 | ||
|
|
ae33c3d991 | ||
|
|
61280a945d | ||
|
|
e82712bf52 | ||
|
|
06307abd03 | ||
|
|
daf735b047 | ||
|
|
f591c88aff | ||
|
|
ca47a08882 | ||
|
|
92adacf99e | ||
|
|
43e5ec25ab | ||
|
|
1018b75847 | ||
|
|
3871d1bd5d | ||
|
|
976d4a8dbb | ||
|
|
40b1b9b717 | ||
|
|
a3b817cb1f | ||
|
|
83e152cd21 |
@@ -201,10 +201,6 @@ echo Building Qt base...
|
||||
rmdir /S /Q "qtbase-everywhere-src-%QT%"
|
||||
%SEVENZIP% x "qtbase-everywhere-src-%QT%.zip" || goto error
|
||||
cd "qtbase-everywhere-src-%QT%" || goto error
|
||||
|
||||
rem Disable the PCRE2 JIT, it doesn't properly verify AVX2 support.
|
||||
%PATCH% -p1 < "%SCRIPTDIR%\qtbase-disable-pcre2-jit.patch" || goto error
|
||||
|
||||
cmake -B build -DFEATURE_sql=OFF -DCMAKE_INSTALL_PREFIX="%INSTALLDIR%" %FORCEPDB% -DINPUT_gui=yes -DINPUT_widgets=yes -DINPUT_ssl=yes -DINPUT_openssl=no -DINPUT_schannel=yes -DFEATURE_system_png=ON -DFEATURE_system_jpeg=ON -DFEATURE_system_zlib=ON -DFEATURE_system_freetype=ON -DFEATURE_system_harfbuzz=ON %QTBUILDSPEC% || goto error
|
||||
cmake --build build --parallel || goto error
|
||||
ninja -C build install || goto error
|
||||
|
||||
@@ -1,35 +0,0 @@
|
||||
--- qtbase/src/3rdparty/pcre2/CMakeLists.txt 2024-03-19 08:46:43.000000000 -0700
|
||||
+++ qtbase/src/3rdparty/pcre2/CMakeLists.txt 2024-06-06 21:52:20.539619500 -0700
|
||||
@@ -41,6 +41,7 @@
|
||||
src/pcre2_xclass.c
|
||||
DEFINES
|
||||
HAVE_CONFIG_H
|
||||
+ PCRE2_DISABLE_JIT
|
||||
PUBLIC_DEFINES
|
||||
PCRE2_CODE_UNIT_WIDTH=16
|
||||
PUBLIC_INCLUDE_DIRECTORIES
|
||||
@@ -52,23 +53,8 @@
|
||||
## Scopes:
|
||||
#####################################################################
|
||||
|
||||
-qt_internal_extend_target(BundledPcre2 CONDITION QNX OR UIKIT
|
||||
- DEFINES
|
||||
- PCRE2_DISABLE_JIT
|
||||
-)
|
||||
-
|
||||
-qt_internal_extend_target(BundledPcre2 CONDITION (TEST_architecture_arch STREQUAL "arm") AND WIN32
|
||||
- DEFINES
|
||||
- PCRE2_DISABLE_JIT
|
||||
-)
|
||||
-
|
||||
-qt_internal_extend_target(BundledPcre2 CONDITION (TEST_architecture_arch STREQUAL "arm64") AND WIN32
|
||||
- DEFINES
|
||||
- PCRE2_DISABLE_JIT
|
||||
-)
|
||||
-
|
||||
if (APPLE)
|
||||
- target_compile_options(BundledPcre2 PRIVATE "SHELL:-Xarch_arm64 -DPCRE2_DISABLE_JIT")
|
||||
+ target_compile_options(BundledPcre2 PRIVATE "SHELL:-Xarch_arm64")
|
||||
endif()
|
||||
|
||||
qt_internal_extend_target(BundledPcre2 CONDITION WIN32
|
||||
@@ -2239,6 +2239,8 @@ SCAJ-20152:
|
||||
gsHWFixes:
|
||||
alignSprite: 1 # Fixes vertical lines.
|
||||
textureInsideRT: 1 # Fixes corruption.
|
||||
halfPixelOffset: 4 # Aligns post bloom.
|
||||
nativeScaling: 2 # Fixes post effects.
|
||||
getSkipCount: "GSC_UrbanReign"
|
||||
SCAJ-20153:
|
||||
name: "コード・エイジ コマンダーズ"
|
||||
@@ -5600,7 +5602,7 @@ SCES-52033:
|
||||
author=refraction
|
||||
// Cop2 problems.
|
||||
patch=0,EE,003953F8,word,48438000
|
||||
patch=0,EE,003735FC,word,4B06521B
|
||||
patch=0,EE,003953FC,word,4B06521B
|
||||
author=YukiXXL
|
||||
// Speed Correction (25 FPS)
|
||||
patch=1,EE,00175E1C,extended,00000019
|
||||
@@ -6229,6 +6231,8 @@ SCES-53688:
|
||||
gsHWFixes:
|
||||
alignSprite: 1 # Fixes vertical lines.
|
||||
textureInsideRT: 1 # Fixes corruption.
|
||||
halfPixelOffset: 4 # Aligns post bloom.
|
||||
nativeScaling: 2 # Fixes post effects.
|
||||
getSkipCount: "GSC_UrbanReign"
|
||||
SCES-53795:
|
||||
name: "SingStar - '80s"
|
||||
@@ -7698,6 +7702,8 @@ SCKA-20065:
|
||||
gsHWFixes:
|
||||
alignSprite: 1 # Fixes vertical lines.
|
||||
textureInsideRT: 1 # Fixes corruption.
|
||||
halfPixelOffset: 4 # Aligns post bloom.
|
||||
nativeScaling: 2 # Fixes post effects.
|
||||
getSkipCount: "GSC_UrbanReign"
|
||||
SCKA-20066:
|
||||
name: "아이토이 - 플레이 3"
|
||||
@@ -11686,6 +11692,15 @@ SCUS-97264:
|
||||
// Cop2 problems.
|
||||
patch=0,EE,003735F8,word,48438000
|
||||
patch=0,EE,003735FC,word,4B06521B
|
||||
062BC79E:
|
||||
content: |-
|
||||
author=YukiXXL
|
||||
// Cop2 problems.
|
||||
patch=0,EE,00395D28,word,48438000
|
||||
patch=0,EE,00395D2C,word,4B06521B
|
||||
// Other languages SNDVAG fix
|
||||
patch=1,EE,204A0C3C,word,482E7325
|
||||
patch=1,EE,204A0C40,word,0000474F
|
||||
SCUS-97265:
|
||||
name: "Jak II"
|
||||
region: "NTSC-U"
|
||||
@@ -12073,12 +12088,21 @@ SCUS-97396:
|
||||
gsHWFixes:
|
||||
PCRTCOffsets: 1 # Fixes boot videos screen size.
|
||||
SCUS-97397:
|
||||
name: "Syphon Filter - The Omega Strain"
|
||||
name: "Syphon Filter - The Omega Strain Public Beta 1.0"
|
||||
region: "NTSC-U"
|
||||
gsHWFixes:
|
||||
autoFlush: 2 # Fixes lights going through walls.
|
||||
preloadFrameData: 1 # Fixes light flicker.
|
||||
halfPixelOffset: 2 # Corrects light position.
|
||||
gameFixes:
|
||||
- EETimingHack # Fixes random hangs.
|
||||
patches:
|
||||
C909A32E:
|
||||
content: |-
|
||||
author=YukiXXL
|
||||
// Cop2 problems.
|
||||
patch=0,EE,00367798,word,48438000
|
||||
patch=0,EE,0036779C,word,4B06521B
|
||||
SCUS-97398:
|
||||
name: "Siren [Demo]"
|
||||
region: "NTSC-U"
|
||||
@@ -35952,6 +35976,8 @@ SLPM-60272:
|
||||
gsHWFixes:
|
||||
alignSprite: 1 # Fixes vertical lines.
|
||||
textureInsideRT: 1 # Fixes corruption.
|
||||
halfPixelOffset: 4 # Aligns post bloom.
|
||||
nativeScaling: 2 # Fixes post effects.
|
||||
getSkipCount: "GSC_UrbanReign"
|
||||
SLPM-60273:
|
||||
name: "絶体絶命都市2 -凍てついた記憶たち- [体験版 Type-B]"
|
||||
@@ -60340,6 +60366,8 @@ SLPS-25557:
|
||||
gsHWFixes:
|
||||
alignSprite: 1 # Fixes vertical lines.
|
||||
textureInsideRT: 1 # Fixes corruption.
|
||||
halfPixelOffset: 4 # Aligns post bloom.
|
||||
nativeScaling: 2 # Fixes post effects.
|
||||
getSkipCount: "GSC_UrbanReign"
|
||||
SLPS-25558:
|
||||
name: "ネオジオ バトルコロシアム"
|
||||
@@ -70360,6 +70388,8 @@ SLUS-21209:
|
||||
gsHWFixes:
|
||||
alignSprite: 1 # Fixes vertical lines.
|
||||
textureInsideRT: 1 # Fixes corruption.
|
||||
halfPixelOffset: 4 # Aligns post bloom.
|
||||
nativeScaling: 2 # Fixes post effects.
|
||||
getSkipCount: "GSC_UrbanReign"
|
||||
SLUS-21212:
|
||||
name: "Spartan - Total Warrior"
|
||||
@@ -75768,6 +75798,9 @@ TCES-52033:
|
||||
0DDA2728:
|
||||
content: |-
|
||||
author=YukiXXL
|
||||
// Cop2 problems.
|
||||
patch=0,EE,0038E8E8,word,48438000
|
||||
patch=0,EE,0038E8EC,word,4B06521B
|
||||
// Speed Correction (25 FPS)
|
||||
patch=1,EE,00175a7c,extended,00000019
|
||||
patch=1,EE,00175848,extended,00000019
|
||||
|
||||
@@ -71,6 +71,7 @@
|
||||
#define PS_DITHER 0
|
||||
#define PS_DITHER_ADJUST 0
|
||||
#define PS_ZCLAMP 0
|
||||
#define PS_ZFLOOR 0
|
||||
#define PS_SCANMSK 0
|
||||
#define PS_AUTOMATIC_LOD 0
|
||||
#define PS_MANUAL_LOD 0
|
||||
@@ -138,7 +139,7 @@ struct PS_OUTPUT
|
||||
#endif
|
||||
#endif
|
||||
#endif
|
||||
#if PS_ZCLAMP
|
||||
#if PS_ZCLAMP || PS_ZFLOOR
|
||||
float depth : SV_Depth;
|
||||
#endif
|
||||
};
|
||||
@@ -1209,8 +1210,16 @@ PS_OUTPUT ps_main(PS_INPUT input)
|
||||
|
||||
#endif // PS_DATE != 1/2
|
||||
|
||||
#if PS_ZFLOOR
|
||||
float depth_value = floor(input.p.z * exp2(32.0f)) * exp2(-32.0f);
|
||||
#else
|
||||
float depth_value = input.p.z;
|
||||
#endif
|
||||
|
||||
#if PS_ZCLAMP
|
||||
output.depth = min(input.p.z, MaxDepthPS);
|
||||
output.depth = min(depth_value, MaxDepthPS);
|
||||
#elif PS_ZFLOOR
|
||||
output.depth = depth_value;
|
||||
#endif
|
||||
|
||||
return output;
|
||||
|
||||
@@ -1143,7 +1143,16 @@ void ps_main()
|
||||
#endif
|
||||
#endif
|
||||
|
||||
#if PS_ZCLAMP
|
||||
gl_FragDepth = min(gl_FragCoord.z, MaxDepthPS);
|
||||
#if PS_ZFLOOR
|
||||
float depth_value = floor(gl_FragCoord.z * exp2(32.0f)) * exp2(-32.0f);
|
||||
#else
|
||||
float depth_value = gl_FragCoord.z;
|
||||
#endif
|
||||
|
||||
#if PS_ZCLAMP
|
||||
gl_FragDepth = min(depth_value, MaxDepthPS);
|
||||
#elif PS_ZFLOOR
|
||||
gl_FragDepth = depth_value;
|
||||
#endif
|
||||
|
||||
}
|
||||
|
||||
@@ -288,6 +288,7 @@ void main()
|
||||
#define PS_DITHER 0
|
||||
#define PS_DITHER_ADJUST 0
|
||||
#define PS_ZCLAMP 0
|
||||
#define PS_ZFLOOR 0
|
||||
#define PS_FEEDBACK_LOOP 0
|
||||
#define PS_TEX_IS_FB 0
|
||||
#endif
|
||||
@@ -1400,8 +1401,16 @@ void main()
|
||||
#endif
|
||||
#endif
|
||||
|
||||
#if PS_ZFLOOR
|
||||
float depth_value = floor(gl_FragCoord.z * exp2(32.0f)) * exp2(-32.0f);;
|
||||
#else
|
||||
float depth_value = gl_FragCoord.z;
|
||||
#endif
|
||||
|
||||
#if PS_ZCLAMP
|
||||
gl_FragDepth = min(gl_FragCoord.z, MaxDepthPS);
|
||||
#elif PS_ZFLOOR
|
||||
gl_FragDepth = depth_value;
|
||||
#endif
|
||||
|
||||
#endif // PS_DATE
|
||||
|
||||
@@ -5,10 +5,14 @@
|
||||
#include "MainWindow.h"
|
||||
#include "QtHost.h"
|
||||
#include "SettingWidgetBinder.h"
|
||||
#include "VMManager.h"
|
||||
|
||||
#include <QtCore/QLatin1StringView>
|
||||
#include <QtCore/QUtf8StringView>
|
||||
#include <QtGui/QIcon>
|
||||
#include <QtWidgets/QCheckBox>
|
||||
#include <QtWidgets/QHBoxLayout>
|
||||
#include <QtWidgets/QLineEdit>
|
||||
#include <QtWidgets/QMenuBar>
|
||||
#include <QtWidgets/QScrollBar>
|
||||
|
||||
@@ -46,6 +50,12 @@ void LogWindow::updateSettings()
|
||||
const bool new_enabled = Host::GetBaseBoolSettingValue("Logging", "EnableLogWindow", false) && !Host::InNoGUIMode();
|
||||
const bool attach_to_main = Host::GetBaseBoolSettingValue("Logging", "AttachLogWindowToMainWindow", true);
|
||||
const bool curr_enabled = Log::IsHostOutputEnabled();
|
||||
const bool input_enabled = Host::GetBaseBoolSettingValue("Logging", "ShowEESIOInput");
|
||||
|
||||
if(g_log_window && g_log_window->m_line_input)
|
||||
{
|
||||
g_log_window->m_input_widget->setVisible(input_enabled);
|
||||
}
|
||||
|
||||
if (new_enabled == curr_enabled)
|
||||
{
|
||||
@@ -171,6 +181,10 @@ void LogWindow::createUi()
|
||||
action->setCheckable(true);
|
||||
SettingWidgetBinder::BindWidgetToBoolSetting(nullptr, action, "Logging", "EnableTimestamps", true);
|
||||
|
||||
action = settings_menu->addAction(tr("Show EE SIO &Input"));
|
||||
action->setCheckable(true);
|
||||
SettingWidgetBinder::BindWidgetToBoolSetting(nullptr, action, "Logging", "ShowEESIOInput", false);
|
||||
|
||||
settings_menu->addSeparator();
|
||||
|
||||
// TODO: Log Level
|
||||
@@ -181,6 +195,30 @@ void LogWindow::createUi()
|
||||
m_text->setTextInteractionFlags(Qt::TextSelectableByKeyboard | Qt::TextSelectableByMouse);
|
||||
m_text->setVerticalScrollBarPolicy(Qt::ScrollBarAlwaysOn);
|
||||
m_text->setWordWrapMode(QTextOption::WrapAnywhere);
|
||||
m_text->setSizePolicy(QSizePolicy::Expanding, QSizePolicy::Expanding);
|
||||
|
||||
m_line_input = new QLineEdit(this);
|
||||
connect(m_line_input, &QLineEdit::returnPressed, this, &LogWindow::onInputEntered);
|
||||
|
||||
m_local_echo_checkbox = new QCheckBox(tr("Local Echo"), this);
|
||||
m_local_echo_checkbox->setChecked(m_local_echo);
|
||||
connect(m_local_echo_checkbox, &QCheckBox::checkStateChanged, this, [&](Qt::CheckState state)
|
||||
{
|
||||
m_local_echo = state == Qt::CheckState::Checked;
|
||||
});
|
||||
|
||||
m_newline_on_enter_checkbox = new QCheckBox(tr("Newline on send"), this);
|
||||
m_newline_on_enter_checkbox->setChecked(m_newline_on_enter);
|
||||
connect(m_newline_on_enter_checkbox, &QCheckBox::checkStateChanged, this, [&](Qt::CheckState state)
|
||||
{
|
||||
m_newline_on_enter = state == Qt::CheckState::Checked;
|
||||
});
|
||||
|
||||
m_input_hbox = new QHBoxLayout(this);
|
||||
m_input_hbox->addWidget(m_line_input, 1);
|
||||
m_input_hbox->addWidget(m_local_echo_checkbox);
|
||||
m_input_hbox->addWidget(m_newline_on_enter_checkbox);
|
||||
m_input_hbox->setSpacing(8);
|
||||
|
||||
#if defined(_WIN32)
|
||||
QFont font("Consolas");
|
||||
@@ -194,7 +232,19 @@ void LogWindow::createUi()
|
||||
#endif
|
||||
m_text->setFont(font);
|
||||
|
||||
setCentralWidget(m_text);
|
||||
QWidget* central_widget = new QWidget(this);
|
||||
m_input_widget = new QWidget(this);
|
||||
m_input_widget->setVisible(Host::GetBaseBoolSettingValue("Logging", "ShowEESIOInput"));
|
||||
m_input_widget->setLayout(m_input_hbox);
|
||||
|
||||
QVBoxLayout* vlayout = new QVBoxLayout(central_widget);
|
||||
vlayout->setContentsMargins(0, 0, 0, 0);
|
||||
vlayout->setSpacing(0);
|
||||
vlayout->addWidget(m_text);
|
||||
vlayout->addWidget(m_input_widget);
|
||||
|
||||
central_widget->setLayout(vlayout);
|
||||
setCentralWidget(central_widget);
|
||||
}
|
||||
|
||||
void LogWindow::onClearTriggered()
|
||||
@@ -361,6 +411,31 @@ void LogWindow::appendMessage(quint32 level, quint32 color, const QString& messa
|
||||
}
|
||||
}
|
||||
|
||||
void LogWindow::onInputEntered()
|
||||
{
|
||||
QString text = m_line_input->text();
|
||||
if (text.isEmpty() && !m_newline_on_enter)
|
||||
return;
|
||||
|
||||
if(m_newline_on_enter)
|
||||
text.append('\n');
|
||||
|
||||
std::string str = text.toUtf8().toStdString();
|
||||
|
||||
if(VMManager::WriteBytesToEESIORXFIFO({reinterpret_cast<const u8*>(str.data()), str.size()}))
|
||||
{
|
||||
m_line_input->clear();
|
||||
|
||||
if(m_local_echo)
|
||||
// appendMessage expects a newline to be at the end of the string
|
||||
appendMessage(0, 0, m_newline_on_enter ? text : (text + '\n') );
|
||||
|
||||
QTextCursor cursor(m_text->textCursor());
|
||||
cursor.movePosition(QTextCursor::End);
|
||||
m_text->setTextCursor(cursor);
|
||||
}
|
||||
}
|
||||
|
||||
void LogWindow::saveSize()
|
||||
{
|
||||
const int current_width = Host::GetBaseIntSettingValue("UI", "LogWindowWidth", DEFAULT_WIDTH);
|
||||
|
||||
@@ -5,6 +5,9 @@
|
||||
|
||||
#include "common/Console.h"
|
||||
|
||||
#include <QtWidgets/QCheckBox>
|
||||
#include <QtWidgets/QHBoxLayout>
|
||||
#include <QtWidgets/QLineEdit>
|
||||
#include <QtWidgets/QMainWindow>
|
||||
#include <QtWidgets/QPlainTextEdit>
|
||||
|
||||
@@ -36,6 +39,7 @@ private Q_SLOTS:
|
||||
void onClearTriggered();
|
||||
void onSaveTriggered();
|
||||
void appendMessage(quint32 level, quint32 color, const QString& message);
|
||||
void onInputEntered();
|
||||
|
||||
private:
|
||||
static constexpr int DEFAULT_WIDTH = 750;
|
||||
@@ -45,8 +49,15 @@ private:
|
||||
void restoreSize();
|
||||
|
||||
QPlainTextEdit* m_text;
|
||||
QLineEdit* m_line_input;
|
||||
QMenu* m_level_menu;
|
||||
QWidget* m_input_widget;
|
||||
QHBoxLayout* m_input_hbox;
|
||||
QCheckBox* m_local_echo_checkbox;
|
||||
QCheckBox* m_newline_on_enter_checkbox;
|
||||
|
||||
bool m_local_echo = false;
|
||||
bool m_newline_on_enter = true;
|
||||
bool m_attached_to_main_window = true;
|
||||
bool m_destroying = false;
|
||||
};
|
||||
|
||||
@@ -67,6 +67,17 @@ struct KeyCodeName
|
||||
const char* icon_name;
|
||||
};
|
||||
|
||||
// Extended keys for left/right versions, Non conflicting with Qt::Key enum
|
||||
enum ExtendedKeys
|
||||
{
|
||||
Key_RightShift = 0x01100022,
|
||||
Key_LeftShift = 0x01100023,
|
||||
Key_RightControl = 0x01100024,
|
||||
Key_LeftControl = 0x01100025,
|
||||
Key_RightAlt = 0x01100026,
|
||||
Key_LeftAlt = 0x01100027,
|
||||
};
|
||||
|
||||
static constexpr const KeyCodeName s_qt_key_names[] = {
|
||||
{Qt::Key_Escape, "Escape", ICON_PF_ESC},
|
||||
{Qt::Key_Tab, "Tab", ICON_PF_TAB},
|
||||
@@ -92,6 +103,13 @@ static constexpr const KeyCodeName s_qt_key_names[] = {
|
||||
{Qt::Key_Control, "Control", ICON_PF_CTRL},
|
||||
{Qt::Key_Meta, "Meta", ICON_PF_SUPER},
|
||||
{Qt::Key_Alt, "Alt", ICON_PF_ALT},
|
||||
// patch for left and right versions of the keys
|
||||
{ExtendedKeys::Key_LeftShift, "LShift", ICON_PF_SHIFT},
|
||||
{ExtendedKeys::Key_RightShift, "RShift", ICON_PF_SHIFT},
|
||||
{ExtendedKeys::Key_LeftControl, "LCtrl", ICON_PF_CTRL},
|
||||
{ExtendedKeys::Key_RightControl, "RCtrl", ICON_PF_CTRL},
|
||||
{ExtendedKeys::Key_LeftAlt, "LAlt", ICON_PF_ALT},
|
||||
{ExtendedKeys::Key_RightAlt, "RAlt", ICON_PF_ALT},
|
||||
{Qt::Key_CapsLock, "CapsLock", ICON_PF_CAPS},
|
||||
{Qt::Key_NumLock, "NumLock", ICON_PF_NUMLOCK},
|
||||
{Qt::Key_ScrollLock, "ScrollLock", ICON_PF_SCRLK},
|
||||
@@ -575,6 +593,41 @@ u32 QtUtils::KeyEventToCode(const QKeyEvent* ev)
|
||||
const u8 keycode = set_keycode ? map_text_to_keycode(text) : 0;
|
||||
int key = ev->key();
|
||||
|
||||
if (key == Qt::Key_Shift || key == Qt::Key_Alt || key == Qt::Key_Control)
|
||||
{
|
||||
#if defined(Q_OS_WIN) or defined(Q_OS_LINUX)
|
||||
// Scan codes (Tested it)
|
||||
// 0x2A : Left shift
|
||||
// 0x36 : Right shift
|
||||
// 0x1D : Left ctrl
|
||||
// 0xE01D : Right ctrl
|
||||
// 0x38 : Left alt
|
||||
// right alt can become ctrl + right alt in some keyboard layouts (windows)
|
||||
// but thats fine for our use case
|
||||
switch (ev->nativeScanCode())
|
||||
{
|
||||
case 0x2A:
|
||||
key = ExtendedKeys::Key_LeftShift;
|
||||
break;
|
||||
case 0x36:
|
||||
key = ExtendedKeys::Key_RightShift;
|
||||
break;
|
||||
case 0x1D:
|
||||
key = ExtendedKeys::Key_LeftControl;
|
||||
break;
|
||||
case 0xE01D:
|
||||
key = ExtendedKeys::Key_RightControl;
|
||||
break;
|
||||
case 0x38:
|
||||
key = ExtendedKeys::Key_LeftAlt;
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
|
||||
#endif
|
||||
}
|
||||
|
||||
if (keycode != 0)
|
||||
key = keycode; // Override key if mapped
|
||||
|
||||
|
||||
@@ -14,8 +14,31 @@
|
||||
<string/>
|
||||
</property>
|
||||
<layout class="QGridLayout" name="gridLayout" columnstretch="0,1">
|
||||
<item row="3" column="1">
|
||||
<widget class="QComboBox" name="hwAutoFlush">
|
||||
<item row="8" column="0">
|
||||
<spacer name="verticalSpacer">
|
||||
<property name="orientation">
|
||||
<enum>Qt::Orientation::Vertical</enum>
|
||||
</property>
|
||||
<property name="sizeHint" stdset="0">
|
||||
<size>
|
||||
<width>20</width>
|
||||
<height>0</height>
|
||||
</size>
|
||||
</property>
|
||||
</spacer>
|
||||
</item>
|
||||
<item row="6" column="0">
|
||||
<widget class="QLabel" name="skipDrawLabel">
|
||||
<property name="text">
|
||||
<string>Skip Draw Range:</string>
|
||||
</property>
|
||||
<property name="buddy">
|
||||
<cstring>skipDrawStart</cstring>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item row="4" column="1">
|
||||
<widget class="QComboBox" name="textureInsideRt">
|
||||
<item>
|
||||
<property name="text">
|
||||
<string>Disabled (Default)</string>
|
||||
@@ -23,12 +46,12 @@
|
||||
</item>
|
||||
<item>
|
||||
<property name="text">
|
||||
<string>Enabled (Sprites Only)</string>
|
||||
<string>Inside Target</string>
|
||||
</property>
|
||||
</item>
|
||||
<item>
|
||||
<property name="text">
|
||||
<string>Enabled (All Primitives)</string>
|
||||
<string>Merge Targets</string>
|
||||
</property>
|
||||
</item>
|
||||
</widget>
|
||||
@@ -43,41 +66,6 @@
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item row="5" column="0">
|
||||
<widget class="QLabel" name="skipDrawLabel">
|
||||
<property name="text">
|
||||
<string>Skip Draw Range:</string>
|
||||
</property>
|
||||
<property name="buddy">
|
||||
<cstring>skipDrawStart</cstring>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item row="1" column="1">
|
||||
<widget class="QComboBox" name="cpuCLUTRender">
|
||||
<property name="currentText">
|
||||
<string extracomment="0 (Disabled)">0 (Disabled)</string>
|
||||
</property>
|
||||
<property name="currentIndex">
|
||||
<number>0</number>
|
||||
</property>
|
||||
<item>
|
||||
<property name="text">
|
||||
<string>0 (Disabled)</string>
|
||||
</property>
|
||||
</item>
|
||||
<item>
|
||||
<property name="text">
|
||||
<string>1 (Normal)</string>
|
||||
</property>
|
||||
</item>
|
||||
<item>
|
||||
<property name="text">
|
||||
<string>2 (Aggressive)</string>
|
||||
</property>
|
||||
</item>
|
||||
</widget>
|
||||
</item>
|
||||
<item row="0" column="1">
|
||||
<layout class="QHBoxLayout" name="cpuCLUTRenderLayout" stretch="0,0">
|
||||
<item>
|
||||
@@ -160,8 +148,36 @@
|
||||
</item>
|
||||
</layout>
|
||||
</item>
|
||||
<item row="4" column="1">
|
||||
<widget class="QComboBox" name="textureInsideRt">
|
||||
<item row="3" column="0">
|
||||
<widget class="QLabel" name="hwAutoFlushLabel">
|
||||
<property name="text">
|
||||
<string>Auto Flush:</string>
|
||||
</property>
|
||||
<property name="buddy">
|
||||
<cstring>hwAutoFlush</cstring>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item row="6" column="1">
|
||||
<layout class="QHBoxLayout" name="skipDrawLayout">
|
||||
<item>
|
||||
<widget class="QSpinBox" name="skipDrawStart">
|
||||
<property name="maximum">
|
||||
<number>10000</number>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item>
|
||||
<widget class="QSpinBox" name="skipDrawEnd">
|
||||
<property name="maximum">
|
||||
<number>10000</number>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
</layout>
|
||||
</item>
|
||||
<item row="2" column="1">
|
||||
<widget class="QComboBox" name="gpuTargetCLUTMode">
|
||||
<item>
|
||||
<property name="text">
|
||||
<string>Disabled (Default)</string>
|
||||
@@ -169,12 +185,57 @@
|
||||
</item>
|
||||
<item>
|
||||
<property name="text">
|
||||
<string>Inside Target</string>
|
||||
<string>Enabled (Exact Match)</string>
|
||||
</property>
|
||||
</item>
|
||||
<item>
|
||||
<property name="text">
|
||||
<string>Merge Targets</string>
|
||||
<string>Enabled (Check Inside Target)</string>
|
||||
</property>
|
||||
</item>
|
||||
</widget>
|
||||
</item>
|
||||
<item row="0" column="0">
|
||||
<widget class="QLabel" name="cpuCLUTRenderLabel">
|
||||
<property name="text">
|
||||
<string>CPU Sprite Render Size:</string>
|
||||
</property>
|
||||
<property name="buddy">
|
||||
<cstring>cpuSpriteRenderBW</cstring>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item row="2" column="0">
|
||||
<widget class="QLabel" name="gpuTargetCLUTLabel">
|
||||
<property name="text">
|
||||
<string extracomment="CLUT: Color Look Up Table, often referred to as a palette in non-PS2 things. GPU Target CLUT: GPU handling of when a game uses data from a render target as a CLUT.">GPU Target CLUT:</string>
|
||||
</property>
|
||||
<property name="buddy">
|
||||
<cstring>gpuTargetCLUTMode</cstring>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item row="1" column="1">
|
||||
<widget class="QComboBox" name="cpuCLUTRender">
|
||||
<property name="currentText">
|
||||
<string extracomment="0 (Disabled)">0 (Disabled)</string>
|
||||
</property>
|
||||
<property name="currentIndex">
|
||||
<number>0</number>
|
||||
</property>
|
||||
<item>
|
||||
<property name="text">
|
||||
<string>0 (Disabled)</string>
|
||||
</property>
|
||||
</item>
|
||||
<item>
|
||||
<property name="text">
|
||||
<string>1 (Normal)</string>
|
||||
</property>
|
||||
</item>
|
||||
<item>
|
||||
<property name="text">
|
||||
<string>2 (Aggressive)</string>
|
||||
</property>
|
||||
</item>
|
||||
</widget>
|
||||
@@ -189,7 +250,26 @@
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item row="6" column="0" colspan="2">
|
||||
<item row="3" column="1">
|
||||
<widget class="QComboBox" name="hwAutoFlush">
|
||||
<item>
|
||||
<property name="text">
|
||||
<string>Disabled (Default)</string>
|
||||
</property>
|
||||
</item>
|
||||
<item>
|
||||
<property name="text">
|
||||
<string>Enabled (Sprites Only)</string>
|
||||
</property>
|
||||
</item>
|
||||
<item>
|
||||
<property name="text">
|
||||
<string>Enabled (All Primitives)</string>
|
||||
</property>
|
||||
</item>
|
||||
</widget>
|
||||
</item>
|
||||
<item row="7" column="0" colspan="2">
|
||||
<layout class="QGridLayout" name="hwFixesLayout">
|
||||
<item row="4" column="0">
|
||||
<widget class="QCheckBox" name="estimateTextureRegion">
|
||||
@@ -256,28 +336,8 @@
|
||||
</item>
|
||||
</layout>
|
||||
</item>
|
||||
<item row="3" column="0">
|
||||
<widget class="QLabel" name="hwAutoFlushLabel">
|
||||
<property name="text">
|
||||
<string>Auto Flush:</string>
|
||||
</property>
|
||||
<property name="buddy">
|
||||
<cstring>hwAutoFlush</cstring>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item row="2" column="0">
|
||||
<widget class="QLabel" name="gpuTargetCLUTLabel">
|
||||
<property name="text">
|
||||
<string extracomment="CLUT: Color Look Up Table, often referred to as a palette in non-PS2 things. GPU Target CLUT: GPU handling of when a game uses data from a render target as a CLUT.">GPU Target CLUT:</string>
|
||||
</property>
|
||||
<property name="buddy">
|
||||
<cstring>gpuTargetCLUTMode</cstring>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item row="2" column="1">
|
||||
<widget class="QComboBox" name="gpuTargetCLUTMode">
|
||||
<item row="5" column="1">
|
||||
<widget class="QComboBox" name="limit24BitDepth">
|
||||
<item>
|
||||
<property name="text">
|
||||
<string>Disabled (Default)</string>
|
||||
@@ -285,57 +345,23 @@
|
||||
</item>
|
||||
<item>
|
||||
<property name="text">
|
||||
<string>Enabled (Exact Match)</string>
|
||||
<string>Prioritize Upper</string>
|
||||
</property>
|
||||
</item>
|
||||
<item>
|
||||
<property name="text">
|
||||
<string>Enabled (Check Inside Target)</string>
|
||||
<string>Prioritize Lower</string>
|
||||
</property>
|
||||
</item>
|
||||
</widget>
|
||||
</item>
|
||||
<item row="0" column="0">
|
||||
<widget class="QLabel" name="cpuCLUTRenderLabel">
|
||||
<item row="5" column="0">
|
||||
<widget class="QLabel" name="limitDepthLabel">
|
||||
<property name="text">
|
||||
<string>CPU Sprite Render Size:</string>
|
||||
</property>
|
||||
<property name="buddy">
|
||||
<cstring>cpuSpriteRenderBW</cstring>
|
||||
<string>Limit 24 Bit Depth</string>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item row="5" column="1">
|
||||
<layout class="QHBoxLayout" name="skipDrawLayout">
|
||||
<item>
|
||||
<widget class="QSpinBox" name="skipDrawStart">
|
||||
<property name="maximum">
|
||||
<number>10000</number>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item>
|
||||
<widget class="QSpinBox" name="skipDrawEnd">
|
||||
<property name="maximum">
|
||||
<number>10000</number>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
</layout>
|
||||
</item>
|
||||
<item row="7" column="0">
|
||||
<spacer name="verticalSpacer">
|
||||
<property name="orientation">
|
||||
<enum>Qt::Orientation::Vertical</enum>
|
||||
</property>
|
||||
<property name="sizeHint" stdset="0">
|
||||
<size>
|
||||
<width>20</width>
|
||||
<height>0</height>
|
||||
</size>
|
||||
</property>
|
||||
</spacer>
|
||||
</item>
|
||||
</layout>
|
||||
</widget>
|
||||
<tabstops>
|
||||
|
||||
@@ -147,6 +147,8 @@ GraphicsSettingsWidget::GraphicsSettingsWidget(SettingsWindow* settings_dialog,
|
||||
sif, m_fixes.disablePartialInvalidation, "EmuCore/GS", "UserHacks_DisablePartialInvalidation", false);
|
||||
SettingWidgetBinder::BindWidgetToIntSetting(
|
||||
sif, m_fixes.textureInsideRt, "EmuCore/GS", "UserHacks_TextureInsideRt", static_cast<int>(GSTextureInRtMode::Disabled));
|
||||
SettingWidgetBinder::BindWidgetToIntSetting(
|
||||
sif, m_fixes.limit24BitDepth, "EmuCore/GS", "UserHacks_Limit24BitDepth", static_cast<int>(GSLimit24BitDepth::Disabled));
|
||||
SettingWidgetBinder::BindWidgetToBoolSetting(sif, m_fixes.readTCOnClose, "EmuCore/GS", "UserHacks_ReadTCOnClose", false);
|
||||
SettingWidgetBinder::BindWidgetToBoolSetting(sif, m_fixes.estimateTextureRegion, "EmuCore/GS", "UserHacks_EstimateTextureRegion", false);
|
||||
SettingWidgetBinder::BindWidgetToBoolSetting(sif, m_fixes.gpuPaletteConversion, "EmuCore/GS", "paltex", false);
|
||||
@@ -624,6 +626,9 @@ GraphicsSettingsWidget::GraphicsSettingsWidget(SettingsWindow* settings_dialog,
|
||||
dialog()->registerWidgetHelp(m_fixes.textureInsideRt, tr("Texture Inside RT"), tr("Disabled"),
|
||||
tr("Allows the texture cache to reuse as an input texture the inner portion of a previous framebuffer."));
|
||||
|
||||
dialog()->registerWidgetHelp(m_fixes.limit24BitDepth, tr("Limit 24 Bit Depth"), tr("Disabled"),
|
||||
tr("Eats your cheese."));
|
||||
|
||||
dialog()->registerWidgetHelp(m_fixes.readTCOnClose, tr("Read Targets When Closing"), tr("Unchecked"),
|
||||
tr("Flushes all targets in the texture cache back to local memory when shutting down. Can prevent lost visuals when saving "
|
||||
"state or switching graphics APIs, but can also cause graphical corruption."));
|
||||
|
||||
File diff suppressed because it is too large
Load Diff
@@ -1043,21 +1043,11 @@ void Achievements::ClientLoadGameCallback(int result, const char* error_message,
|
||||
s_has_leaderboards = has_leaderboards;
|
||||
s_has_rich_presence = rc_client_has_rich_presence(client);
|
||||
s_game_icon = {};
|
||||
s_game_icon_url = {};
|
||||
s_game_icon_url = info->badge_url;
|
||||
|
||||
// ensure fullscreen UI is ready for notifications
|
||||
MTGS::RunOnGSThread(&ImGuiManager::InitializeFullscreenUI);
|
||||
|
||||
char url_buffer[URL_BUFFER_SIZE];
|
||||
if (int err = rc_client_game_get_image_url(info, url_buffer, std::size(url_buffer)); err == RC_OK)
|
||||
{
|
||||
s_game_icon_url = url_buffer;
|
||||
}
|
||||
else
|
||||
{
|
||||
ReportRCError(err, "rc_client_game_get_image_url() failed: ");
|
||||
}
|
||||
|
||||
if (const std::string_view badge_name = info->badge_name; !badge_name.empty())
|
||||
{
|
||||
s_game_icon = Path::Combine(s_image_directory, fmt::format("game_{}.png", badge_name));
|
||||
|
||||
@@ -432,6 +432,13 @@ enum class GSTextureInRtMode : u8
|
||||
MergeTargets,
|
||||
};
|
||||
|
||||
enum class GSLimit24BitDepth : u8
|
||||
{
|
||||
Disabled,
|
||||
PrioritizeUpper,
|
||||
PrioritizeLower,
|
||||
};
|
||||
|
||||
enum class GSBilinearDirtyMode : u8
|
||||
{
|
||||
Automatic,
|
||||
@@ -844,6 +851,7 @@ struct Pcsx2Config
|
||||
u8 UserHacks_CPUCLUTRender = 0;
|
||||
GSGPUTargetCLUTMode UserHacks_GPUTargetCLUTMode = GSGPUTargetCLUTMode::Disabled;
|
||||
GSTextureInRtMode UserHacks_TextureInsideRt = GSTextureInRtMode::Disabled;
|
||||
GSLimit24BitDepth UserHacks_Limit24BitDepth = GSLimit24BitDepth::Disabled;
|
||||
GSBilinearDirtyMode UserHacks_BilinearHack = GSBilinearDirtyMode::Automatic;
|
||||
TriFiltering TriFilter = TriFiltering::Automatic;
|
||||
s8 OverrideTextureBarriers = -1;
|
||||
|
||||
@@ -11,6 +11,8 @@
|
||||
std::vector<BreakPoint> CBreakPoints::breakPoints_;
|
||||
u32 CBreakPoints::breakSkipFirstAtEE_ = 0;
|
||||
u32 CBreakPoints::breakSkipFirstAtIop_ = 0;
|
||||
bool CBreakPoints::pendingClearSkipFirstAtEE_ = false;
|
||||
bool CBreakPoints::pendingClearSkipFirstAtIop_ = false;
|
||||
std::vector<MemCheck> CBreakPoints::memChecks_;
|
||||
std::vector<MemCheck*> CBreakPoints::cleanupMemChecks_;
|
||||
bool CBreakPoints::breakpointTriggered_ = false;
|
||||
@@ -391,10 +393,12 @@ void CBreakPoints::SetSkipFirst(BreakPointCpu cpu, u32 pc)
|
||||
if (cpu == BREAKPOINT_EE)
|
||||
{
|
||||
breakSkipFirstAtEE_ = standardizeBreakpointAddress(pc);
|
||||
pendingClearSkipFirstAtEE_ = false;
|
||||
}
|
||||
else if (cpu == BREAKPOINT_IOP)
|
||||
{
|
||||
breakSkipFirstAtIop_ = pc;
|
||||
pendingClearSkipFirstAtIop_ = false;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -407,10 +411,29 @@ u32 CBreakPoints::CheckSkipFirst(BreakPointCpu cpu, u32 cmpPc)
|
||||
return 0;
|
||||
}
|
||||
|
||||
void CBreakPoints::ClearSkipFirst()
|
||||
void CBreakPoints::ClearSkipFirst(BreakPointCpu cpu)
|
||||
{
|
||||
breakSkipFirstAtEE_ = 0;
|
||||
breakSkipFirstAtIop_ = 0;
|
||||
if((cpu & BREAKPOINT_EE) != 0)
|
||||
pendingClearSkipFirstAtEE_ = true;
|
||||
else if ((cpu & BREAKPOINT_IOP) != 0)
|
||||
pendingClearSkipFirstAtIop_ = true;
|
||||
|
||||
if(cpu == BREAKPOINT_IOP_AND_EE)
|
||||
CommitClearSkipFirst(BREAKPOINT_IOP_AND_EE);
|
||||
}
|
||||
|
||||
void CBreakPoints::CommitClearSkipFirst(BreakPointCpu cpu)
|
||||
{
|
||||
if((cpu & BREAKPOINT_EE) != 0 && pendingClearSkipFirstAtEE_)
|
||||
{
|
||||
pendingClearSkipFirstAtEE_ = false;
|
||||
breakSkipFirstAtEE_ = 0;
|
||||
}
|
||||
else if ((cpu & BREAKPOINT_IOP) != 0 && pendingClearSkipFirstAtIop_)
|
||||
{
|
||||
pendingClearSkipFirstAtIop_ = true;
|
||||
breakSkipFirstAtIop_ = 0;
|
||||
}
|
||||
}
|
||||
|
||||
const std::vector<MemCheck> CBreakPoints::GetMemCheckRanges()
|
||||
|
||||
@@ -135,7 +135,8 @@ public:
|
||||
|
||||
static void SetSkipFirst(BreakPointCpu cpu, u32 pc);
|
||||
static u32 CheckSkipFirst(BreakPointCpu cpu, u32 pc);
|
||||
static void ClearSkipFirst();
|
||||
static void ClearSkipFirst(BreakPointCpu cpu = BREAKPOINT_IOP_AND_EE);
|
||||
static void CommitClearSkipFirst(BreakPointCpu cpu);
|
||||
|
||||
// Includes uncached addresses.
|
||||
static const std::vector<MemCheck> GetMemCheckRanges();
|
||||
@@ -169,9 +170,9 @@ private:
|
||||
|
||||
static std::vector<BreakPoint> breakPoints_;
|
||||
static u32 breakSkipFirstAtEE_;
|
||||
static u64 breakSkipFirstTicksEE_;
|
||||
static bool pendingClearSkipFirstAtEE_;
|
||||
static u32 breakSkipFirstAtIop_;
|
||||
static u64 breakSkipFirstTicksIop_;
|
||||
static bool pendingClearSkipFirstAtIop_;
|
||||
|
||||
static bool breakpointTriggered_;
|
||||
static BreakPointCpu breakpointTriggeredCpu_;
|
||||
|
||||
@@ -806,12 +806,12 @@ void GSState::DumpTransferList(const std::string& filename)
|
||||
(*file) << std::endl;
|
||||
|
||||
// clear, EE->GS, or GS->GS
|
||||
(*file) << LIST_ITEM << "type: " << (transfer.zero_clear ? "clear" : (transfer.ee_to_gs ? "EE_to_GS" : "GS_to_GS")) << std::endl;
|
||||
(*file) << LIST_ITEM << "type: " << (transfer.zero_clear ? "clear" : ((transfer.transfer_type == EEGS_TransferType::EE_to_GS) ? "EE_to_GS" : "GS_to_GS")) << std::endl;
|
||||
|
||||
// Dump BITBLTBUF
|
||||
(*file) << INDENT << "BITBLTBUF: " << OPEN_MAP;
|
||||
|
||||
const bool gs_to_gs = !transfer.ee_to_gs && !transfer.zero_clear;
|
||||
const bool gs_to_gs = (transfer.transfer_type == EEGS_TransferType::GS_to_GS) && !transfer.zero_clear;
|
||||
|
||||
if (gs_to_gs)
|
||||
{
|
||||
@@ -857,7 +857,7 @@ void GSState::DumpTransferImages()
|
||||
const GSUploadQueue& transfer = m_draw_transfers[i];
|
||||
|
||||
std::string filename;
|
||||
if (transfer.ee_to_gs || transfer.zero_clear)
|
||||
if ((transfer.transfer_type == EEGS_TransferType::EE_to_GS) || transfer.zero_clear)
|
||||
{
|
||||
// clear or EE->GS: only the destination info is relevant.
|
||||
filename = GetDrawDumpPath("%05d_transfer%02d_%s_%04x_%d_%s_%d_%d_%d_%d.png",
|
||||
@@ -2365,7 +2365,7 @@ void GSState::Write(const u8* mem, int len)
|
||||
|
||||
s_last_transfer_draw_n = s_n;
|
||||
// Store the transfer for preloading new RT's.
|
||||
if ((m_draw_transfers.size() > 0 && blit.DBP == m_draw_transfers.back().blit.DBP))
|
||||
if ((m_draw_transfers.size() > 0 && blit.DBP == m_draw_transfers.back().blit.DBP && m_draw_transfers.back().transfer_type == EEGS_TransferType::EE_to_GS))
|
||||
{
|
||||
// Same BP, let's update the rect.
|
||||
GSUploadQueue transfer = m_draw_transfers.back();
|
||||
@@ -2377,7 +2377,7 @@ void GSState::Write(const u8* mem, int len)
|
||||
}
|
||||
else
|
||||
{
|
||||
const GSUploadQueue new_transfer = { blit, r, s_n, false, true };
|
||||
const GSUploadQueue new_transfer = {blit, r, s_n, false, EEGS_TransferType::EE_to_GS};
|
||||
m_draw_transfers.push_back(new_transfer);
|
||||
}
|
||||
|
||||
@@ -2519,21 +2519,31 @@ void GSState::Move()
|
||||
|
||||
InvalidateLocalMem(m_env.BITBLTBUF, GSVector4i(sx, sy, sx + w, sy + h));
|
||||
InvalidateVideoMem(m_env.BITBLTBUF, GSVector4i(dx, dy, dx + w, dy + h));
|
||||
const bool overlaps = m_env.BITBLTBUF.SBP == m_env.BITBLTBUF.DBP;
|
||||
const bool intersect = overlaps && !(GSVector4i(sx, sy, sx + w, sy + h).rintersect(GSVector4i(dx, dy, dx + w, dy + h)).rempty());
|
||||
|
||||
int xinc = 1;
|
||||
int yinc = 1;
|
||||
|
||||
if (m_env.TRXPOS.DIRX)
|
||||
{
|
||||
sx += w - 1;
|
||||
dx += w - 1;
|
||||
xinc = -1;
|
||||
// Only allow it to reverse if the destination is behind the source.
|
||||
if (!intersect || (sx <= dx && (sx == dx || ((!m_env.TRXPOS.DIRY && sy >= dy) || (m_env.TRXPOS.DIRY && sy < dy)))))
|
||||
{
|
||||
sx += w - 1;
|
||||
dx += w - 1;
|
||||
xinc = -1;
|
||||
}
|
||||
}
|
||||
if (m_env.TRXPOS.DIRY)
|
||||
{
|
||||
sy += h - 1;
|
||||
dy += h - 1;
|
||||
yinc = -1;
|
||||
// Only allow it to reverse if the destination is behind the source.
|
||||
if (!intersect || (sy <= dy && (sy == dy || ((!m_env.TRXPOS.DIRX && sx >= dx) || (m_env.TRXPOS.DIRX && sx < dx)))))
|
||||
{
|
||||
sy += h - 1;
|
||||
dy += h - 1;
|
||||
yinc = -1;
|
||||
}
|
||||
}
|
||||
|
||||
const GSLocalMemory::psm_t& spsm = GSLocalMemory::m_psm[m_env.BITBLTBUF.SPSM];
|
||||
@@ -2556,7 +2566,7 @@ void GSState::Move()
|
||||
|
||||
s_last_transfer_draw_n = s_n;
|
||||
// Store the transfer for preloading new RT's.
|
||||
if ((m_draw_transfers.size() > 0 && m_env.BITBLTBUF.DBP == m_draw_transfers.back().blit.DBP))
|
||||
if ((m_draw_transfers.size() > 0 && m_env.BITBLTBUF.DBP == m_draw_transfers.back().blit.DBP && m_draw_transfers.back().transfer_type == EEGS_TransferType::GS_to_GS))
|
||||
{
|
||||
// Same BP, let's update the rect.
|
||||
GSUploadQueue transfer = m_draw_transfers.back();
|
||||
@@ -2568,11 +2578,11 @@ void GSState::Move()
|
||||
}
|
||||
else
|
||||
{
|
||||
const GSUploadQueue new_transfer = { m_env.BITBLTBUF, r, s_n, false, false };
|
||||
const GSUploadQueue new_transfer = {m_env.BITBLTBUF, r, s_n, false, EEGS_TransferType::GS_to_GS};
|
||||
m_draw_transfers.push_back(new_transfer);
|
||||
}
|
||||
|
||||
auto copy = [this, sbp, dbp, sx, sy, dx, dy, w, h, yinc, xinc](const GSOffset& dpo, const GSOffset& spo, auto&& pxCopyFn)
|
||||
auto copy = [this, sbp, dbp, sx, sy, dx, dy, w, h, yinc, xinc, intersect](const GSOffset& dpo, const GSOffset& spo, auto&& pxCopyFn)
|
||||
{
|
||||
int _sy = sy, _dy = dy; // Faster with local copied variables, compiler optimizations are dumb
|
||||
if (xinc > 0)
|
||||
@@ -2584,8 +2594,6 @@ void GSState::Move()
|
||||
// Copying from itself to itself (rotating textures) used in Gitaroo Man stage 8
|
||||
// What probably happens is because the copy is buffered, the source stays just ahead of the destination.
|
||||
// No need to do all this if the copy source/destination don't intersect, however.
|
||||
const bool intersect = !(GSVector4i(sx, sy, sx + w, sy + h).rintersect(GSVector4i(dx, dy, dx + w, dy + h)).rempty());
|
||||
|
||||
if (intersect && sbp == dbp && (((_sy < _dy) && ((ypage + page_height) > _dy)) || ((sx < dx) && ((xpage + page_width) > dx))))
|
||||
{
|
||||
int starty = (yinc > 0) ? 0 : h-1;
|
||||
@@ -4657,6 +4665,14 @@ __forceinline void GSState::VertexKick(u32 skip)
|
||||
u32 next = m_vertex.next;
|
||||
u32 xy_tail = m_vertex.xy_tail;
|
||||
|
||||
if (GSIsHardwareRenderer() && GSLocalMemory::m_psm[m_context->ZBUF.PSM].bpp == 32)
|
||||
{
|
||||
if (GSConfig.UserHacks_Limit24BitDepth == GSLimit24BitDepth::PrioritizeUpper)
|
||||
m_v.XYZ.Z = ((m_v.XYZ.Z >> 8) & ~0xFF) | (m_v.XYZ.Z & 0xFF);
|
||||
else if (GSConfig.UserHacks_Limit24BitDepth == GSLimit24BitDepth::PrioritizeLower)
|
||||
m_v.XYZ.Z &= 0x00FFFFFF;
|
||||
}
|
||||
|
||||
// callers should write XYZUVF to m_v.m[1] in one piece to have this load store-forwarded, either by the cpu or the compiler when this function is inlined
|
||||
|
||||
const GSVector4i new_v0(m_v.m[0]);
|
||||
|
||||
@@ -211,13 +211,20 @@ protected:
|
||||
void CorrectATEAlphaMinMax(const u32 atst, const int aref);
|
||||
|
||||
public:
|
||||
enum EEGS_TransferType
|
||||
{
|
||||
EE_to_GS,
|
||||
GS_to_GS,
|
||||
GS_to_EE
|
||||
};
|
||||
|
||||
struct GSUploadQueue
|
||||
{
|
||||
GIFRegBITBLTBUF blit;
|
||||
GSVector4i rect;
|
||||
int draw;
|
||||
bool zero_clear;
|
||||
bool ee_to_gs;
|
||||
EEGS_TransferType transfer_type;
|
||||
};
|
||||
|
||||
enum NoGapsType
|
||||
|
||||
@@ -401,6 +401,7 @@ struct alignas(16) GSHWDrawConfig
|
||||
|
||||
// Depth clamp
|
||||
u32 zclamp : 1;
|
||||
u32 zfloor : 1;
|
||||
|
||||
// Hack
|
||||
u32 tcoffsethack : 1;
|
||||
|
||||
@@ -1760,6 +1760,7 @@ void GSDevice11::SetupPS(const PSSelector& sel, const GSHWDrawConfig::PSConstant
|
||||
sm.AddMacro("PS_DITHER", sel.dither);
|
||||
sm.AddMacro("PS_DITHER_ADJUST", sel.dither_adjust);
|
||||
sm.AddMacro("PS_ZCLAMP", sel.zclamp);
|
||||
sm.AddMacro("PS_ZFLOOR", sel.zfloor);
|
||||
sm.AddMacro("PS_SCANMSK", sel.scanmsk);
|
||||
sm.AddMacro("PS_AUTOMATIC_LOD", sel.automatic_lod);
|
||||
sm.AddMacro("PS_MANUAL_LOD", sel.manual_lod);
|
||||
|
||||
@@ -2922,6 +2922,7 @@ const ID3DBlob* GSDevice12::GetTFXPixelShader(const GSHWDrawConfig::PSSelector&
|
||||
sm.AddMacro("PS_DITHER", sel.dither);
|
||||
sm.AddMacro("PS_DITHER_ADJUST", sel.dither_adjust);
|
||||
sm.AddMacro("PS_ZCLAMP", sel.zclamp);
|
||||
sm.AddMacro("PS_ZFLOOR", sel.zfloor);
|
||||
sm.AddMacro("PS_SCANMSK", sel.scanmsk);
|
||||
sm.AddMacro("PS_AUTOMATIC_LOD", sel.automatic_lod);
|
||||
sm.AddMacro("PS_MANUAL_LOD", sel.manual_lod);
|
||||
|
||||
@@ -3194,6 +3194,7 @@ void GSRendererHW::Draw()
|
||||
float target_scale = GetTextureScaleFactor();
|
||||
bool scaled_copy = false;
|
||||
int scale_draw = IsScalingDraw(src, m_primitive_covers_without_gaps != NoGapsType::GapsFound);
|
||||
|
||||
if (GSConfig.UserHacks_NativeScaling != GSNativeScaling::Off)
|
||||
{
|
||||
if (target_scale > 1.0f && scale_draw > 0)
|
||||
@@ -3202,9 +3203,15 @@ void GSRendererHW::Draw()
|
||||
// 2 == Upscale, so likely putting it over the top of the render target.
|
||||
if (scale_draw == 1)
|
||||
{
|
||||
if (!PRIM->ABE || GSConfig.UserHacks_NativeScaling < GSNativeScaling::NormalUpscaled)
|
||||
target_scale = 1.0f;
|
||||
m_downscale_source = src->m_from_target ? src->m_from_target->GetScale() > 1.0f : false;
|
||||
const bool highlights_only = m_cached_ctx.TEST.ATE || (PRIM->ABE && m_context->ALPHA.C == 2 && m_context->ALPHA.FIX == 255);
|
||||
// If it's alpha tested/stenciling for the bloom, we don't want to using the Upscaled versions. Also if the source is already native scale, may as well keep it so.
|
||||
// Overlap check is for games such as Tomb Raider, where it recursively downsamples.
|
||||
// Also make sure this isn't a blend, just draw (possibly with modulation).
|
||||
if (GSConfig.UserHacks_NativeScaling < GSNativeScaling::NormalUpscaled || highlights_only || !PRIM->ABE || (src->m_from_target && src->m_from_target->Overlaps(m_cached_ctx.FRAME.Block(), m_cached_ctx.FRAME.FBW, m_cached_ctx.FRAME.PSM, m_r)))
|
||||
{
|
||||
target_scale = 1.0f;
|
||||
}
|
||||
}
|
||||
else
|
||||
m_downscale_source = ((GSConfig.UserHacks_NativeScaling != GSNativeScaling::Aggressive && GSConfig.UserHacks_NativeScaling != GSNativeScaling::AggressiveUpscaled) || !src->m_from_target) ? false : src->m_from_target->GetScale() > 1.0f; // Bad for GTA + Full Spectrum Warrior, good for Sacred Blaze + Parappa.
|
||||
@@ -3232,7 +3239,7 @@ void GSRendererHW::Draw()
|
||||
// This upscaling hack is for games which construct P8 textures by drawing a bunch of small sprites in C32,
|
||||
// then reinterpreting it as P8. We need to keep the off-screen intermediate textures at native resolution,
|
||||
// but not propagate that through to the normal render targets. Test Case: Crash Wrath of Cortex.
|
||||
if (no_ds && src && !m_channel_shuffle && src->m_from_target && (GSConfig.UserHacks_NativePaletteDraw || (src->m_target_direct && src->m_from_target->m_downscaled && scale_draw <= 1)) &&
|
||||
if (no_ds && src && !m_channel_shuffle && src->m_from_target && (GSConfig.UserHacks_NativePaletteDraw || (src->m_target_direct && src->m_from_target->m_downscaled && scale_draw <= 1)) &&
|
||||
src->m_scale == 1.0f && (src->m_TEX0.PSM == PSMT8 || src->m_TEX0.TBP0 == m_cached_ctx.FRAME.Block()))
|
||||
{
|
||||
GL_CACHE("HW: Using native resolution for target based on texture source");
|
||||
@@ -3525,7 +3532,7 @@ void GSRendererHW::Draw()
|
||||
|
||||
// Preserve downscaled target when copying directly from a downscaled target, or it's a normal draw using a downscaled target. Clears that are drawing to the target can also preserve size.
|
||||
// Of course if this size is different (in width) or this is a shuffle happening, this will be bypassed.
|
||||
const bool preserve_downscale_draw = (GSConfig.UserHacks_NativeScaling != GSNativeScaling::Off && (std::abs(scale_draw) == 1 || (scale_draw == 0 && src && src->m_from_target && src->m_from_target->m_downscaled))) || is_possible_mem_clear == ClearType::ClearWithDraw;
|
||||
const bool preserve_downscale_draw = (GSConfig.UserHacks_NativeScaling != GSNativeScaling::Off && ((std::abs(scale_draw) == 1 && !scaled_copy) || (scale_draw == 0 && src && src->m_from_target && src->m_from_target->m_downscaled))) || is_possible_mem_clear == ClearType::ClearWithDraw;
|
||||
|
||||
rt = g_texture_cache->LookupTarget(FRAME_TEX0, t_size, ((src && src->m_scale != 1) && (GSConfig.UserHacks_NativeScaling == GSNativeScaling::Normal || GSConfig.UserHacks_NativeScaling == GSNativeScaling::NormalUpscaled) && !possible_shuffle) ? GetTextureScaleFactor() : target_scale, GSTextureCache::RenderTarget, true,
|
||||
fm, false, force_preload, preserve_rt_rgb, preserve_rt_alpha, lookup_rect, possible_shuffle, is_possible_mem_clear && FRAME_TEX0.TBP0 != m_cached_ctx.ZBUF.Block(),
|
||||
@@ -5138,6 +5145,7 @@ void GSRendererHW::EmulateZbuffer(const GSTextureCache::Target* ds)
|
||||
m_conf.cb_vs.max_depth = GSVector2i(0xFFFFFFFF);
|
||||
//ps_cb.MaxDepth = GSVector4(0.0f, 0.0f, 0.0f, 1.0f);
|
||||
m_conf.ps.zclamp = 0;
|
||||
m_conf.ps.zfloor = !m_cached_ctx.ZBUF.ZMSK;
|
||||
|
||||
if (clamp_z)
|
||||
{
|
||||
@@ -7024,7 +7032,7 @@ __ri void GSRendererHW::HandleTextureHazards(const GSTextureCache::Target* rt, c
|
||||
// When using native HPO, the top-left column/row of pixels are often not drawn. Clamp these away to avoid sampling black,
|
||||
// causing bleeding into the edges of the downsampled texture.
|
||||
const u32 downsample_factor = static_cast<u32>(src_target->GetScale());
|
||||
const GSVector2i clamp_min = (GSConfig.UserHacks_HalfPixelOffset < GSHalfPixelOffset::Native) ?
|
||||
const GSVector2i clamp_min = (GSConfig.UserHacks_HalfPixelOffset != GSHalfPixelOffset::Native) ?
|
||||
GSVector2i(0, 0) :
|
||||
GSVector2i(downsample_factor, downsample_factor);
|
||||
GSVector4i copy_rect = tmm.coverage;
|
||||
@@ -9222,7 +9230,7 @@ int GSRendererHW::IsScalingDraw(GSTextureCache::Source* src, bool no_gaps)
|
||||
const bool no_resize = (std::abs(draw_size.x - tex_size.x) <= 1 && std::abs(draw_size.y - tex_size.y) <= 1);
|
||||
const bool can_maintain = no_resize || (!is_target_src && m_index.tail == 2);
|
||||
|
||||
if (!src || ((!is_target_src || src->m_from_target->m_downscaled) && can_maintain))
|
||||
if (!src || ((!is_target_src || (src->m_from_target->m_downscaled || GSConfig.UserHacks_NativeScaling > GSNativeScaling::Aggressive)) && can_maintain))
|
||||
return -1;
|
||||
|
||||
const GSDrawingContext& next_ctx = m_env.CTXT[m_env.PRIM.CTXT];
|
||||
@@ -9237,7 +9245,7 @@ int GSRendererHW::IsScalingDraw(GSTextureCache::Source* src, bool no_gaps)
|
||||
// Only allow non-bilineared downscales if it's most of the target (misdetections of shadows in Naruto, Transformers etc), otherwise it's fine.
|
||||
const GSVector4i src_valid = src->m_from_target ? src->m_from_target->m_valid : src->m_valid_rect;
|
||||
const GSVector2i tex_size_half = GSVector2i((src->GetRegion().HasX() ? src->GetRegionSize().x : src_valid.width()) / 2, (src->GetRegion().HasY() ? src->GetRegionSize().y : src_valid.height()) / 2);
|
||||
const bool possible_downscale = m_context->TEX1.MMIN == 1 || !src->m_from_target || src->m_from_target->m_downscaled || tex_size.x >= tex_size_half.x || tex_size.y >= tex_size_half.y;
|
||||
const bool possible_downscale = m_context->TEX1.MMIN == 1 || !src->m_from_target || src->m_from_target->m_downscaled || GSConfig.UserHacks_NativeScaling > GSNativeScaling::Aggressive || tex_size.x >= tex_size_half.x || tex_size.y >= tex_size_half.y;
|
||||
|
||||
if (is_downscale && (draw_size.x >= PCRTCDisplays.GetResolution().x || !possible_downscale))
|
||||
return 0;
|
||||
|
||||
@@ -2756,7 +2756,22 @@ GSTextureCache::Target* GSTextureCache::LookupTarget(GIFRegTEX0 TEX0, const GSVe
|
||||
if (!tex)
|
||||
return nullptr;
|
||||
|
||||
g_gs_device->StretchRect(dst->m_texture, sRect, tex, dRect, (type == RenderTarget) ? ShaderConvert::COPY : ShaderConvert::DEPTH_COPY, dst->m_scale < scale);
|
||||
if (scale == 1.0f)
|
||||
{
|
||||
// When using native HPO, the top-left column/row of pixels are often not drawn. Clamp these away to avoid sampling black,
|
||||
// causing bleeding into the edges of the downsampled texture.
|
||||
const u32 downsample_factor = static_cast<u32>(dst->GetScale());
|
||||
const GSVector2i clamp_min = (GSConfig.UserHacks_HalfPixelOffset != GSHalfPixelOffset::Native) ?
|
||||
GSVector2i(0, 0) :
|
||||
GSVector2i(downsample_factor, downsample_factor);
|
||||
|
||||
const GSVector4 dRect = GSVector4(dst->GetUnscaledRect());
|
||||
|
||||
g_gs_device->FilteredDownsampleTexture(dst->m_texture, tex, downsample_factor, clamp_min, dRect);
|
||||
}
|
||||
else
|
||||
g_gs_device->StretchRect(dst->m_texture, sRect, tex, dRect, (type == RenderTarget) ? ShaderConvert::COPY : ShaderConvert::DEPTH_COPY, dst->m_scale < scale);
|
||||
|
||||
g_perfmon.Put(GSPerfMon::TextureCopies, 1);
|
||||
m_target_memory_usage = (m_target_memory_usage - dst->m_texture->GetMemUsage()) + tex->GetMemUsage();
|
||||
|
||||
|
||||
@@ -1878,6 +1878,7 @@ void GSDeviceMTL::MRESetHWPipelineState(GSHWDrawConfig::VSSelector vssel, GSHWDr
|
||||
setFnConstantI(m_fn_constants, pssel.dither, GSMTLConstantIndex_PS_DITHER);
|
||||
setFnConstantI(m_fn_constants, pssel.dither_adjust, GSMTLConstantIndex_PS_DITHER_ADJUST);
|
||||
setFnConstantB(m_fn_constants, pssel.zclamp, GSMTLConstantIndex_PS_ZCLAMP);
|
||||
setFnConstantB(m_fn_constants, pssel.zfloor, GSMTLConstantIndex_PS_ZFLOOR);
|
||||
setFnConstantB(m_fn_constants, pssel.tcoffsethack, GSMTLConstantIndex_PS_TCOFFSETHACK);
|
||||
setFnConstantB(m_fn_constants, pssel.urban_chaos_hle, GSMTLConstantIndex_PS_URBAN_CHAOS_HLE);
|
||||
setFnConstantB(m_fn_constants, pssel.tales_of_abyss_hle, GSMTLConstantIndex_PS_TALES_OF_ABYSS_HLE);
|
||||
|
||||
@@ -208,6 +208,7 @@ enum GSMTLFnConstants
|
||||
GSMTLConstantIndex_PS_DITHER,
|
||||
GSMTLConstantIndex_PS_DITHER_ADJUST,
|
||||
GSMTLConstantIndex_PS_ZCLAMP,
|
||||
GSMTLConstantIndex_PS_ZFLOOR,
|
||||
GSMTLConstantIndex_PS_TCOFFSETHACK,
|
||||
GSMTLConstantIndex_PS_URBAN_CHAOS_HLE,
|
||||
GSMTLConstantIndex_PS_TALES_OF_ABYSS_HLE,
|
||||
|
||||
@@ -61,6 +61,7 @@ constant uint PS_CHANNEL [[function_constant(GSMTLConstantIndex_PS_CH
|
||||
constant uint PS_DITHER [[function_constant(GSMTLConstantIndex_PS_DITHER)]];
|
||||
constant uint PS_DITHER_ADJUST [[function_constant(GSMTLConstantIndex_PS_DITHER_ADJUST)]];
|
||||
constant bool PS_ZCLAMP [[function_constant(GSMTLConstantIndex_PS_ZCLAMP)]];
|
||||
constant bool PS_ZFLOOR [[function_constant(GSMTLConstantIndex_PS_ZFLOOR)]];
|
||||
constant bool PS_TCOFFSETHACK [[function_constant(GSMTLConstantIndex_PS_TCOFFSETHACK)]];
|
||||
constant bool PS_URBAN_CHAOS_HLE [[function_constant(GSMTLConstantIndex_PS_URBAN_CHAOS_HLE)]];
|
||||
constant bool PS_TALES_OF_ABYSS_HLE [[function_constant(GSMTLConstantIndex_PS_TALES_OF_ABYSS_HLE)]];
|
||||
@@ -102,6 +103,7 @@ constant bool NEEDS_RT = NEEDS_RT_FOR_AFAIL || NEEDS_RT_EARLY || (!PS_PRIM_CHECK
|
||||
|
||||
constant bool PS_COLOR0 = !PS_NO_COLOR;
|
||||
constant bool PS_COLOR1 = !PS_NO_COLOR1;
|
||||
constant bool PS_ZOUTPUT = PS_ZCLAMP || PS_ZFLOOR;
|
||||
|
||||
struct MainVSIn
|
||||
{
|
||||
@@ -137,7 +139,7 @@ struct MainPSOut
|
||||
{
|
||||
float4 c0 [[color(0), index(0), function_constant(PS_COLOR0)]];
|
||||
float4 c1 [[color(0), index(1), function_constant(PS_COLOR1)]];
|
||||
float depth [[depth(less), function_constant(PS_ZCLAMP)]];
|
||||
float depth [[depth(less), function_constant(PS_ZOUTPUT)]];
|
||||
};
|
||||
|
||||
// MARK: - Vertex functions
|
||||
@@ -1209,8 +1211,13 @@ struct PSMain
|
||||
}
|
||||
if (PS_COLOR1)
|
||||
out.c1 = alpha_blend;
|
||||
|
||||
float depth_value = PS_ZFLOOR ? (floor(in.p.z * exp2(32.0f)) * exp2(-32.0f)) : in.p.z;
|
||||
|
||||
if (PS_ZCLAMP)
|
||||
out.depth = min(in.p.z, cb.max_depth);
|
||||
out.depth = min(depth_value, cb.max_depth);
|
||||
else if (PS_ZFLOOR)
|
||||
out.depth = depth_value;
|
||||
|
||||
return out;
|
||||
}
|
||||
|
||||
@@ -1389,7 +1389,9 @@ std::string GSDeviceOGL::GetPSSource(const PSSelector& sel)
|
||||
+ fmt::format("#define PS_DITHER {}\n", sel.dither)
|
||||
+ fmt::format("#define PS_DITHER_ADJUST {}\n", sel.dither_adjust)
|
||||
+ fmt::format("#define PS_ZCLAMP {}\n", sel.zclamp)
|
||||
+ fmt::format("#define PS_ZFLOOR {}\n", sel.zfloor)
|
||||
+ fmt::format("#define PS_BLEND_MIX {}\n", sel.blend_mix)
|
||||
+ fmt::format("#define PS_ZCLAMP {}\n", sel.zclamp)
|
||||
+ fmt::format("#define PS_ROUND_INV {}\n", sel.round_inv)
|
||||
+ fmt::format("#define PS_FIXED_ONE_A {}\n", sel.fixed_one_a)
|
||||
+ fmt::format("#define PS_PABE {}\n", sel.pabe)
|
||||
|
||||
@@ -4777,6 +4777,7 @@ VkShaderModule GSDeviceVK::GetTFXFragmentShader(const GSHWDrawConfig::PSSelector
|
||||
AddMacro(ss, "PS_DITHER", sel.dither);
|
||||
AddMacro(ss, "PS_DITHER_ADJUST", sel.dither_adjust);
|
||||
AddMacro(ss, "PS_ZCLAMP", sel.zclamp);
|
||||
AddMacro(ss, "PS_ZFLOOR", sel.zfloor);
|
||||
AddMacro(ss, "PS_PABE", sel.pabe);
|
||||
AddMacro(ss, "PS_SCANMSK", sel.scanmsk);
|
||||
AddMacro(ss, "PS_TEX_IS_FB", sel.tex_is_fb);
|
||||
|
||||
12
pcsx2/Hw.cpp
12
pcsx2/Hw.cpp
@@ -11,15 +11,27 @@
|
||||
|
||||
#include "fmt/format.h"
|
||||
|
||||
#include <deque>
|
||||
|
||||
using namespace R5900;
|
||||
|
||||
const int rdram_devices = 2; // put 8 for TOOL and 2 for PS2 and PSX
|
||||
int rdram_sdevid = 0;
|
||||
|
||||
std::deque<u8> ee_sio_rx_fifo;
|
||||
std::deque<u8> ee_sio_tx_fifo;
|
||||
|
||||
void hwReset()
|
||||
{
|
||||
std::memset(eeHw, 0, sizeof(eeHw));
|
||||
|
||||
{
|
||||
std::deque<u8> empty_rx;
|
||||
std::swap(ee_sio_rx_fifo, empty_rx);
|
||||
std::deque<u8> empty_tx;
|
||||
std::swap(ee_sio_tx_fifo, empty_tx);
|
||||
}
|
||||
|
||||
psHu32(SBUS_F260) = 0x1D000060;
|
||||
|
||||
// i guess this is kinda a version, it's used by some bioses
|
||||
|
||||
@@ -1,6 +1,8 @@
|
||||
// SPDX-FileCopyrightText: 2002-2025 PCSX2 Dev Team
|
||||
// SPDX-License-Identifier: GPL-3.0+
|
||||
|
||||
#include <deque>
|
||||
|
||||
#pragma once
|
||||
|
||||
namespace EEMemoryMap
|
||||
@@ -355,3 +357,6 @@ extern void hwReset();
|
||||
|
||||
extern const int rdram_devices;
|
||||
extern int rdram_sdevid;
|
||||
|
||||
extern std::deque<u8> ee_sio_rx_fifo;
|
||||
extern std::deque<u8> ee_sio_tx_fifo;
|
||||
|
||||
@@ -125,7 +125,23 @@ mem32_t _hwRead32(u32 mem)
|
||||
switch( mem )
|
||||
{
|
||||
case SIO_ISR:
|
||||
|
||||
// Not (yet) hardware tested
|
||||
// The PS2SDK behaviour is as follows:
|
||||
|
||||
// TX: Don't write to TX FIFO until until bit 15 is 0
|
||||
|
||||
// RX: RX FIFO has data when bits 8-11 are not 0 (maybe a byte count?)
|
||||
// RX: When reading from the RX FIFO, set bits 0-2 to 1 (why??)
|
||||
|
||||
// For TX, we don't do any LLE buffering, so we can keep bit 15 to 0
|
||||
// For RX, just hack it so when the ee_rx_fifo.size() != 0, ISR = 0xf00
|
||||
|
||||
if(!ee_sio_rx_fifo.empty())
|
||||
return 0xf00;
|
||||
|
||||
return 0x0;
|
||||
break;
|
||||
case 0x1000f410:
|
||||
case MCH_RICM:
|
||||
return 0;
|
||||
@@ -211,6 +227,16 @@ mem32_t hwRead32_page_0F_INTC_HACK(u32 mem)
|
||||
template< uint page >
|
||||
mem8_t _hwRead8(u32 mem)
|
||||
{
|
||||
if(mem == SIO_RXFIFO)
|
||||
{
|
||||
if(ee_sio_rx_fifo.empty())
|
||||
return 0; // needs hardware test, what does it return with the FIFO is empty
|
||||
|
||||
const char c = ee_sio_rx_fifo.front();
|
||||
ee_sio_rx_fifo.pop_front();
|
||||
return c;
|
||||
}
|
||||
|
||||
u32 ret32 = _hwRead32<page, false>(mem & ~0x03);
|
||||
return ((u8*)&ret32)[mem & 0x03];
|
||||
}
|
||||
|
||||
@@ -285,26 +285,35 @@ void _hwWrite8(u32 mem, u8 value)
|
||||
#endif
|
||||
if (mem == SIO_TXFIFO)
|
||||
{
|
||||
static bool included_newline = false;
|
||||
static char sio_buffer[1024];
|
||||
static int sio_count;
|
||||
|
||||
if (value == '\r')
|
||||
static bool last_char_was_cr = false;
|
||||
|
||||
// skip the \n in \r\n
|
||||
if(last_char_was_cr && (value == '\n'))
|
||||
{
|
||||
included_newline = true;
|
||||
sio_buffer[sio_count++] = '\n';
|
||||
last_char_was_cr = false;
|
||||
return;
|
||||
}
|
||||
else if (!included_newline || (value != '\n'))
|
||||
|
||||
last_char_was_cr = value == '\r';
|
||||
bool should_flush_cause_newline = false;
|
||||
if (last_char_was_cr)
|
||||
{
|
||||
included_newline = false;
|
||||
sio_buffer[sio_count++] = value;
|
||||
should_flush_cause_newline = true;
|
||||
ee_sio_tx_fifo.push_back('\n');
|
||||
}
|
||||
else
|
||||
{
|
||||
should_flush_cause_newline = value == '\n';
|
||||
ee_sio_tx_fifo.push_back(value);
|
||||
}
|
||||
|
||||
if ((sio_count == std::size(sio_buffer)-1) || (sio_count != 0 && sio_buffer[sio_count-1] == '\n'))
|
||||
// Check if the only thing in the buffer
|
||||
if (ee_sio_tx_fifo.size() == 1024 || should_flush_cause_newline)
|
||||
{
|
||||
sio_buffer[sio_count] = 0;
|
||||
eeConLog( ShiftJIS_ConvertString(sio_buffer) );
|
||||
sio_count = 0;
|
||||
std::string output_string(ee_sio_tx_fifo.begin(), ee_sio_tx_fifo.end());
|
||||
|
||||
eeConLog(ShiftJIS_ConvertString(output_string.c_str()));
|
||||
ee_sio_tx_fifo.clear();
|
||||
}
|
||||
return;
|
||||
}
|
||||
|
||||
@@ -619,6 +619,8 @@ __ri void ImGuiManager::DrawSettingsOverlay(float scale, float margin, float spa
|
||||
APPEND("SD={}/{} ", GSConfig.SkipDrawStart, GSConfig.SkipDrawEnd);
|
||||
if (GSConfig.UserHacks_TextureInsideRt != GSTextureInRtMode::Disabled)
|
||||
APPEND("TexRT={} ", static_cast<unsigned>(GSConfig.UserHacks_TextureInsideRt));
|
||||
if (GSConfig.UserHacks_Limit24BitDepth != GSLimit24BitDepth::Disabled)
|
||||
APPEND("TDR={} ", static_cast<unsigned>(GSConfig.UserHacks_Limit24BitDepth));
|
||||
if (GSConfig.UserHacks_BilinearHack != GSBilinearDirtyMode::Automatic)
|
||||
APPEND("BLU={} ", static_cast<unsigned>(GSConfig.UserHacks_BilinearHack));
|
||||
if (GSConfig.UserHacks_ForceEvenSpritePosition)
|
||||
|
||||
@@ -67,7 +67,10 @@ void intBreakpoint(bool memcheck)
|
||||
{
|
||||
const u32 pc = cpuRegs.pc;
|
||||
if (CBreakPoints::CheckSkipFirst(BREAKPOINT_EE, pc) != 0)
|
||||
{
|
||||
CBreakPoints::ClearSkipFirst(BREAKPOINT_EE);
|
||||
return;
|
||||
}
|
||||
|
||||
if (!memcheck)
|
||||
{
|
||||
@@ -161,6 +164,8 @@ static void execI()
|
||||
intBreakpoint(false);
|
||||
|
||||
intCheckMemcheck();
|
||||
|
||||
CBreakPoints::CommitClearSkipFirst(BREAKPOINT_EE);
|
||||
#endif
|
||||
|
||||
const u32 pc = cpuRegs.pc;
|
||||
|
||||
@@ -755,6 +755,7 @@ Pcsx2Config::GSOptions::GSOptions()
|
||||
ManualUserHacks = false;
|
||||
UserHacks_AlignSpriteX = false;
|
||||
UserHacks_AutoFlush = GSHWAutoFlushLevel::Disabled;
|
||||
UserHacks_Limit24BitDepth = GSLimit24BitDepth::Disabled;
|
||||
UserHacks_CPUFBConversion = false;
|
||||
UserHacks_ReadTCOnClose = false;
|
||||
UserHacks_DisableDepthSupport = false;
|
||||
@@ -847,6 +848,7 @@ bool Pcsx2Config::GSOptions::OptionsAreEqual(const GSOptions& right) const
|
||||
OpEqu(UserHacks_CPUCLUTRender) &&
|
||||
OpEqu(UserHacks_GPUTargetCLUTMode) &&
|
||||
OpEqu(UserHacks_TextureInsideRt) &&
|
||||
OpEqu(UserHacks_Limit24BitDepth) &&
|
||||
OpEqu(UserHacks_BilinearHack) &&
|
||||
OpEqu(OverrideTextureBarriers) &&
|
||||
|
||||
@@ -983,6 +985,7 @@ void Pcsx2Config::GSOptions::LoadSave(SettingsWrapper& wrap)
|
||||
SettingsWrapIntEnumEx(UserHacks_BilinearHack, "UserHacks_BilinearHack");
|
||||
SettingsWrapBitBoolEx(UserHacks_NativePaletteDraw, "UserHacks_NativePaletteDraw");
|
||||
SettingsWrapIntEnumEx(UserHacks_TextureInsideRt, "UserHacks_TextureInsideRt");
|
||||
SettingsWrapIntEnumEx(UserHacks_Limit24BitDepth, "UserHacks_Limit24BitDepth");
|
||||
SettingsWrapBitBoolEx(UserHacks_EstimateTextureRegion, "UserHacks_EstimateTextureRegion");
|
||||
SettingsWrapBitBoolEx(FXAA, "fxaa");
|
||||
SettingsWrapBitBool(ShadeBoost);
|
||||
@@ -1111,6 +1114,7 @@ void Pcsx2Config::GSOptions::MaskUserHacks()
|
||||
UserHacks_CPUFBConversion = false;
|
||||
UserHacks_ReadTCOnClose = false;
|
||||
UserHacks_TextureInsideRt = GSTextureInRtMode::Disabled;
|
||||
UserHacks_Limit24BitDepth = GSLimit24BitDepth::Disabled;
|
||||
UserHacks_EstimateTextureRegion = false;
|
||||
UserHacks_TCOffsetX = 0;
|
||||
UserHacks_TCOffsetY = 0;
|
||||
|
||||
@@ -120,7 +120,10 @@ void psxBreakpoint(bool memcheck)
|
||||
{
|
||||
u32 pc = psxRegs.pc;
|
||||
if (CBreakPoints::CheckSkipFirst(BREAKPOINT_IOP, pc) != 0)
|
||||
{
|
||||
CBreakPoints::ClearSkipFirst(BREAKPOINT_IOP);
|
||||
return;
|
||||
}
|
||||
|
||||
if (!memcheck)
|
||||
{
|
||||
@@ -208,6 +211,8 @@ static __fi void execI()
|
||||
psxBreakpoint(false);
|
||||
|
||||
psxCheckMemcheck();
|
||||
|
||||
CBreakPoints::CommitClearSkipFirst(BREAKPOINT_IOP);
|
||||
#endif
|
||||
|
||||
// Inject IRX hack
|
||||
|
||||
@@ -3,4 +3,4 @@
|
||||
|
||||
/// Version number for GS and other shaders. Increment whenever any of the contents of the
|
||||
/// shaders change, to invalidate the cache.
|
||||
static constexpr u32 SHADER_CACHE_VERSION = 77;
|
||||
static constexpr u32 SHADER_CACHE_VERSION = 78;
|
||||
|
||||
@@ -526,6 +526,7 @@ void VMManager::SetDefaultLoggingSettings(SettingsInterface& si)
|
||||
si.SetBoolValue("Logging", "EnableSystemConsole", false);
|
||||
si.SetBoolValue("Logging", "EnableFileLogging", true);
|
||||
si.SetBoolValue("Logging", "EnableTimestamps", true);
|
||||
si.SetBoolValue("Logging", "EnableEESIOInput", false);
|
||||
si.SetBoolValue("Logging", "EnableVerbose", false);
|
||||
si.SetBoolValue("Logging", "EnableEEConsole", false);
|
||||
si.SetBoolValue("Logging", "EnableIOPConsole", false);
|
||||
@@ -3725,15 +3726,16 @@ void VMManager::UpdateDiscordPresence(bool update_session_time)
|
||||
|
||||
auto lock = Achievements::GetLock();
|
||||
|
||||
if (Achievements::HasRichPresence())
|
||||
if (Achievements::HasActiveGame() && Achievements::HasAchievementsOrLeaderboards())
|
||||
{
|
||||
rp.state = (state_string = StringUtil::Ellipsise(Achievements::GetRichPresenceString(), 128)).c_str();
|
||||
|
||||
if (const std::string& icon_url = Achievements::GetGameIconURL(); !icon_url.empty())
|
||||
{
|
||||
rp.largeImageKey = icon_url.c_str();
|
||||
rp.largeImageText = s_title.c_str();
|
||||
}
|
||||
|
||||
if (Achievements::HasRichPresence())
|
||||
rp.state = (state_string = StringUtil::Ellipsise(Achievements::GetRichPresenceString(), 128)).c_str();
|
||||
}
|
||||
|
||||
Discord_UpdatePresence(&rp);
|
||||
@@ -3747,3 +3749,15 @@ void VMManager::PollDiscordPresence()
|
||||
|
||||
Discord_RunCallbacks();
|
||||
}
|
||||
|
||||
bool VMManager::WriteBytesToEESIORXFIFO(const std::span<const u8> data)
|
||||
{
|
||||
if(ee_sio_rx_fifo.size() + data.size() > 1024)
|
||||
{
|
||||
Console.Warning("EE RX FIFO is full, not appending more bytes.");
|
||||
return false;
|
||||
}
|
||||
|
||||
ee_sio_rx_fifo.insert(ee_sio_rx_fifo.end(), data.begin(), data.end());
|
||||
return true;
|
||||
}
|
||||
|
||||
@@ -6,6 +6,7 @@
|
||||
#include <functional>
|
||||
#include <mutex>
|
||||
#include <optional>
|
||||
#include <span>
|
||||
#include <string>
|
||||
#include <string_view>
|
||||
#include <vector>
|
||||
@@ -264,6 +265,9 @@ namespace VMManager
|
||||
/// Called when the rich presence string, provided by RetroAchievements, changes.
|
||||
void UpdateDiscordPresence(bool update_session_time);
|
||||
|
||||
/// Append bytes to the EE SIO RX FIFO. If it returns false, the FIFO is full and data is not inserted.
|
||||
bool WriteBytesToEESIORXFIFO(const std::span<const u8> data);
|
||||
|
||||
/// Internal callbacks, implemented in the emu core.
|
||||
namespace Internal
|
||||
{
|
||||
|
||||
@@ -1259,7 +1259,10 @@ static bool psxDynarecCheckBreakpoint()
|
||||
{
|
||||
u32 pc = psxRegs.pc;
|
||||
if (CBreakPoints::CheckSkipFirst(BREAKPOINT_IOP, pc) == pc)
|
||||
{
|
||||
CBreakPoints::ClearSkipFirst(BREAKPOINT_IOP);
|
||||
return false;
|
||||
}
|
||||
|
||||
int bpFlags = psxIsBreakpointNeeded(pc);
|
||||
bool hit = false;
|
||||
@@ -1299,8 +1302,10 @@ static bool psxDynarecMemcheck(size_t i)
|
||||
auto mc = CBreakPoints::GetMemChecks(BREAKPOINT_IOP)[i];
|
||||
|
||||
if (CBreakPoints::CheckSkipFirst(BREAKPOINT_IOP, pc) == pc)
|
||||
{
|
||||
CBreakPoints::ClearSkipFirst(BREAKPOINT_IOP);
|
||||
return false;
|
||||
|
||||
}
|
||||
if (mc.hasCond)
|
||||
{
|
||||
if (!mc.cond.Evaluate())
|
||||
@@ -1373,7 +1378,7 @@ static void psxRecMemcheck(u32 op, u32 bits, bool store)
|
||||
}
|
||||
}
|
||||
|
||||
static void psxEncodeBreakpoint()
|
||||
static bool psxEncodeBreakpoint()
|
||||
{
|
||||
if (psxIsBreakpointNeeded(psxpc) != 0)
|
||||
{
|
||||
@@ -1381,14 +1386,17 @@ static void psxEncodeBreakpoint()
|
||||
xFastCall((void*)psxDynarecCheckBreakpoint);
|
||||
xTEST(al, al);
|
||||
xJNZ(iopExitRecompiledCode);
|
||||
return true;
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
static void psxEncodeMemcheck()
|
||||
static bool psxEncodeMemcheck()
|
||||
{
|
||||
int needed = psxIsMemcheckNeeded(psxpc);
|
||||
if (needed == 0)
|
||||
return;
|
||||
return false;
|
||||
|
||||
u32 op = iopMemRead32(needed == 2 ? psxpc + 4 : psxpc);
|
||||
const R5900::OPCODE& opcode = R5900::GetInstruction(op);
|
||||
@@ -1409,6 +1417,7 @@ static void psxEncodeMemcheck()
|
||||
psxRecMemcheck(op, 64, store);
|
||||
break;
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
void psxRecompileNextInstruction(bool delayslot, bool swapped_delayslot)
|
||||
@@ -1437,12 +1446,10 @@ void psxRecompileNextInstruction(bool delayslot, bool swapped_delayslot)
|
||||
EEINST* old_inst_info = g_pCurInstInfo;
|
||||
s_recompilingDelaySlot = delayslot;
|
||||
|
||||
// add breakpoint
|
||||
if (!delayslot)
|
||||
{
|
||||
// Broken on x64
|
||||
psxEncodeBreakpoint();
|
||||
psxEncodeMemcheck();
|
||||
if(psxEncodeBreakpoint() || psxEncodeMemcheck())
|
||||
xFastCall((void*)CBreakPoints::CommitClearSkipFirst, BREAKPOINT_IOP);
|
||||
}
|
||||
else
|
||||
{
|
||||
|
||||
@@ -1498,7 +1498,10 @@ void dynarecCheckBreakpoint()
|
||||
{
|
||||
u32 pc = cpuRegs.pc;
|
||||
if (CBreakPoints::CheckSkipFirst(BREAKPOINT_EE, pc) != 0)
|
||||
{
|
||||
CBreakPoints::ClearSkipFirst(BREAKPOINT_EE);
|
||||
return;
|
||||
}
|
||||
|
||||
const int bpFlags = isBreakpointNeeded(pc);
|
||||
bool hit = false;
|
||||
@@ -1532,7 +1535,10 @@ void dynarecMemcheck(size_t i)
|
||||
const u32 op = memRead32(cpuRegs.pc);
|
||||
const OPCODE& opcode = GetInstruction(op);
|
||||
if (CBreakPoints::CheckSkipFirst(BREAKPOINT_EE, pc) != 0)
|
||||
{
|
||||
CBreakPoints::ClearSkipFirst(BREAKPOINT_EE);
|
||||
return;
|
||||
}
|
||||
|
||||
auto mc = CBreakPoints::GetMemChecks(BREAKPOINT_EE)[i];
|
||||
|
||||
@@ -1606,20 +1612,22 @@ void recMemcheck(u32 op, u32 bits, bool store)
|
||||
}
|
||||
}
|
||||
|
||||
void encodeBreakpoint()
|
||||
bool encodeBreakpoint()
|
||||
{
|
||||
if (isBreakpointNeeded(pc) != 0)
|
||||
{
|
||||
iFlushCall(FLUSH_EVERYTHING | FLUSH_PC);
|
||||
xFastCall((void*)dynarecCheckBreakpoint);
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
void encodeMemcheck()
|
||||
bool encodeMemcheck()
|
||||
{
|
||||
const int needed = isMemcheckNeeded(pc);
|
||||
if (needed == 0)
|
||||
return;
|
||||
return false;
|
||||
|
||||
const u32 op = memRead32(needed == 2 ? pc + 4 : pc);
|
||||
const OPCODE& opcode = GetInstruction(op);
|
||||
@@ -1643,6 +1651,7 @@ void encodeMemcheck()
|
||||
recMemcheck(op, 128, store);
|
||||
break;
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
void recompileNextInstruction(bool delayslot, bool swapped_delay_slot)
|
||||
@@ -1653,8 +1662,8 @@ void recompileNextInstruction(bool delayslot, bool swapped_delay_slot)
|
||||
// add breakpoint
|
||||
if (!delayslot)
|
||||
{
|
||||
encodeBreakpoint();
|
||||
encodeMemcheck();
|
||||
if(encodeBreakpoint() || encodeMemcheck())
|
||||
xFastCall((void*)CBreakPoints::CommitClearSkipFirst, BREAKPOINT_EE);
|
||||
}
|
||||
else
|
||||
{
|
||||
|
||||
@@ -233,7 +233,13 @@ public:
|
||||
const u64 quick64 = pState->quick64[0];
|
||||
for (const microBlockLinkRef& ref : quickLookup)
|
||||
{
|
||||
if (ref.quick != quick64) continue;
|
||||
// if we're using the flag hack, ignore the mac flags going in to the new block too if an exact match wasn't requested.
|
||||
if (mVUsFlagHack)
|
||||
{
|
||||
if ((ref.quick & ~0x0C04) != (quick64 & ~0x0C04)) continue;
|
||||
}
|
||||
else if (ref.quick != quick64) continue;
|
||||
|
||||
if (doConstProp && (ref.pBlock->pState.vi15 != pState->vi15)) continue;
|
||||
if (doConstProp && (ref.pBlock->pState.vi15v != pState->vi15v)) continue;
|
||||
return ref.pBlock;
|
||||
|
||||
Reference in New Issue
Block a user