All: Add option to lock video to integer scaling
jump to
@@ -15,6 +15,7 @@ - Savestates now contain any RTC override data
- Command line ability to override configuration values - Add option to allow preloading the entire ROM before running - GB: Video/audio channel enabling/disabling + - Add option to lock video to integer scaling Bugfixes: - LR35902: Fix core never exiting with certain event patterns - GB Timer: Improve DIV reset behavior
@@ -42,6 +42,7 @@ int fullscreen;
int width; int height; bool lockAspectRatio; + bool lockIntegerScaling; bool resampleVideo; bool suspendScreensaver; char* shader;
@@ -349,6 +349,9 @@ }
if (_lookupIntValue(config, "lockAspectRatio", &fakeBool)) { opts->lockAspectRatio = fakeBool; } + if (_lookupIntValue(config, "lockIntegerScaling", &fakeBool)) { + opts->lockIntegerScaling = fakeBool; + } if (_lookupIntValue(config, "resampleVideo", &fakeBool)) { opts->resampleVideo = fakeBool; }@@ -396,6 +399,7 @@ ConfigurationSetIntValue(&config->defaultsTable, 0, "height", opts->height);
ConfigurationSetIntValue(&config->defaultsTable, 0, "volume", opts->volume); ConfigurationSetIntValue(&config->defaultsTable, 0, "mute", opts->mute); ConfigurationSetIntValue(&config->defaultsTable, 0, "lockAspectRatio", opts->lockAspectRatio); + ConfigurationSetIntValue(&config->defaultsTable, 0, "lockIntegerScaling", opts->lockIntegerScaling); ConfigurationSetIntValue(&config->defaultsTable, 0, "resampleVideo", opts->resampleVideo); ConfigurationSetIntValue(&config->defaultsTable, 0, "suspendScreensaver", opts->suspendScreensaver); }
@@ -65,6 +65,10 @@ } else if (w * v->height < h * v->width) {
drawH = w * v->height / v->width; } } + if (v->lockIntegerScaling) { + drawW -= drawW % v->width; + drawH -= drawH % v->height; + } glMatrixMode(GL_MODELVIEW); glLoadIdentity(); glClearColor(0, 0, 0, 0);
@@ -171,6 +171,10 @@ } else if (w * v->height < h * v->width) {
drawH = w * v->height / v->width; } } + if (v->lockIntegerScaling) { + drawW -= drawW % v->width; + drawH -= drawH % v->height; + } glViewport(0, 0, v->width, v->height); glClearColor(0.f, 0.f, 0.f, 1.f); glClear(GL_COLOR_BUFFER_BIT);
@@ -54,6 +54,7 @@
Display::Display(QWidget* parent) : QWidget(parent) , m_lockAspectRatio(false) + , m_lockIntegerScaling(false) , m_filter(false) { setSizePolicy(QSizePolicy::MinimumExpanding, QSizePolicy::MinimumExpanding);@@ -75,6 +76,10 @@
void Display::lockAspectRatio(bool lock) { m_lockAspectRatio = lock; m_messagePainter.resize(size(), m_lockAspectRatio, devicePixelRatio()); +} + +void Display::lockIntegerScaling(bool lock) { + m_lockIntegerScaling = lock; } void Display::filter(bool filter) {
@@ -38,6 +38,7 @@ static Display* create(QWidget* parent = nullptr);
static void setDriver(Driver driver) { s_driver = driver; } bool isAspectRatioLocked() const { return m_lockAspectRatio; } + bool isIntegerScalingLocked() const { return m_lockIntegerScaling; } bool isFiltered() const { return m_filter; } virtual bool isDrawing() const = 0;@@ -55,6 +56,7 @@ virtual void pauseDrawing() = 0;
virtual void unpauseDrawing() = 0; virtual void forceDraw() = 0; virtual void lockAspectRatio(bool lock); + virtual void lockIntegerScaling(bool lock); virtual void filter(bool filter); virtual void framePosted(const uint32_t*) = 0; virtual void setShaders(struct VDir*) = 0;@@ -74,6 +76,7 @@ static const int MOUSE_DISAPPEAR_TIMER = 1000;
MessagePainter m_messagePainter; bool m_lockAspectRatio; + bool m_lockIntegerScaling; bool m_filter; QTimer m_mouseTimer; };
@@ -73,6 +73,7 @@ m_drawThread->start();
mCoreSyncSetVideoSync(&m_context->sync, false); lockAspectRatio(isAspectRatioLocked()); + lockIntegerScaling(isIntegerScalingLocked()); filter(isFiltered()); #if (QT_VERSION >= QT_VERSION_CHECK(5, 6, 0)) messagePainter()->resize(size(), isAspectRatioLocked(), devicePixelRatioF());@@ -133,6 +134,13 @@ void DisplayGL::lockAspectRatio(bool lock) {
Display::lockAspectRatio(lock); if (m_drawThread) { QMetaObject::invokeMethod(m_painter, "lockAspectRatio", Q_ARG(bool, lock)); + } +} + +void DisplayGL::lockIntegerScaling(bool lock) { + Display::lockIntegerScaling(lock); + if (m_drawThread) { + QMetaObject::invokeMethod(m_painter, "lockIntegerScaling", Q_ARG(bool, lock)); } }@@ -285,6 +293,13 @@ }
void PainterGL::lockAspectRatio(bool lock) { m_backend->lockAspectRatio = lock; + if (m_started && !m_active) { + forceDraw(); + } +} + +void PainterGL::lockIntegerScaling(bool lock) { + m_backend->lockIntegerScaling = lock; if (m_started && !m_active) { forceDraw(); }
@@ -55,6 +55,7 @@ void pauseDrawing() override;
void unpauseDrawing() override; void forceDraw() override; void lockAspectRatio(bool lock) override; + void lockIntegerScaling(bool lock) override; void filter(bool filter) override; void framePosted(const uint32_t*) override; void setShaders(struct VDir*) override;@@ -96,6 +97,7 @@ void pause();
void unpause(); void resize(const QSize& size); void lockAspectRatio(bool lock); + void lockIntegerScaling(bool lock); void filter(bool filter); void setShaders(struct VDir*);
@@ -30,6 +30,11 @@ Display::lockAspectRatio(lock);
update(); } +void DisplayQt::lockIntegerScaling(bool lock) { + Display::lockIntegerScaling(lock); + update(); +} + void DisplayQt::filter(bool filter) { Display::filter(filter); update();@@ -65,6 +70,10 @@ ds.setWidth(s.height() * m_width / m_height);
} else if (s.width() * m_height < s.height() * m_width) { ds.setHeight(s.width() * m_height / m_width); } + } + if (isIntegerScalingLocked()) { + ds.setWidth(ds.width() - ds.width() % m_width); + ds.setHeight(ds.height() - ds.height() % m_height); } QPoint origin = QPoint((s.width() - ds.width()) / 2, (s.height() - ds.height()) / 2); QRect full(origin, ds);
@@ -30,6 +30,7 @@ void pauseDrawing() override { m_isDrawing = false; }
void unpauseDrawing() override { m_isDrawing = true; } void forceDraw() override { update(); } void lockAspectRatio(bool lock) override; + void lockIntegerScaling(bool lock) override; void filter(bool filter) override; void framePosted(const uint32_t*) override; void setShaders(struct VDir*) override {}
@@ -190,6 +190,7 @@ saveSetting("audioSync", m_ui.audioSync);
saveSetting("frameskip", m_ui.frameskip); saveSetting("fpsTarget", m_ui.fpsTarget); saveSetting("lockAspectRatio", m_ui.lockAspectRatio); + saveSetting("lockIntegerScaling", m_ui.lockIntegerScaling); saveSetting("volume", m_ui.volume); saveSetting("mute", m_ui.mute); saveSetting("rewindEnable", m_ui.rewind);@@ -270,6 +271,7 @@ loadSetting("audioSync", m_ui.audioSync);
loadSetting("frameskip", m_ui.frameskip); loadSetting("fpsTarget", m_ui.fpsTarget); loadSetting("lockAspectRatio", m_ui.lockAspectRatio); + loadSetting("lockIntegerScaling", m_ui.lockIntegerScaling); loadSetting("volume", m_ui.volume); loadSetting("mute", m_ui.mute); loadSetting("rewindEnable", m_ui.rewind);
@@ -7,7 +7,7 @@ <rect>
<x>0</x> <y>0</y> <width>650</width> - <height>450</height> + <height>454</height> </rect> </property> <property name="sizePolicy">@@ -115,7 +115,7 @@ <widget class="QComboBox" name="audioBufferSize">
<property name="editable"> <bool>true</bool> </property> - <property name="currentText" stdset="0"> + <property name="currentText"> <string>1536</string> </property> <property name="currentIndex">@@ -181,7 +181,7 @@ <widget class="QComboBox" name="sampleRate">
<property name="editable"> <bool>true</bool> </property> - <property name="currentText" stdset="0"> + <property name="currentText"> <string>44100</string> </property> <property name="currentIndex">@@ -380,10 +380,17 @@ <string>Lock aspect ratio</string>
</property> </widget> </item> - <item row="11" column="1"> + <item row="12" column="1"> <widget class="QCheckBox" name="resampleVideo"> <property name="text"> <string>Bilinear filtering</string> + </property> + </widget> + </item> + <item row="11" column="1"> + <widget class="QCheckBox" name="lockIntegerScaling"> + <property name="text"> + <string>Force integer scaling</string> </property> </widget> </item>
@@ -1263,6 +1263,14 @@ m_display->lockAspectRatio(value.toBool());
}, this); m_config->updateOption("lockAspectRatio"); + ConfigOption* lockIntegerScaling = m_config->addOption("lockIntegerScaling"); + lockIntegerScaling->addBoolean(tr("Force integer scaling"), avMenu); + lockIntegerScaling->connect([this](const QVariant& value) { + m_display->lockIntegerScaling(value.toBool()); + m_screenWidget->setLockIntegerScaling(value.toBool()); + }, this); + m_config->updateOption("lockIntegerScaling"); + ConfigOption* resampleVideo = m_config->addOption("resampleVideo"); resampleVideo->addBoolean(tr("Bilinear filtering"), avMenu); resampleVideo->connect([this](const QVariant& value) {@@ -1637,6 +1645,10 @@ m_aspectWidth = width;
m_aspectHeight = height; } +void WindowBackground::setLockIntegerScaling(bool lock) { + m_lockIntegerScaling = lock; +} + void WindowBackground::paintEvent(QPaintEvent*) { const QPixmap* logo = pixmap(); if (!logo) {@@ -1651,6 +1663,10 @@ if (ds.width() * m_aspectHeight > ds.height() * m_aspectWidth) {
ds.setWidth(ds.height() * m_aspectWidth / m_aspectHeight); } else if (ds.width() * m_aspectHeight < ds.height() * m_aspectWidth) { ds.setHeight(ds.width() * m_aspectHeight / m_aspectWidth); + } + if (m_lockIntegerScaling) { + ds.setWidth(ds.width() - ds.width() % m_aspectWidth); + ds.setHeight(ds.height() - ds.height() % m_aspectHeight); } QPoint origin = QPoint((s.width() - ds.width()) / 2, (s.height() - ds.height()) / 2); QRect full(origin, ds);
@@ -210,6 +210,7 @@
void setSizeHint(const QSize& size); virtual QSize sizeHint() const override; void setLockAspectRatio(int width, int height); + void setLockIntegerScaling(bool lock); protected: virtual void paintEvent(QPaintEvent*) override;@@ -218,6 +219,7 @@ private:
QSize m_sizeHint; int m_aspectWidth; int m_aspectHeight; + bool m_lockIntegerScaling; }; }
@@ -35,6 +35,7 @@ unsigned height;
bool filter; bool lockAspectRatio; + bool lockIntegerScaling; }; struct VideoShader {