mirror of
https://github.com/PCSX2/pcsx2.git
synced 2026-01-31 01:15:24 +01:00
Compare commits
9 Commits
v2.5.145
...
misc_auto_
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
3b0a83c1ab | ||
|
|
9864cd97de | ||
|
|
6d7deb57a0 | ||
|
|
21876ff590 | ||
|
|
c543c05968 | ||
|
|
a5537da4df | ||
|
|
edaddeecc4 | ||
|
|
6b30a199da | ||
|
|
23c637e3e5 |
@@ -76,6 +76,7 @@
|
||||
03000000c82d00000260000000000000,8BitDo SN30 Pro Plus,a:b1,b:b0,back:b10,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b2,leftshoulder:b6,leftstick:b13,lefttrigger:b8,leftx:a0,lefty:a1,rightshoulder:b7,rightstick:b14,righttrigger:b9,rightx:a2,righty:a3,start:b11,x:b4,y:b3,platform:Windows,
|
||||
03000000c82d00000261000000000000,8BitDo SN30 Pro Plus,a:b1,b:b0,back:b10,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b2,leftshoulder:b6,leftstick:b13,lefttrigger:b8,leftx:a0,lefty:a1,rightshoulder:b7,rightstick:b14,righttrigger:b9,rightx:a2,righty:a3,start:b11,x:b4,y:b3,platform:Windows,
|
||||
03000000c82d00001230000000000000,8BitDo Ultimate,a:b0,b:b1,back:b10,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b12,leftshoulder:b6,leftstick:b13,lefttrigger:b8,leftx:a0,lefty:a1,paddle1:b2,paddle2:b5,rightshoulder:b7,rightstick:b14,righttrigger:b9,rightx:a3,righty:a4,start:b11,x:b3,y:b4,platform:Windows,
|
||||
03000000c82d00001260000000000000,8BitDo Ultimate 2,a:b0,b:b1,back:b10,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b12,leftshoulder:b6,leftstick:b13,lefttrigger:b8,leftx:a0,lefty:a1,paddle1:b17,paddle2:b16,paddle3:b2,paddle4:b5,rightshoulder:b7,rightstick:b14,righttrigger:b9,rightx:a3,righty:a4,start:b11,x:b3,y:b4,platform:Windows,
|
||||
03000000c82d00001b30000000000000,8BitDo Ultimate 2C,a:b0,b:b1,back:b10,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b12,leftshoulder:b6,leftstick:b13,lefttrigger:b8,leftx:a0,lefty:a1,paddle1:b5,paddle2:b2,rightshoulder:b7,rightstick:b14,righttrigger:b9,rightx:a3,righty:a4,start:b11,x:b3,y:b4,platform:Windows,
|
||||
03000000c82d00001d30000000000000,8BitDo Ultimate 2C,a:b0,b:b1,back:b10,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b12,leftshoulder:b6,leftstick:b13,lefttrigger:b8,leftx:a0,lefty:a1,paddle1:b5,paddle2:b2,rightshoulder:b7,rightstick:b14,righttrigger:b9,rightx:a3,righty:a4,start:b11,x:b3,y:b4,platform:Windows,
|
||||
03000000c82d00001530000000000000,8BitDo Ultimate C,a:b0,b:b1,back:b10,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b12,leftshoulder:b6,leftstick:b13,lefttrigger:b8,leftx:a0,lefty:a1,rightshoulder:b7,rightstick:b14,righttrigger:b9,rightx:a3,righty:a4,start:b11,x:b3,y:b4,platform:Windows,
|
||||
|
||||
@@ -3,13 +3,14 @@
|
||||
|
||||
#include "SymbolTreeDelegates.h"
|
||||
|
||||
#include "Debugger/SymbolTree/SymbolTreeModel.h"
|
||||
#include "Debugger/SymbolTree/TypeString.h"
|
||||
|
||||
#include <QtWidgets/QCheckBox>
|
||||
#include <QtWidgets/QComboBox>
|
||||
#include <QtWidgets/QDoubleSpinBox>
|
||||
#include <QtWidgets/QLineEdit>
|
||||
#include <QtWidgets/QMessageBox>
|
||||
#include "Debugger/SymbolTree/SymbolTreeModel.h"
|
||||
#include "Debugger/SymbolTree/TypeString.h"
|
||||
|
||||
SymbolTreeValueDelegate::SymbolTreeValueDelegate(
|
||||
DebugInterface& cpu,
|
||||
@@ -28,6 +29,8 @@ QWidget* SymbolTreeValueDelegate::createEditor(QWidget* parent, const QStyleOpti
|
||||
if (!tree_model)
|
||||
return nullptr;
|
||||
|
||||
const SymbolTreeDisplayOptions& display_options = tree_model->displayOptions();
|
||||
|
||||
SymbolTreeNode* node = tree_model->nodeFromIndex(index);
|
||||
if (!node || !node->type.valid())
|
||||
return nullptr;
|
||||
@@ -46,9 +49,9 @@ QWidget* SymbolTreeValueDelegate::createEditor(QWidget* parent, const QStyleOpti
|
||||
{
|
||||
case ccc::ast::BUILTIN:
|
||||
{
|
||||
const ccc::ast::BuiltIn& builtIn = type.as<ccc::ast::BuiltIn>();
|
||||
const ccc::ast::BuiltIn& builtin = type.as<ccc::ast::BuiltIn>();
|
||||
|
||||
switch (builtIn.bclass)
|
||||
switch (builtin.bclass)
|
||||
{
|
||||
case ccc::ast::BuiltInClass::UNSIGNED_8:
|
||||
case ccc::ast::BuiltInClass::UNQUALIFIED_8:
|
||||
@@ -56,8 +59,9 @@ QWidget* SymbolTreeValueDelegate::createEditor(QWidget* parent, const QStyleOpti
|
||||
case ccc::ast::BuiltInClass::UNSIGNED_32:
|
||||
case ccc::ast::BuiltInClass::UNSIGNED_64:
|
||||
{
|
||||
QLineEdit* editor = new QLineEdit(parent);
|
||||
editor->setText(QString::number(value.toULongLong()));
|
||||
SymbolTreeIntegerLineEdit* editor = new SymbolTreeIntegerLineEdit(
|
||||
display_options, ccc::ast::builtin_class_size(builtin.bclass) * 8, parent);
|
||||
editor->setUnsignedValue(value.toULongLong());
|
||||
result = editor;
|
||||
|
||||
break;
|
||||
@@ -67,8 +71,9 @@ QWidget* SymbolTreeValueDelegate::createEditor(QWidget* parent, const QStyleOpti
|
||||
case ccc::ast::BuiltInClass::SIGNED_32:
|
||||
case ccc::ast::BuiltInClass::SIGNED_64:
|
||||
{
|
||||
QLineEdit* editor = new QLineEdit(parent);
|
||||
editor->setText(QString::number(value.toLongLong()));
|
||||
SymbolTreeIntegerLineEdit* editor = new SymbolTreeIntegerLineEdit(
|
||||
display_options, ccc::ast::builtin_class_size(builtin.bclass) * 8, parent);
|
||||
editor->setSignedValue(value.toLongLong());
|
||||
result = editor;
|
||||
|
||||
break;
|
||||
@@ -168,9 +173,9 @@ void SymbolTreeValueDelegate::setModelData(QWidget* editor, QAbstractItemModel*
|
||||
{
|
||||
case ccc::ast::BUILTIN:
|
||||
{
|
||||
const ccc::ast::BuiltIn& builtIn = type.as<ccc::ast::BuiltIn>();
|
||||
const ccc::ast::BuiltIn& builtin = type.as<ccc::ast::BuiltIn>();
|
||||
|
||||
switch (builtIn.bclass)
|
||||
switch (builtin.bclass)
|
||||
{
|
||||
case ccc::ast::BuiltInClass::UNSIGNED_8:
|
||||
case ccc::ast::BuiltInClass::UNQUALIFIED_8:
|
||||
@@ -178,13 +183,12 @@ void SymbolTreeValueDelegate::setModelData(QWidget* editor, QAbstractItemModel*
|
||||
case ccc::ast::BuiltInClass::UNSIGNED_32:
|
||||
case ccc::ast::BuiltInClass::UNSIGNED_64:
|
||||
{
|
||||
QLineEdit* line_edit = qobject_cast<QLineEdit*>(editor);
|
||||
auto line_edit = qobject_cast<SymbolTreeIntegerLineEdit*>(editor);
|
||||
Q_ASSERT(line_edit);
|
||||
|
||||
bool ok;
|
||||
qulonglong i = line_edit->text().toULongLong(&ok);
|
||||
if (ok)
|
||||
value = i;
|
||||
std::optional<u64> i = line_edit->unsignedValue();
|
||||
if (i.has_value())
|
||||
value = static_cast<quint64>(*i);
|
||||
|
||||
break;
|
||||
}
|
||||
@@ -193,13 +197,12 @@ void SymbolTreeValueDelegate::setModelData(QWidget* editor, QAbstractItemModel*
|
||||
case ccc::ast::BuiltInClass::SIGNED_32:
|
||||
case ccc::ast::BuiltInClass::SIGNED_64:
|
||||
{
|
||||
QLineEdit* line_edit = qobject_cast<QLineEdit*>(editor);
|
||||
auto line_edit = qobject_cast<SymbolTreeIntegerLineEdit*>(editor);
|
||||
Q_ASSERT(line_edit);
|
||||
|
||||
bool ok;
|
||||
qlonglong i = line_edit->text().toLongLong(&ok);
|
||||
if (ok)
|
||||
value = i;
|
||||
std::optional<s64> i = line_edit->signedValue();
|
||||
if (i.has_value())
|
||||
value = static_cast<qint64>(*i);
|
||||
|
||||
break;
|
||||
}
|
||||
@@ -481,3 +484,33 @@ void SymbolTreeTypeDelegate::setModelData(QWidget* editor, QAbstractItemModel* m
|
||||
else
|
||||
QMessageBox::warning(editor, tr("Cannot Change Type"), error_message);
|
||||
}
|
||||
|
||||
// *****************************************************************************
|
||||
|
||||
SymbolTreeIntegerLineEdit::SymbolTreeIntegerLineEdit(
|
||||
SymbolTreeDisplayOptions display_options, s32 size_bits, QWidget* parent)
|
||||
: QLineEdit(parent)
|
||||
, m_display_options(display_options)
|
||||
, m_size_bits(size_bits)
|
||||
{
|
||||
}
|
||||
|
||||
std::optional<u64> SymbolTreeIntegerLineEdit::unsignedValue()
|
||||
{
|
||||
return m_display_options.stringToUnsignedInteger(text());
|
||||
}
|
||||
|
||||
void SymbolTreeIntegerLineEdit::setUnsignedValue(u64 value)
|
||||
{
|
||||
setText(m_display_options.unsignedIntegerToString(value, m_size_bits));
|
||||
}
|
||||
|
||||
std::optional<s64> SymbolTreeIntegerLineEdit::signedValue()
|
||||
{
|
||||
return m_display_options.stringToSignedInteger(text());
|
||||
}
|
||||
|
||||
void SymbolTreeIntegerLineEdit::setSignedValue(s64 value)
|
||||
{
|
||||
setText(m_display_options.signedIntegerToString(value, m_size_bits));
|
||||
}
|
||||
|
||||
@@ -3,10 +3,12 @@
|
||||
|
||||
#pragma once
|
||||
|
||||
#include <QtWidgets/QStyledItemDelegate>
|
||||
#include "Debugger/SymbolTree/SymbolTreeNode.h"
|
||||
|
||||
#include "DebugTools/DebugInterface.h"
|
||||
#include "DebugTools/SymbolGuardian.h"
|
||||
|
||||
#include <QtWidgets/QStyledItemDelegate>
|
||||
#include <QtWidgets/QLineEdit>
|
||||
|
||||
class SymbolTreeValueDelegate : public QStyledItemDelegate
|
||||
{
|
||||
@@ -21,7 +23,7 @@ public:
|
||||
void setEditorData(QWidget* editor, const QModelIndex& index) const override;
|
||||
void setModelData(QWidget* editor, QAbstractItemModel* model, const QModelIndex& index) const override;
|
||||
|
||||
protected:
|
||||
private:
|
||||
// These make it so the values inputted are written back to memory
|
||||
// immediately when the widgets are interacted with rather than when they
|
||||
// are deselected.
|
||||
@@ -45,7 +47,7 @@ public:
|
||||
void setEditorData(QWidget* editor, const QModelIndex& index) const override;
|
||||
void setModelData(QWidget* editor, QAbstractItemModel* model, const QModelIndex& index) const override;
|
||||
|
||||
protected:
|
||||
private:
|
||||
DebugInterface& m_cpu;
|
||||
u32 m_alignment;
|
||||
};
|
||||
@@ -63,6 +65,24 @@ public:
|
||||
void setEditorData(QWidget* editor, const QModelIndex& index) const override;
|
||||
void setModelData(QWidget* editor, QAbstractItemModel* model, const QModelIndex& index) const override;
|
||||
|
||||
protected:
|
||||
private:
|
||||
DebugInterface& m_cpu;
|
||||
};
|
||||
|
||||
class SymbolTreeIntegerLineEdit : public QLineEdit
|
||||
{
|
||||
Q_OBJECT
|
||||
|
||||
public:
|
||||
SymbolTreeIntegerLineEdit(SymbolTreeDisplayOptions display_options, s32 size_bits, QWidget* parent);
|
||||
|
||||
std::optional<u64> unsignedValue();
|
||||
void setUnsignedValue(u64 value);
|
||||
|
||||
std::optional<s64> signedValue();
|
||||
void setSignedValue(s64 value);
|
||||
|
||||
private:
|
||||
SymbolTreeDisplayOptions m_display_options;
|
||||
s32 m_size_bits;
|
||||
};
|
||||
|
||||
@@ -183,10 +183,10 @@ bool SymbolTreeModel::setData(const QModelIndex& index, const QVariant& value, i
|
||||
switch (role)
|
||||
{
|
||||
case EDIT_ROLE:
|
||||
data_changed = node->writeToVM(value, m_cpu, database);
|
||||
data_changed = node->writeToVM(value, m_cpu, database, m_display_options);
|
||||
break;
|
||||
case UPDATE_FROM_MEMORY_ROLE:
|
||||
data_changed = node->readFromVM(m_cpu, database);
|
||||
data_changed = node->readFromVM(m_cpu, database, m_display_options);
|
||||
break;
|
||||
}
|
||||
});
|
||||
@@ -216,7 +216,13 @@ void SymbolTreeModel::fetchMore(const QModelIndex& parent)
|
||||
return;
|
||||
|
||||
children = populateChildren(
|
||||
parent_node->name, parent_node->location, *logical_parent_type, parent_node->type, m_cpu, database);
|
||||
parent_node->name,
|
||||
parent_node->location,
|
||||
*logical_parent_type,
|
||||
parent_node->type,
|
||||
m_cpu,
|
||||
database,
|
||||
m_display_options);
|
||||
});
|
||||
|
||||
bool insert_children = !children.empty();
|
||||
@@ -403,7 +409,8 @@ std::vector<std::unique_ptr<SymbolTreeNode>> SymbolTreeModel::populateChildren(
|
||||
const ccc::ast::Node& logical_type,
|
||||
ccc::NodeHandle parent_handle,
|
||||
DebugInterface& cpu,
|
||||
const ccc::SymbolDatabase& database)
|
||||
const ccc::SymbolDatabase& database,
|
||||
const SymbolTreeDisplayOptions& display_options)
|
||||
{
|
||||
auto [physical_type, symbol] = logical_type.physical_type(database);
|
||||
|
||||
@@ -485,7 +492,7 @@ std::vector<std::unique_ptr<SymbolTreeNode>> SymbolTreeModel::populateChildren(
|
||||
}
|
||||
|
||||
for (std::unique_ptr<SymbolTreeNode>& child : children)
|
||||
child->readFromVM(cpu, database);
|
||||
child->readFromVM(cpu, database, display_options);
|
||||
|
||||
return children;
|
||||
}
|
||||
|
||||
@@ -65,6 +65,9 @@ public:
|
||||
std::optional<QString> changeTypeTemporarily(QModelIndex index, std::string_view type_string);
|
||||
std::optional<QString> typeFromModelIndexToString(QModelIndex index);
|
||||
|
||||
const SymbolTreeDisplayOptions& displayOptions() const { return m_display_options; }
|
||||
void setDisplayOptions(const SymbolTreeDisplayOptions& options) { m_display_options = options; }
|
||||
|
||||
protected:
|
||||
static std::vector<std::unique_ptr<SymbolTreeNode>> populateChildren(
|
||||
const QString& name,
|
||||
@@ -72,11 +75,13 @@ protected:
|
||||
const ccc::ast::Node& logical_type,
|
||||
ccc::NodeHandle parent_handle,
|
||||
DebugInterface& cpu,
|
||||
const ccc::SymbolDatabase& database);
|
||||
const ccc::SymbolDatabase& database,
|
||||
const SymbolTreeDisplayOptions& display_options);
|
||||
|
||||
static bool nodeHasChildren(const ccc::ast::Node& logical_type, const ccc::SymbolDatabase& database);
|
||||
|
||||
std::unique_ptr<SymbolTreeNode> m_root;
|
||||
QString m_filter;
|
||||
DebugInterface& m_cpu;
|
||||
SymbolTreeDisplayOptions m_display_options;
|
||||
};
|
||||
|
||||
@@ -20,7 +20,10 @@ std::optional<bool> SymbolTreeNode::liveness()
|
||||
return m_liveness;
|
||||
}
|
||||
|
||||
bool SymbolTreeNode::readFromVM(DebugInterface& cpu, const ccc::SymbolDatabase& database)
|
||||
bool SymbolTreeNode::readFromVM(
|
||||
DebugInterface& cpu,
|
||||
const ccc::SymbolDatabase& database,
|
||||
const SymbolTreeDisplayOptions& display_options)
|
||||
{
|
||||
QVariant new_value;
|
||||
|
||||
@@ -39,14 +42,18 @@ bool SymbolTreeNode::readFromVM(DebugInterface& cpu, const ccc::SymbolDatabase&
|
||||
data_changed = true;
|
||||
}
|
||||
|
||||
data_changed |= updateDisplayString(cpu, database);
|
||||
data_changed |= updateDisplayString(cpu, database, display_options);
|
||||
data_changed |= updateLiveness(cpu);
|
||||
data_changed |= updateMatchesMemory(cpu, database);
|
||||
|
||||
return data_changed;
|
||||
}
|
||||
|
||||
bool SymbolTreeNode::writeToVM(QVariant value, DebugInterface& cpu, const ccc::SymbolDatabase& database)
|
||||
bool SymbolTreeNode::writeToVM(
|
||||
QVariant value,
|
||||
DebugInterface& cpu,
|
||||
const ccc::SymbolDatabase& database,
|
||||
const SymbolTreeDisplayOptions& display_options)
|
||||
{
|
||||
bool data_changed = false;
|
||||
|
||||
@@ -63,7 +70,7 @@ bool SymbolTreeNode::writeToVM(QVariant value, DebugInterface& cpu, const ccc::S
|
||||
writeValueFromVariant(m_value, physical_type, cpu);
|
||||
}
|
||||
|
||||
data_changed |= updateDisplayString(cpu, database);
|
||||
data_changed |= updateDisplayString(cpu, database, display_options);
|
||||
data_changed |= updateLiveness(cpu);
|
||||
|
||||
return data_changed;
|
||||
@@ -202,7 +209,8 @@ bool SymbolTreeNode::writeValueFromVariant(QVariant value, const ccc::ast::Node&
|
||||
return true;
|
||||
}
|
||||
|
||||
bool SymbolTreeNode::updateDisplayString(DebugInterface& cpu, const ccc::SymbolDatabase& database)
|
||||
bool SymbolTreeNode::updateDisplayString(
|
||||
DebugInterface& cpu, const ccc::SymbolDatabase& database, const SymbolTreeDisplayOptions& display)
|
||||
{
|
||||
QString result;
|
||||
|
||||
@@ -210,7 +218,7 @@ bool SymbolTreeNode::updateDisplayString(DebugInterface& cpu, const ccc::SymbolD
|
||||
if (logical_type)
|
||||
{
|
||||
const ccc::ast::Node& physical_type = *logical_type->physical_type(database).first;
|
||||
result = generateDisplayString(physical_type, cpu, database, 0);
|
||||
result = generateDisplayString(physical_type, cpu, database, display, 0);
|
||||
}
|
||||
|
||||
if (result.isEmpty())
|
||||
@@ -219,10 +227,10 @@ bool SymbolTreeNode::updateDisplayString(DebugInterface& cpu, const ccc::SymbolD
|
||||
// first 4 bytes of it as a hex dump.
|
||||
u32 value = location.read32(cpu);
|
||||
result = QString("%1 %2 %3 %4")
|
||||
.arg(value & 0xff, 2, 16, QChar('0'))
|
||||
.arg((value >> 8) & 0xff, 2, 16, QChar('0'))
|
||||
.arg((value >> 16) & 0xff, 2, 16, QChar('0'))
|
||||
.arg((value >> 24) & 0xff, 2, 16, QChar('0'));
|
||||
.arg(value & 0xff, 2, 16, QChar('0'))
|
||||
.arg((value >> 8) & 0xff, 2, 16, QChar('0'))
|
||||
.arg((value >> 16) & 0xff, 2, 16, QChar('0'))
|
||||
.arg((value >> 24) & 0xff, 2, 16, QChar('0'));
|
||||
}
|
||||
|
||||
if (result == m_display_value)
|
||||
@@ -234,7 +242,11 @@ bool SymbolTreeNode::updateDisplayString(DebugInterface& cpu, const ccc::SymbolD
|
||||
}
|
||||
|
||||
QString SymbolTreeNode::generateDisplayString(
|
||||
const ccc::ast::Node& physical_type, DebugInterface& cpu, const ccc::SymbolDatabase& database, s32 depth) const
|
||||
const ccc::ast::Node& physical_type,
|
||||
DebugInterface& cpu,
|
||||
const ccc::SymbolDatabase& database,
|
||||
const SymbolTreeDisplayOptions& display_options,
|
||||
s32 depth) const
|
||||
{
|
||||
s32 max_elements_to_display = 0;
|
||||
switch (depth)
|
||||
@@ -270,7 +282,7 @@ QString SymbolTreeNode::generateDisplayString(
|
||||
SymbolTreeNode node;
|
||||
node.location = location.addOffset(i * array.element_type->size_bytes);
|
||||
|
||||
QString element = node.generateDisplayString(element_type, cpu, database, depth + 1);
|
||||
QString element = node.generateDisplayString(element_type, cpu, database, display_options, depth + 1);
|
||||
if (element.isEmpty())
|
||||
element = QString("(%1)").arg(ccc::ast::node_type_to_string(element_type));
|
||||
result += element;
|
||||
@@ -293,28 +305,28 @@ QString SymbolTreeNode::generateDisplayString(
|
||||
switch (builtIn.bclass)
|
||||
{
|
||||
case ccc::ast::BuiltInClass::UNSIGNED_8:
|
||||
result = QString::number(location.read8(cpu));
|
||||
result = display_options.unsignedIntegerToString(location.read8(cpu), 8);
|
||||
break;
|
||||
case ccc::ast::BuiltInClass::SIGNED_8:
|
||||
result = QString::number((s8)location.read8(cpu));
|
||||
result = display_options.signedIntegerToString(static_cast<s8>(location.read8(cpu)), 8);
|
||||
break;
|
||||
case ccc::ast::BuiltInClass::UNQUALIFIED_8:
|
||||
result = QString::number(location.read8(cpu));
|
||||
result = display_options.unsignedIntegerToString(location.read8(cpu), 8);
|
||||
break;
|
||||
case ccc::ast::BuiltInClass::BOOL_8:
|
||||
result = location.read8(cpu) ? "true" : "false";
|
||||
break;
|
||||
case ccc::ast::BuiltInClass::UNSIGNED_16:
|
||||
result = QString::number(location.read16(cpu));
|
||||
result = display_options.unsignedIntegerToString(location.read16(cpu), 16);
|
||||
break;
|
||||
case ccc::ast::BuiltInClass::SIGNED_16:
|
||||
result = QString::number((s16)location.read16(cpu));
|
||||
result = display_options.signedIntegerToString(static_cast<s16>(location.read16(cpu)), 16);
|
||||
break;
|
||||
case ccc::ast::BuiltInClass::UNSIGNED_32:
|
||||
result = QString::number(location.read32(cpu));
|
||||
result = display_options.unsignedIntegerToString(location.read32(cpu), 32);
|
||||
break;
|
||||
case ccc::ast::BuiltInClass::SIGNED_32:
|
||||
result = QString::number((s32)location.read32(cpu));
|
||||
result = display_options.signedIntegerToString(static_cast<s32>(location.read32(cpu)), 32);
|
||||
break;
|
||||
case ccc::ast::BuiltInClass::FLOAT_32:
|
||||
{
|
||||
@@ -323,10 +335,10 @@ QString SymbolTreeNode::generateDisplayString(
|
||||
break;
|
||||
}
|
||||
case ccc::ast::BuiltInClass::UNSIGNED_64:
|
||||
result = QString::number(location.read64(cpu));
|
||||
result = display_options.unsignedIntegerToString(location.read64(cpu), 64);
|
||||
break;
|
||||
case ccc::ast::BuiltInClass::SIGNED_64:
|
||||
result = QString::number((s64)location.read64(cpu));
|
||||
result = display_options.signedIntegerToString(static_cast<s64>(location.read64(cpu)), 64);
|
||||
break;
|
||||
case ccc::ast::BuiltInClass::FLOAT_64:
|
||||
{
|
||||
@@ -408,7 +420,7 @@ QString SymbolTreeNode::generateDisplayString(
|
||||
}
|
||||
else if (depth == 0)
|
||||
{
|
||||
QString pointee = generateDisplayString(value_type, cpu, database, depth + 1);
|
||||
QString pointee = generateDisplayString(value_type, cpu, database, display_options, depth + 1);
|
||||
if (!pointee.isEmpty())
|
||||
result += QString(" -> %1").arg(pointee);
|
||||
}
|
||||
@@ -437,7 +449,7 @@ QString SymbolTreeNode::generateDisplayString(
|
||||
node.location = location.addOffset(field.base_offset + field.node->offset_bytes);
|
||||
|
||||
const ccc::ast::Node& field_type = *field.node->physical_type(database).first;
|
||||
QString field_value = node.generateDisplayString(field_type, cpu, database, depth + 1);
|
||||
QString field_value = node.generateDisplayString(field_type, cpu, database, display_options, depth + 1);
|
||||
if (field_value.isEmpty())
|
||||
field_value = QString("(%1)").arg(ccc::ast::node_type_to_string(field_type));
|
||||
|
||||
@@ -709,3 +721,99 @@ void SymbolTreeNode::sortChildrenRecursively(bool sort_by_if_type_is_known)
|
||||
for (std::unique_ptr<SymbolTreeNode>& child : m_children)
|
||||
child->sortChildrenRecursively(sort_by_if_type_is_known);
|
||||
}
|
||||
|
||||
// *****************************************************************************
|
||||
|
||||
int SymbolTreeDisplayOptions::integerBase() const
|
||||
{
|
||||
return m_integer_base;
|
||||
}
|
||||
|
||||
bool SymbolTreeDisplayOptions::setIntegerBase(int base)
|
||||
{
|
||||
if (base == m_integer_base || (base != 2 && base != 8 && base != 10 && base != 16))
|
||||
return false;
|
||||
|
||||
m_integer_base = base;
|
||||
return true;
|
||||
}
|
||||
|
||||
bool SymbolTreeDisplayOptions::showLeadingZeroes() const
|
||||
{
|
||||
return m_show_leading_zeroes;
|
||||
}
|
||||
|
||||
bool SymbolTreeDisplayOptions::setShowLeadingZeroes(bool show)
|
||||
{
|
||||
if (show == m_show_leading_zeroes)
|
||||
return false;
|
||||
|
||||
m_show_leading_zeroes = show;
|
||||
return true;
|
||||
}
|
||||
|
||||
std::optional<u64> SymbolTreeDisplayOptions::stringToUnsignedInteger(QString string) const
|
||||
{
|
||||
bool ok;
|
||||
u64 value = string.toULongLong(&ok, m_integer_base);
|
||||
if (!ok)
|
||||
{
|
||||
// Try parsing it as a signed integer too, just in case the user tried
|
||||
// to use a minus sign.
|
||||
value = static_cast<u64>(string.toLongLong(&ok, m_integer_base));
|
||||
if (!ok)
|
||||
return std::nullopt;
|
||||
}
|
||||
|
||||
return value;
|
||||
}
|
||||
|
||||
QString SymbolTreeDisplayOptions::unsignedIntegerToString(u64 value, s32 size_bits) const
|
||||
{
|
||||
int field_width = 0;
|
||||
if (m_show_leading_zeroes)
|
||||
field_width = static_cast<int>(ceilf(size_bits / log2f(m_integer_base)));
|
||||
|
||||
return QStringLiteral("%1").arg(value, field_width, m_integer_base, QLatin1Char('0'));
|
||||
}
|
||||
|
||||
std::optional<s64> SymbolTreeDisplayOptions::stringToSignedInteger(QString string) const
|
||||
{
|
||||
bool ok;
|
||||
s64 value = string.toLongLong(&ok, m_integer_base);
|
||||
if (!ok)
|
||||
{
|
||||
// Try to parse it as an unsigned integer too to handle bases other than
|
||||
// decimal (see below), and to handle the case that the user entered a
|
||||
// value that was too big for a signed integer.
|
||||
value = static_cast<s64>(string.toULongLong(&ok, m_integer_base));
|
||||
if (!ok)
|
||||
return std::nullopt;
|
||||
}
|
||||
|
||||
return value;
|
||||
}
|
||||
|
||||
QString SymbolTreeDisplayOptions::signedIntegerToString(s64 value, s32 size_bits) const
|
||||
{
|
||||
// For bases other than decimal, the user most likely just wants to view the
|
||||
// underlying representation, so we want to display it as unsigned.
|
||||
if (m_integer_base != 10)
|
||||
{
|
||||
// Truncate sign extended bits.
|
||||
u64 mask = (static_cast<u64>(1) << size_bits) - 1;
|
||||
return unsignedIntegerToString(static_cast<u64>(value) & mask, size_bits);
|
||||
}
|
||||
|
||||
int field_width = 0;
|
||||
if (m_show_leading_zeroes)
|
||||
{
|
||||
field_width = static_cast<int>(ceilf(size_bits / log2f(m_integer_base)));
|
||||
|
||||
// An extra character is needed for the minus sign.
|
||||
if (value < 0)
|
||||
field_width++;
|
||||
}
|
||||
|
||||
return QStringLiteral("%1").arg(value, field_width, m_integer_base, QLatin1Char('0'));
|
||||
}
|
||||
|
||||
@@ -9,9 +9,10 @@
|
||||
#include "SymbolTreeLocation.h"
|
||||
|
||||
class DebugInterface;
|
||||
class SymbolTreeDisplayOptions;
|
||||
|
||||
// A node in a symbol tree model.
|
||||
struct SymbolTreeNode
|
||||
class SymbolTreeNode
|
||||
{
|
||||
public:
|
||||
enum Tag
|
||||
@@ -49,16 +50,29 @@ public:
|
||||
|
||||
// Read the value from the VM memory, update liveness information, and
|
||||
// generate a display string. Returns true if the data changed.
|
||||
bool readFromVM(DebugInterface& cpu, const ccc::SymbolDatabase& database);
|
||||
bool readFromVM(
|
||||
DebugInterface& cpu,
|
||||
const ccc::SymbolDatabase& database,
|
||||
const SymbolTreeDisplayOptions& display_options);
|
||||
|
||||
// Write the value back to the VM memory. Returns true on success.
|
||||
bool writeToVM(QVariant value, DebugInterface& cpu, const ccc::SymbolDatabase& database);
|
||||
bool writeToVM(
|
||||
QVariant value,
|
||||
DebugInterface& cpu,
|
||||
const ccc::SymbolDatabase& database,
|
||||
const SymbolTreeDisplayOptions& display_options);
|
||||
|
||||
QVariant readValueAsVariant(const ccc::ast::Node& physical_type, DebugInterface& cpu, const ccc::SymbolDatabase& database) const;
|
||||
bool writeValueFromVariant(QVariant value, const ccc::ast::Node& physical_type, DebugInterface& cpu) const;
|
||||
|
||||
bool updateDisplayString(DebugInterface& cpu, const ccc::SymbolDatabase& database);
|
||||
QString generateDisplayString(const ccc::ast::Node& physical_type, DebugInterface& cpu, const ccc::SymbolDatabase& database, s32 depth) const;
|
||||
bool updateDisplayString(
|
||||
DebugInterface& cpu, const ccc::SymbolDatabase& database, const SymbolTreeDisplayOptions& display);
|
||||
QString generateDisplayString(
|
||||
const ccc::ast::Node& physical_type,
|
||||
DebugInterface& cpu,
|
||||
const ccc::SymbolDatabase& database,
|
||||
const SymbolTreeDisplayOptions& display_options,
|
||||
s32 depth) const;
|
||||
|
||||
bool updateLiveness(DebugInterface& cpu);
|
||||
|
||||
@@ -80,7 +94,7 @@ public:
|
||||
|
||||
void sortChildrenRecursively(bool sort_by_if_type_is_known);
|
||||
|
||||
protected:
|
||||
private:
|
||||
QVariant m_value;
|
||||
QString m_display_value;
|
||||
std::optional<bool> m_liveness;
|
||||
@@ -90,3 +104,25 @@ protected:
|
||||
std::vector<std::unique_ptr<SymbolTreeNode>> m_children;
|
||||
bool m_children_fetched = false;
|
||||
};
|
||||
|
||||
// Settings that control how text in the value column is displayed, including
|
||||
// for the editor widgets.
|
||||
class SymbolTreeDisplayOptions
|
||||
{
|
||||
public:
|
||||
int integerBase() const;
|
||||
bool setIntegerBase(int base);
|
||||
|
||||
bool showLeadingZeroes() const;
|
||||
bool setShowLeadingZeroes(bool show);
|
||||
|
||||
std::optional<u64> stringToUnsignedInteger(QString string) const;
|
||||
QString unsignedIntegerToString(u64 value, s32 size_bits) const;
|
||||
|
||||
std::optional<s64> stringToSignedInteger(QString string) const;
|
||||
QString signedIntegerToString(s64 value, s32 size_bits) const;
|
||||
|
||||
private:
|
||||
int m_integer_base = 10;
|
||||
bool m_show_leading_zeroes = false;
|
||||
};
|
||||
|
||||
@@ -7,6 +7,7 @@
|
||||
#include "Debugger/SymbolTree/NewSymbolDialogs.h"
|
||||
#include "Debugger/SymbolTree/SymbolTreeDelegates.h"
|
||||
|
||||
#include <QtGui/QActionGroup>
|
||||
#include <QtGui/QClipboard>
|
||||
#include <QtWidgets/QInputDialog>
|
||||
#include <QtWidgets/QMenu>
|
||||
@@ -81,6 +82,12 @@ void SymbolTreeView::toJson(JsonValueWrapper& json)
|
||||
{
|
||||
json.value().AddMember("sortByIfTypeIsKnown", m_sort_by_if_type_is_known, json.allocator());
|
||||
}
|
||||
|
||||
if (m_flags & ALLOW_TYPE_ACTIONS)
|
||||
{
|
||||
json.value().AddMember("integerBase", m_display_options.integerBase(), json.allocator());
|
||||
json.value().AddMember("showLeadingZeroes", m_display_options.showLeadingZeroes(), json.allocator());
|
||||
}
|
||||
}
|
||||
|
||||
bool SymbolTreeView::fromJson(const JsonValueWrapper& json)
|
||||
@@ -89,6 +96,7 @@ bool SymbolTreeView::fromJson(const JsonValueWrapper& json)
|
||||
return false;
|
||||
|
||||
bool needs_reset = false;
|
||||
bool needs_update = false;
|
||||
|
||||
auto show_size_column = json.value().FindMember("showSizeColumn");
|
||||
if (show_size_column != json.value().MemberEnd() && show_size_column->value.IsBool())
|
||||
@@ -131,8 +139,26 @@ bool SymbolTreeView::fromJson(const JsonValueWrapper& json)
|
||||
}
|
||||
}
|
||||
|
||||
if (m_flags & ALLOW_TYPE_ACTIONS)
|
||||
{
|
||||
auto integer_base = json.value().FindMember("integerBase");
|
||||
if (integer_base != json.value().MemberEnd() && integer_base->value.IsInt())
|
||||
needs_update |= m_display_options.setIntegerBase(integer_base->value.GetInt());
|
||||
|
||||
auto show_leading_zeroes = json.value().FindMember("showLeadingZeroes");
|
||||
if (show_leading_zeroes != json.value().MemberEnd() && show_leading_zeroes->value.IsBool())
|
||||
needs_update |= m_display_options.setShowLeadingZeroes(show_leading_zeroes->value.GetBool());
|
||||
}
|
||||
|
||||
if (needs_reset)
|
||||
{
|
||||
reset();
|
||||
}
|
||||
else if (needs_update && m_model)
|
||||
{
|
||||
m_model->setDisplayOptions(m_display_options);
|
||||
updateVisibleNodes(false);
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
@@ -221,6 +247,7 @@ void SymbolTreeView::expandGroups(QModelIndex index)
|
||||
void SymbolTreeView::setupTree()
|
||||
{
|
||||
m_model = new SymbolTreeModel(cpu(), this);
|
||||
m_model->setDisplayOptions(m_display_options);
|
||||
m_ui.treeView->setModel(m_model);
|
||||
|
||||
auto location_delegate = new SymbolTreeLocationDelegate(cpu(), m_symbol_address_alignment, this);
|
||||
@@ -556,6 +583,47 @@ void SymbolTreeView::openContextMenu(QPoint pos)
|
||||
QAction* change_type_temporarily = menu->addAction(tr("Change Type Temporarily"));
|
||||
change_type_temporarily->setEnabled(node_is_object);
|
||||
connect(change_type_temporarily, &QAction::triggered, this, &SymbolTreeView::onChangeTypeTemporarily);
|
||||
|
||||
struct IntegerDisplayBase
|
||||
{
|
||||
int base;
|
||||
QString name;
|
||||
};
|
||||
|
||||
const std::array<IntegerDisplayBase, 4> bases = {{
|
||||
{2, tr("Binary")},
|
||||
{8, tr("Octal")},
|
||||
{10, tr("Decimal")},
|
||||
{16, tr("Hexadecimal")},
|
||||
}};
|
||||
|
||||
QMenu* integer_base_menu = menu->addMenu(tr("Integer Base"));
|
||||
QActionGroup* base_actions = new QActionGroup(integer_base_menu);
|
||||
|
||||
for (const auto& [base, name] : bases)
|
||||
{
|
||||
QAction* base_action = integer_base_menu->addAction(name);
|
||||
base_action->setCheckable(true);
|
||||
base_action->setChecked(m_model->displayOptions().integerBase() == base);
|
||||
connect(base_action, &QAction::toggled, this, [this, base](bool checked) {
|
||||
m_display_options.setIntegerBase(base);
|
||||
m_model->setDisplayOptions(m_display_options);
|
||||
|
||||
updateVisibleNodes(false);
|
||||
});
|
||||
|
||||
base_actions->addAction(base_action);
|
||||
}
|
||||
|
||||
QAction* show_leading_zeroes = menu->addAction(tr("Show Leading Zeroes"));
|
||||
show_leading_zeroes->setCheckable(true);
|
||||
show_leading_zeroes->setChecked(m_model->displayOptions().showLeadingZeroes());
|
||||
connect(show_leading_zeroes, &QAction::toggled, this, [this](bool checked) {
|
||||
m_display_options.setShowLeadingZeroes(checked);
|
||||
m_model->setDisplayOptions(m_display_options);
|
||||
|
||||
updateVisibleNodes(false);
|
||||
});
|
||||
}
|
||||
|
||||
menu->popup(m_ui.treeView->viewport()->mapToGlobal(pos));
|
||||
@@ -855,8 +923,8 @@ std::vector<SymbolTreeView::SymbolWork> GlobalVariableTreeView::getSymbols(
|
||||
function_name = tr("unknown function");
|
||||
|
||||
QString name = QString("%1 (%2)")
|
||||
.arg(QString::fromStdString(local_variable.name()))
|
||||
.arg(function_name);
|
||||
.arg(QString::fromStdString(local_variable.name()))
|
||||
.arg(function_name);
|
||||
if (!testName(name, filter))
|
||||
continue;
|
||||
|
||||
|
||||
@@ -8,6 +8,8 @@
|
||||
#include "Debugger/DebuggerView.h"
|
||||
#include "Debugger/SymbolTree/SymbolTreeModel.h"
|
||||
|
||||
class SymbolTreeValueDelegate;
|
||||
|
||||
// A symbol tree view with its associated refresh button, filter box and
|
||||
// right-click menu. Supports grouping, sorting and various other settings.
|
||||
class SymbolTreeView : public DebuggerView
|
||||
@@ -112,6 +114,8 @@ protected:
|
||||
bool m_group_by_section = false;
|
||||
bool m_group_by_source_file = false;
|
||||
bool m_sort_by_if_type_is_known = false;
|
||||
|
||||
SymbolTreeDisplayOptions m_display_options;
|
||||
};
|
||||
|
||||
class FunctionTreeView : public SymbolTreeView
|
||||
|
||||
@@ -116,6 +116,11 @@
|
||||
</item>
|
||||
<item row="5" column="1">
|
||||
<widget class="QComboBox" name="blending">
|
||||
<item>
|
||||
<property name="text">
|
||||
<string>Automatic (Default)</string>
|
||||
</property>
|
||||
</item>
|
||||
<item>
|
||||
<property name="text">
|
||||
<string>Minimum</string>
|
||||
@@ -123,7 +128,7 @@
|
||||
</item>
|
||||
<item>
|
||||
<property name="text">
|
||||
<string>Basic (Recommended)</string>
|
||||
<string>Basic</string>
|
||||
</property>
|
||||
</item>
|
||||
<item>
|
||||
|
||||
@@ -121,7 +121,7 @@ GraphicsSettingsWidget::GraphicsSettingsWidget(SettingsWindow* settings_dialog,
|
||||
SettingWidgetBinder::BindWidgetToIntSetting(sif, m_hw.dithering, "EmuCore/GS", "dithering_ps2", 2);
|
||||
SettingWidgetBinder::BindWidgetToBoolSetting(sif, m_hw.mipmapping, "EmuCore/GS", "hw_mipmap", true);
|
||||
SettingWidgetBinder::BindWidgetToIntSetting(
|
||||
sif, m_hw.blending, "EmuCore/GS", "accurate_blending_unit", static_cast<int>(AccBlendLevel::Basic));
|
||||
sif, m_hw.blending, "EmuCore/GS", "accurate_blending_unit", static_cast<int>(AccBlendLevel::Automatic), -1);
|
||||
SettingWidgetBinder::BindWidgetToBoolSetting(sif, m_hw.enableHWFixes, "EmuCore/GS", "UserHacks", false);
|
||||
connect(m_hw.upscaleMultiplier, QOverload<int>::of(&QComboBox::currentIndexChanged), this,
|
||||
&GraphicsSettingsWidget::onUpscaleMultiplierChanged);
|
||||
|
||||
@@ -44,8 +44,8 @@ const char* InterfaceSettingsWidget::THEME_NAMES[] = {
|
||||
QT_TRANSLATE_NOOP("InterfaceSettingsWidget", "Sapphire (Black/Blue) [Dark]"),
|
||||
//: Ignore what Crowdin says in this string about "[Light]/[Dark]" being untouchable here, these are not variables in this case and must be translated.
|
||||
QT_TRANSLATE_NOOP("InterfaceSettingsWidget", "Emerald (Black/Green) [Dark]"),
|
||||
//: "Custom.qss" must be kept as-is.
|
||||
QT_TRANSLATE_NOOP("InterfaceSettingsWidget", "Custom.qss [Drop in PCSX2 Folder]"),
|
||||
//: "custom.qss" must be kept as-is.
|
||||
QT_TRANSLATE_NOOP("InterfaceSettingsWidget", "custom.qss [Drop in PCSX2 Folder]"),
|
||||
nullptr};
|
||||
|
||||
const char* InterfaceSettingsWidget::THEME_VALUES[] = {
|
||||
|
||||
@@ -12779,7 +12779,7 @@ Scanning recursively takes more time, but will identify files in subdirectories.
|
||||
<context>
|
||||
<name>GlobalVariableTreeView</name>
|
||||
<message>
|
||||
<location filename="../Debugger/SymbolTree/SymbolTreeViews.cpp" line="855"/>
|
||||
<location filename="../Debugger/SymbolTree/SymbolTreeViews.cpp" line="923"/>
|
||||
<source>unknown function</source>
|
||||
<translation type="unfinished"></translation>
|
||||
</message>
|
||||
@@ -17000,12 +17000,6 @@ Right click to clear binding</source>
|
||||
<extracomment>Ignore what Crowdin says in this string about "[Light]/[Dark]" being untouchable here, these are not variables in this case and must be translated.</extracomment>
|
||||
<translation type="unfinished"></translation>
|
||||
</message>
|
||||
<message>
|
||||
<location filename="../Settings/InterfaceSettingsWidget.cpp" line="48"/>
|
||||
<source>Custom.qss [Drop in PCSX2 Folder]</source>
|
||||
<extracomment>"Custom.qss" must be kept as-is.</extracomment>
|
||||
<translation type="unfinished"></translation>
|
||||
</message>
|
||||
<message>
|
||||
<location filename="../Settings/InterfaceSettingsWidget.cpp" line="121"/>
|
||||
<location filename="../Settings/InterfaceSettingsWidget.cpp" line="150"/>
|
||||
@@ -17095,6 +17089,12 @@ Right click to clear binding</source>
|
||||
<source>Fusion [Light/Dark]</source>
|
||||
<translation type="unfinished"></translation>
|
||||
</message>
|
||||
<message>
|
||||
<location filename="../Settings/InterfaceSettingsWidget.cpp" line="48"/>
|
||||
<source>custom.qss [Drop in PCSX2 Folder]</source>
|
||||
<extracomment>"custom.qss" must be kept as-is.</extracomment>
|
||||
<translation type="unfinished"></translation>
|
||||
</message>
|
||||
<message>
|
||||
<location filename="../Settings/InterfaceSettingsWidget.cpp" line="157"/>
|
||||
<source>Pauses the emulator when a game is started.</source>
|
||||
@@ -21323,32 +21323,32 @@ Scanning recursively takes more time, but will identify files in subdirectories.
|
||||
<translation type="unfinished"></translation>
|
||||
</message>
|
||||
<message>
|
||||
<location filename="../Debugger/SymbolTree/SymbolTreeModel.cpp" line="272"/>
|
||||
<location filename="../Debugger/SymbolTree/SymbolTreeModel.cpp" line="278"/>
|
||||
<source>Name</source>
|
||||
<translation type="unfinished"></translation>
|
||||
</message>
|
||||
<message>
|
||||
<location filename="../Debugger/SymbolTree/SymbolTreeModel.cpp" line="274"/>
|
||||
<location filename="../Debugger/SymbolTree/SymbolTreeModel.cpp" line="280"/>
|
||||
<source>Value</source>
|
||||
<translation type="unfinished"></translation>
|
||||
</message>
|
||||
<message>
|
||||
<location filename="../Debugger/SymbolTree/SymbolTreeModel.cpp" line="276"/>
|
||||
<location filename="../Debugger/SymbolTree/SymbolTreeModel.cpp" line="282"/>
|
||||
<source>Location</source>
|
||||
<translation type="unfinished"></translation>
|
||||
</message>
|
||||
<message>
|
||||
<location filename="../Debugger/SymbolTree/SymbolTreeModel.cpp" line="278"/>
|
||||
<location filename="../Debugger/SymbolTree/SymbolTreeModel.cpp" line="284"/>
|
||||
<source>Size</source>
|
||||
<translation type="unfinished"></translation>
|
||||
</message>
|
||||
<message>
|
||||
<location filename="../Debugger/SymbolTree/SymbolTreeModel.cpp" line="280"/>
|
||||
<location filename="../Debugger/SymbolTree/SymbolTreeModel.cpp" line="286"/>
|
||||
<source>Type</source>
|
||||
<translation type="unfinished"></translation>
|
||||
</message>
|
||||
<message>
|
||||
<location filename="../Debugger/SymbolTree/SymbolTreeModel.cpp" line="282"/>
|
||||
<location filename="../Debugger/SymbolTree/SymbolTreeModel.cpp" line="288"/>
|
||||
<source>Liveness</source>
|
||||
<translation type="unfinished"></translation>
|
||||
</message>
|
||||
@@ -21356,12 +21356,12 @@ Scanning recursively takes more time, but will identify files in subdirectories.
|
||||
<context>
|
||||
<name>SymbolTreeTypeDelegate</name>
|
||||
<message>
|
||||
<location filename="../Debugger/SymbolTree/SymbolTreeDelegates.cpp" line="464"/>
|
||||
<location filename="../Debugger/SymbolTree/SymbolTreeDelegates.cpp" line="467"/>
|
||||
<source>Symbol no longer exists.</source>
|
||||
<translation type="unfinished"></translation>
|
||||
</message>
|
||||
<message>
|
||||
<location filename="../Debugger/SymbolTree/SymbolTreeDelegates.cpp" line="482"/>
|
||||
<location filename="../Debugger/SymbolTree/SymbolTreeDelegates.cpp" line="485"/>
|
||||
<source>Cannot Change Type</source>
|
||||
<translation type="unfinished"></translation>
|
||||
</message>
|
||||
@@ -21394,109 +21394,139 @@ Scanning recursively takes more time, but will identify files in subdirectories.
|
||||
<translation type="unfinished"></translation>
|
||||
</message>
|
||||
<message>
|
||||
<location filename="../Debugger/SymbolTree/SymbolTreeViews.cpp" line="355"/>
|
||||
<location filename="../Debugger/SymbolTree/SymbolTreeViews.cpp" line="382"/>
|
||||
<source>(unknown source file)</source>
|
||||
<translation type="unfinished"></translation>
|
||||
</message>
|
||||
<message>
|
||||
<location filename="../Debugger/SymbolTree/SymbolTreeViews.cpp" line="394"/>
|
||||
<location filename="../Debugger/SymbolTree/SymbolTreeViews.cpp" line="421"/>
|
||||
<source>(unknown section)</source>
|
||||
<translation type="unfinished"></translation>
|
||||
</message>
|
||||
<message>
|
||||
<location filename="../Debugger/SymbolTree/SymbolTreeViews.cpp" line="439"/>
|
||||
<location filename="../Debugger/SymbolTree/SymbolTreeViews.cpp" line="466"/>
|
||||
<source>(unknown module)</source>
|
||||
<translation type="unfinished"></translation>
|
||||
</message>
|
||||
<message>
|
||||
<location filename="../Debugger/SymbolTree/SymbolTreeViews.cpp" line="464"/>
|
||||
<location filename="../Debugger/SymbolTree/SymbolTreeViews.cpp" line="491"/>
|
||||
<source>Copy Name</source>
|
||||
<translation type="unfinished"></translation>
|
||||
</message>
|
||||
<message>
|
||||
<location filename="../Debugger/SymbolTree/SymbolTreeViews.cpp" line="469"/>
|
||||
<location filename="../Debugger/SymbolTree/SymbolTreeViews.cpp" line="496"/>
|
||||
<source>Copy Mangled Name</source>
|
||||
<translation type="unfinished"></translation>
|
||||
</message>
|
||||
<message>
|
||||
<location filename="../Debugger/SymbolTree/SymbolTreeViews.cpp" line="473"/>
|
||||
<location filename="../Debugger/SymbolTree/SymbolTreeViews.cpp" line="500"/>
|
||||
<source>Copy Location</source>
|
||||
<translation type="unfinished"></translation>
|
||||
</message>
|
||||
<message>
|
||||
<location filename="../Debugger/SymbolTree/SymbolTreeViews.cpp" line="478"/>
|
||||
<location filename="../Debugger/SymbolTree/SymbolTreeViews.cpp" line="624"/>
|
||||
<location filename="../Debugger/SymbolTree/SymbolTreeViews.cpp" line="505"/>
|
||||
<location filename="../Debugger/SymbolTree/SymbolTreeViews.cpp" line="692"/>
|
||||
<source>Rename Symbol</source>
|
||||
<translation type="unfinished"></translation>
|
||||
</message>
|
||||
<message>
|
||||
<location filename="../Debugger/SymbolTree/SymbolTreeViews.cpp" line="498"/>
|
||||
<location filename="../Debugger/SymbolTree/SymbolTreeViews.cpp" line="525"/>
|
||||
<source>Show Size Column</source>
|
||||
<translation type="unfinished"></translation>
|
||||
</message>
|
||||
<message>
|
||||
<location filename="../Debugger/SymbolTree/SymbolTreeViews.cpp" line="510"/>
|
||||
<location filename="../Debugger/SymbolTree/SymbolTreeViews.cpp" line="537"/>
|
||||
<source>Group by Module</source>
|
||||
<translation type="unfinished"></translation>
|
||||
</message>
|
||||
<message>
|
||||
<location filename="../Debugger/SymbolTree/SymbolTreeViews.cpp" line="518"/>
|
||||
<location filename="../Debugger/SymbolTree/SymbolTreeViews.cpp" line="545"/>
|
||||
<source>Group by Section</source>
|
||||
<translation type="unfinished"></translation>
|
||||
</message>
|
||||
<message>
|
||||
<location filename="../Debugger/SymbolTree/SymbolTreeViews.cpp" line="526"/>
|
||||
<location filename="../Debugger/SymbolTree/SymbolTreeViews.cpp" line="553"/>
|
||||
<source>Group by Source File</source>
|
||||
<translation type="unfinished"></translation>
|
||||
</message>
|
||||
<message>
|
||||
<location filename="../Debugger/SymbolTree/SymbolTreeViews.cpp" line="539"/>
|
||||
<location filename="../Debugger/SymbolTree/SymbolTreeViews.cpp" line="566"/>
|
||||
<source>Sort by if type is known</source>
|
||||
<translation type="unfinished"></translation>
|
||||
</message>
|
||||
<message>
|
||||
<location filename="../Debugger/SymbolTree/SymbolTreeViews.cpp" line="552"/>
|
||||
<location filename="../Debugger/SymbolTree/SymbolTreeViews.cpp" line="579"/>
|
||||
<source>Reset Children</source>
|
||||
<translation type="unfinished"></translation>
|
||||
</message>
|
||||
<message>
|
||||
<location filename="../Debugger/SymbolTree/SymbolTreeViews.cpp" line="556"/>
|
||||
<location filename="../Debugger/SymbolTree/SymbolTreeViews.cpp" line="583"/>
|
||||
<source>Change Type Temporarily</source>
|
||||
<translation type="unfinished"></translation>
|
||||
</message>
|
||||
<message>
|
||||
<location filename="../Debugger/SymbolTree/SymbolTreeViews.cpp" line="578"/>
|
||||
<location filename="../Debugger/SymbolTree/SymbolTreeViews.cpp" line="594"/>
|
||||
<source>Binary</source>
|
||||
<translation type="unfinished"></translation>
|
||||
</message>
|
||||
<message>
|
||||
<location filename="../Debugger/SymbolTree/SymbolTreeViews.cpp" line="595"/>
|
||||
<source>Octal</source>
|
||||
<translation type="unfinished"></translation>
|
||||
</message>
|
||||
<message>
|
||||
<location filename="../Debugger/SymbolTree/SymbolTreeViews.cpp" line="596"/>
|
||||
<source>Decimal</source>
|
||||
<translation type="unfinished"></translation>
|
||||
</message>
|
||||
<message>
|
||||
<location filename="../Debugger/SymbolTree/SymbolTreeViews.cpp" line="597"/>
|
||||
<source>Hexadecimal</source>
|
||||
<translation type="unfinished"></translation>
|
||||
</message>
|
||||
<message>
|
||||
<location filename="../Debugger/SymbolTree/SymbolTreeViews.cpp" line="600"/>
|
||||
<source>Integer Base</source>
|
||||
<translation type="unfinished"></translation>
|
||||
</message>
|
||||
<message>
|
||||
<location filename="../Debugger/SymbolTree/SymbolTreeViews.cpp" line="618"/>
|
||||
<source>Show Leading Zeroes</source>
|
||||
<translation type="unfinished"></translation>
|
||||
</message>
|
||||
<message>
|
||||
<location filename="../Debugger/SymbolTree/SymbolTreeViews.cpp" line="646"/>
|
||||
<source>Confirm Deletion</source>
|
||||
<translation type="unfinished"></translation>
|
||||
</message>
|
||||
<message>
|
||||
<location filename="../Debugger/SymbolTree/SymbolTreeViews.cpp" line="578"/>
|
||||
<location filename="../Debugger/SymbolTree/SymbolTreeViews.cpp" line="646"/>
|
||||
<source>Delete '%1'?</source>
|
||||
<translation type="unfinished"></translation>
|
||||
</message>
|
||||
<message>
|
||||
<location filename="../Debugger/SymbolTree/SymbolTreeViews.cpp" line="625"/>
|
||||
<location filename="../Debugger/SymbolTree/SymbolTreeViews.cpp" line="693"/>
|
||||
<source>Name:</source>
|
||||
<translation type="unfinished"></translation>
|
||||
</message>
|
||||
<message>
|
||||
<location filename="../Debugger/SymbolTree/SymbolTreeViews.cpp" line="667"/>
|
||||
<location filename="../Debugger/SymbolTree/SymbolTreeViews.cpp" line="735"/>
|
||||
<source>Change Type To</source>
|
||||
<translation type="unfinished"></translation>
|
||||
</message>
|
||||
<message>
|
||||
<location filename="../Debugger/SymbolTree/SymbolTreeViews.cpp" line="668"/>
|
||||
<location filename="../Debugger/SymbolTree/SymbolTreeViews.cpp" line="736"/>
|
||||
<source>Type:</source>
|
||||
<translation type="unfinished"></translation>
|
||||
</message>
|
||||
<message>
|
||||
<location filename="../Debugger/SymbolTree/SymbolTreeViews.cpp" line="672"/>
|
||||
<location filename="../Debugger/SymbolTree/SymbolTreeViews.cpp" line="683"/>
|
||||
<location filename="../Debugger/SymbolTree/SymbolTreeViews.cpp" line="740"/>
|
||||
<location filename="../Debugger/SymbolTree/SymbolTreeViews.cpp" line="751"/>
|
||||
<source>Cannot Change Type</source>
|
||||
<translation type="unfinished"></translation>
|
||||
</message>
|
||||
<message>
|
||||
<location filename="../Debugger/SymbolTree/SymbolTreeViews.cpp" line="672"/>
|
||||
<location filename="../Debugger/SymbolTree/SymbolTreeViews.cpp" line="740"/>
|
||||
<source>That node cannot have a type.</source>
|
||||
<translation type="unfinished"></translation>
|
||||
</message>
|
||||
|
||||
@@ -75,7 +75,7 @@ void InputIsoFile::BeginRead2(uint lsn)
|
||||
{
|
||||
// While this usually indicates that the ISO is corrupted, some games do attempt
|
||||
// to read past the end of the disc, so don't error here.
|
||||
ERROR_LOG("isoFile error: Block index is past the end of file! (%u >= %u).", lsn, m_blocks);
|
||||
ERROR_LOG("isoFile error: Block index is past the end of file! ({} >= {}).", lsn, m_blocks);
|
||||
return;
|
||||
}
|
||||
|
||||
|
||||
@@ -327,8 +327,9 @@ enum class TriFiltering : s8
|
||||
Forced,
|
||||
};
|
||||
|
||||
enum class AccBlendLevel : u8
|
||||
enum class AccBlendLevel : s8
|
||||
{
|
||||
Automatic = -1,
|
||||
Minimum,
|
||||
Basic,
|
||||
Medium,
|
||||
@@ -811,7 +812,7 @@ struct Pcsx2Config
|
||||
GSRendererType Renderer = GSRendererType::Auto;
|
||||
float UpscaleMultiplier = 1.0f;
|
||||
|
||||
AccBlendLevel AccurateBlendingUnit = AccBlendLevel::Basic;
|
||||
AccBlendLevel AccurateBlendingUnit = AccBlendLevel::Automatic;
|
||||
BiFiltering TextureFiltering = BiFiltering::PS2;
|
||||
TexturePreloadingLevel TexturePreloading = TexturePreloadingLevel::Full;
|
||||
GSDumpCompressionMethod GSDumpCompression = GSDumpCompressionMethod::Zstandard;
|
||||
|
||||
@@ -2741,12 +2741,6 @@ void GSDevice11::RenderHW(GSHWDrawConfig& config)
|
||||
|
||||
OMSetRenderTargets(draw_rt, draw_ds, &config.scissor, read_only_dsv);
|
||||
SetupOM(config.depth, OMBlendSelector(config.colormask, config.blend), config.blend.constant);
|
||||
|
||||
// Clear stencil as close as possible to the RT bind, to avoid framebuffer swaps.
|
||||
if (draw_ds && config.destination_alpha == GSHWDrawConfig::DestinationAlphaMode::StencilOne &&
|
||||
m_features.multidraw_fb_copy && (config.require_one_barrier || config.require_full_barrier))
|
||||
m_ctx->ClearDepthStencilView(*static_cast<GSTexture11*>(draw_ds), D3D11_CLEAR_STENCIL, 0.0f, 1);
|
||||
|
||||
SendHWDraw(config, draw_rt_clone, draw_rt, config.require_one_barrier, config.require_full_barrier, false);
|
||||
|
||||
if (config.blend_multi_pass.enable)
|
||||
|
||||
@@ -5180,6 +5180,8 @@ void GSRendererHW::EmulateTextureShuffleAndFbmask(GSTextureCache::Target* rt, GS
|
||||
enable_fbmask_emulation = true;
|
||||
break;
|
||||
case AccBlendLevel::Basic:
|
||||
case AccBlendLevel::Automatic:
|
||||
default:
|
||||
// Enable Fbmask emulation excluding triangle class because it is quite slow.
|
||||
enable_fbmask_emulation = (m_vt.m_primclass != GS_TRIANGLE_CLASS);
|
||||
break;
|
||||
@@ -5204,7 +5206,7 @@ void GSRendererHW::EmulateTextureShuffleAndFbmask(GSTextureCache::Target* rt, GS
|
||||
|
||||
// If date is enabled you need to test the green channel instead of the alpha channel.
|
||||
// Only enable this code in DATE mode to reduce the number of shaders.
|
||||
m_conf.ps.write_rg = (process_rg & SHUFFLE_WRITE) && m_cached_ctx.TEST.DATE;
|
||||
m_conf.ps.write_rg = (process_rg & SHUFFLE_WRITE) && (features.texture_barrier || features.multidraw_fb_copy) && m_cached_ctx.TEST.DATE;
|
||||
m_conf.ps.real16src = m_copy_16bit_to_target_shuffle;
|
||||
m_conf.ps.shuffle_same = m_same_group_texture_shuffle;
|
||||
// Please bang my head against the wall!
|
||||
@@ -5784,7 +5786,7 @@ void GSRendererHW::EmulateBlending(int rt_alpha_min, int rt_alpha_max, const boo
|
||||
const bool blend_ad = m_conf.ps.blend_c == 1;
|
||||
const bool alpha_mask = (m_cached_ctx.FRAME.FBMSK & 0xFF000000) == 0xFF000000;
|
||||
bool blend_ad_alpha_masked = blend_ad && alpha_mask;
|
||||
const bool is_basic_blend = GSConfig.AccurateBlendingUnit >= AccBlendLevel::Basic;
|
||||
const bool is_basic_blend = GSConfig.AccurateBlendingUnit != AccBlendLevel::Minimum;
|
||||
if (blend_ad_alpha_masked && (((is_basic_blend || (COLCLAMP.CLAMP == 0)) && (features.texture_barrier || features.multidraw_fb_copy))
|
||||
|| ((GSConfig.AccurateBlendingUnit >= AccBlendLevel::Medium) || m_conf.require_one_barrier)))
|
||||
{
|
||||
@@ -5894,6 +5896,8 @@ void GSRendererHW::EmulateBlending(int rt_alpha_min, int rt_alpha_max, const boo
|
||||
sw_blending |= m_vt.m_primclass == GS_SPRITE_CLASS && m_drawlist.size() < 100;
|
||||
[[fallthrough]];
|
||||
case AccBlendLevel::Basic:
|
||||
case AccBlendLevel::Automatic:
|
||||
default:
|
||||
// Prefer sw blend if possible.
|
||||
color_dest_blend &= !prefer_sw_blend;
|
||||
color_dest_blend2 &= !prefer_sw_blend;
|
||||
@@ -5935,6 +5939,8 @@ void GSRendererHW::EmulateBlending(int rt_alpha_min, int rt_alpha_max, const boo
|
||||
sw_blending |= !(blend_ad_alpha_masked || ad_second_pass) && (alpha_c1_high_max_one || alpha_c1_high_no_rta_correct) && no_prim_overlap;
|
||||
[[fallthrough]];
|
||||
case AccBlendLevel::Basic:
|
||||
case AccBlendLevel::Automatic:
|
||||
default:
|
||||
// Prefer sw blend if possible.
|
||||
color_dest_blend &= !prefer_sw_blend;
|
||||
color_dest_blend2 &= !prefer_sw_blend;
|
||||
@@ -6441,7 +6447,8 @@ void GSRendererHW::EmulateBlending(int rt_alpha_min, int rt_alpha_max, const boo
|
||||
// Switch DATE_PRIMID with DATE_BARRIER in such cases to ensure accuracy.
|
||||
// No mix of COLCLIP + sw blend + DATE_PRIMID, neither sw fbmask + DATE_PRIMID.
|
||||
// Note: Do the swap in the end, saves the expensive draw splitting/barriers when mixed software blending is used.
|
||||
if (sw_blending && DATE_PRIMID && m_conf.require_full_barrier)
|
||||
if (sw_blending && DATE_PRIMID && m_conf.require_full_barrier &&
|
||||
(features.texture_barrier || (features.multidraw_fb_copy && !no_prim_overlap)))
|
||||
{
|
||||
GL_PERF("DATE: Swap DATE_PRIMID with DATE_BARRIER");
|
||||
DATE_PRIMID = false;
|
||||
@@ -7969,8 +7976,7 @@ __ri void GSRendererHW::DrawPrims(GSTextureCache::Target* rt, GSTextureCache::Ta
|
||||
}
|
||||
else if (DATE_one)
|
||||
{
|
||||
const bool multidraw_fb_copy = features.multidraw_fb_copy && (m_conf.require_one_barrier || m_conf.require_full_barrier);
|
||||
if (features.texture_barrier || multidraw_fb_copy)
|
||||
if (features.texture_barrier)
|
||||
{
|
||||
m_conf.require_one_barrier = true;
|
||||
m_conf.ps.date = 5 + m_cached_ctx.TEST.DATM;
|
||||
|
||||
@@ -664,10 +664,10 @@ bool GameDatabaseSchema::GameEntry::configMatchesHWFix(const Pcsx2Config::GSOpti
|
||||
return (config.GPUPaletteConversion == ((value > 1) ? (config.TexturePreloading == TexturePreloadingLevel::Full) : (value != 0)));
|
||||
|
||||
case GSHWFixId::MinimumBlendingLevel:
|
||||
return (static_cast<int>(config.AccurateBlendingUnit) >= value);
|
||||
return (config.AccurateBlendingUnit == AccBlendLevel::Automatic || static_cast<int>(config.AccurateBlendingUnit) >= value);
|
||||
|
||||
case GSHWFixId::MaximumBlendingLevel:
|
||||
return (static_cast<int>(config.AccurateBlendingUnit) <= value);
|
||||
return (config.AccurateBlendingUnit == AccBlendLevel::Automatic || static_cast<int>(config.AccurateBlendingUnit) <= value);
|
||||
|
||||
case GSHWFixId::RecommendedBlendingLevel:
|
||||
return true;
|
||||
@@ -868,21 +868,23 @@ void GameDatabaseSchema::GameEntry::applyGSHardwareFixes(Pcsx2Config::GSOptions&
|
||||
|
||||
case GSHWFixId::MinimumBlendingLevel:
|
||||
{
|
||||
if (value >= 0 && value <= static_cast<int>(AccBlendLevel::Maximum))
|
||||
config.AccurateBlendingUnit = std::max(config.AccurateBlendingUnit, static_cast<AccBlendLevel>(value));
|
||||
if (value >= 0 && value <= static_cast<int>(AccBlendLevel::Maximum) && config.AccurateBlendingUnit == AccBlendLevel::Automatic)
|
||||
config.AccurateBlendingUnit = static_cast<AccBlendLevel>(value);
|
||||
}
|
||||
break;
|
||||
|
||||
case GSHWFixId::MaximumBlendingLevel:
|
||||
{
|
||||
if (value >= 0 && value <= static_cast<int>(AccBlendLevel::Maximum))
|
||||
config.AccurateBlendingUnit = std::min(config.AccurateBlendingUnit, static_cast<AccBlendLevel>(value));
|
||||
if (value >= 0 && value <= static_cast<int>(AccBlendLevel::Maximum) && config.AccurateBlendingUnit == AccBlendLevel::Automatic)
|
||||
config.AccurateBlendingUnit = static_cast<AccBlendLevel>(value);
|
||||
}
|
||||
break;
|
||||
|
||||
case GSHWFixId::RecommendedBlendingLevel:
|
||||
{
|
||||
if (!is_sw_renderer && value >= 0 && value <= static_cast<int>(AccBlendLevel::Maximum) && static_cast<int>(EmuConfig.GS.AccurateBlendingUnit) < value)
|
||||
// Need to increment by 1 because Automatic is -1.
|
||||
const int blend_level = static_cast<int>(config.AccurateBlendingUnit) + 1;
|
||||
if (!is_sw_renderer && value >= static_cast<int>(AccBlendLevel::Automatic) && value <= static_cast<int>(AccBlendLevel::Maximum) && blend_level < value)
|
||||
{
|
||||
Host::AddKeyedOSDMessage("HWBlendingWarning",
|
||||
fmt::format(TRANSLATE_FS("GameDatabase",
|
||||
@@ -891,8 +893,7 @@ void GameDatabaseSchema::GameEntry::applyGSHardwareFixes(Pcsx2Config::GSOptions&
|
||||
"You can adjust the blending level in Game Properties to improve\n"
|
||||
"graphical quality, but this will increase system requirements."),
|
||||
ICON_FA_PAINTBRUSH,
|
||||
Pcsx2Config::GSOptions::BlendingLevelNames[static_cast<int>(
|
||||
EmuConfig.GS.AccurateBlendingUnit)],
|
||||
Pcsx2Config::GSOptions::BlendingLevelNames[blend_level],
|
||||
Pcsx2Config::GSOptions::BlendingLevelNames[value]),
|
||||
Host::OSD_WARNING_DURATION);
|
||||
}
|
||||
|
||||
@@ -4066,8 +4066,9 @@ void FullscreenUI::DrawGraphicsSettingsPage(SettingsInterface* bsi, bool show_ad
|
||||
FSUI_NSTR("Force 32bit"),
|
||||
};
|
||||
static constexpr const char* s_blending_options[] = {
|
||||
FSUI_NSTR("Automatic (Default)"),
|
||||
FSUI_NSTR("Minimum"),
|
||||
FSUI_NSTR("Basic (Recommended)"),
|
||||
FSUI_NSTR("Basic"),
|
||||
FSUI_NSTR("Medium"),
|
||||
FSUI_NSTR("High"),
|
||||
FSUI_NSTR("Full (Slow)"),
|
||||
@@ -4199,7 +4200,7 @@ void FullscreenUI::DrawGraphicsSettingsPage(SettingsInterface* bsi, bool show_ad
|
||||
"EmuCore/GS", "dithering_ps2", 2, s_dithering_options, std::size(s_dithering_options), true);
|
||||
DrawIntListSetting(bsi, FSUI_ICONSTR(ICON_FA_SPLOTCH, "Blending Accuracy"),
|
||||
FSUI_CSTR("Determines the level of accuracy when emulating blend modes not supported by the host graphics API."), "EmuCore/GS",
|
||||
"accurate_blending_unit", static_cast<int>(AccBlendLevel::Basic), s_blending_options, std::size(s_blending_options), true);
|
||||
"accurate_blending_unit", static_cast<int>(AccBlendLevel::Automatic), s_blending_options, std::size(s_blending_options), true);
|
||||
DrawToggleSetting(
|
||||
bsi, FSUI_ICONSTR(ICON_FA_BULLSEYE, "Mipmapping"), FSUI_CSTR("Enables emulation of the GS's texture mipmapping."), "EmuCore/GS", "hw_mipmap", true);
|
||||
}
|
||||
|
||||
@@ -653,6 +653,7 @@ const char* Pcsx2Config::GSOptions::FMVAspectRatioSwitchNames[(size_t)FMVAspectR
|
||||
nullptr};
|
||||
|
||||
const char* Pcsx2Config::GSOptions::BlendingLevelNames[] = {
|
||||
"Automatic",
|
||||
"Minimum",
|
||||
"Basic",
|
||||
"Medium",
|
||||
|
||||
@@ -3150,12 +3150,12 @@ void VMManager::WarnAboutUnsafeSettings()
|
||||
if (EmuConfig.GS.TriFilter != TriFiltering::Automatic)
|
||||
{
|
||||
append(ICON_FA_PAGER,
|
||||
TRANSLATE_SV("VMManager", "Trilinear filtering is not set to automatic. This may break rendering in some games."));
|
||||
TRANSLATE_SV("VMManager", "Trilinear filtering is not set to Automatic. This may break rendering in some games."));
|
||||
}
|
||||
if (EmuConfig.GS.AccurateBlendingUnit <= AccBlendLevel::Minimum)
|
||||
if (EmuConfig.GS.AccurateBlendingUnit == AccBlendLevel::Minimum)
|
||||
{
|
||||
append(ICON_FA_PAINTBRUSH,
|
||||
TRANSLATE_SV("VMManager", "Blending Accuracy is below Basic, this may break effects in some games."));
|
||||
TRANSLATE_SV("VMManager", "Blending Accuracy is set to Minimum. This may break rendering in some games."));
|
||||
}
|
||||
if (EmuConfig.GS.HWDownloadMode != GSHardwareDownloadMode::Enabled)
|
||||
{
|
||||
|
||||
Reference in New Issue
Block a user