mirror of
https://github.com/melonDS-emu/melonDS.git
synced 2025-07-25 15:19:53 -06:00
DSi power button and volume switch support (#1630)
* Add proper BPTWL interrupts * Added DSi power button and volume switch hotkeys * Added hardware reset workaround * Adjusted syntax to follow guidelines * Added DSi output volume synchronization * Fix trivial member function error
This commit is contained in:
@ -22,6 +22,8 @@
|
||||
#include "types.h"
|
||||
#include "Platform.h"
|
||||
#include "Config.h"
|
||||
#include "NDS.h"
|
||||
#include "DSi_I2C.h"
|
||||
|
||||
#include "AudioSettingsDialog.h"
|
||||
#include "ui_AudioSettingsDialog.h"
|
||||
@ -32,7 +34,7 @@ AudioSettingsDialog* AudioSettingsDialog::currentDlg = nullptr;
|
||||
extern std::string EmuDirectory;
|
||||
|
||||
|
||||
AudioSettingsDialog::AudioSettingsDialog(QWidget* parent) : QDialog(parent), ui(new Ui::AudioSettingsDialog)
|
||||
AudioSettingsDialog::AudioSettingsDialog(QWidget* parent, bool emuActive) : QDialog(parent), ui(new Ui::AudioSettingsDialog)
|
||||
{
|
||||
ui->setupUi(this);
|
||||
setAttribute(Qt::WA_DeleteOnClose);
|
||||
@ -40,6 +42,7 @@ AudioSettingsDialog::AudioSettingsDialog(QWidget* parent) : QDialog(parent), ui(
|
||||
oldInterp = Config::AudioInterp;
|
||||
oldBitrate = Config::AudioBitrate;
|
||||
oldVolume = Config::AudioVolume;
|
||||
oldDSiSync = Config::DSiVolumeSync;
|
||||
|
||||
ui->cbInterpolation->addItem("None");
|
||||
ui->cbInterpolation->addItem("Linear");
|
||||
@ -52,7 +55,21 @@ AudioSettingsDialog::AudioSettingsDialog(QWidget* parent) : QDialog(parent), ui(
|
||||
ui->cbBitrate->addItem("16-bit");
|
||||
ui->cbBitrate->setCurrentIndex(Config::AudioBitrate);
|
||||
|
||||
bool state = ui->slVolume->blockSignals(true);
|
||||
ui->slVolume->setValue(Config::AudioVolume);
|
||||
ui->slVolume->blockSignals(state);
|
||||
|
||||
ui->chkSyncDSiVolume->setChecked(Config::DSiVolumeSync);
|
||||
|
||||
// Setup volume slider accordingly
|
||||
if (emuActive && NDS::ConsoleType == 1)
|
||||
{
|
||||
on_chkSyncDSiVolume_clicked(Config::DSiVolumeSync);
|
||||
}
|
||||
else
|
||||
{
|
||||
ui->chkSyncDSiVolume->setEnabled(false);
|
||||
}
|
||||
|
||||
grpMicMode = new QButtonGroup(this);
|
||||
grpMicMode->addButton(ui->rbMicNone, 0);
|
||||
@ -88,6 +105,22 @@ AudioSettingsDialog::~AudioSettingsDialog()
|
||||
delete ui;
|
||||
}
|
||||
|
||||
void AudioSettingsDialog::onSyncVolumeLevel()
|
||||
{
|
||||
if (Config::DSiVolumeSync && NDS::ConsoleType == 1)
|
||||
{
|
||||
bool state = ui->slVolume->blockSignals(true);
|
||||
ui->slVolume->setValue(DSi_BPTWL::GetVolumeLevel());
|
||||
ui->slVolume->blockSignals(state);
|
||||
}
|
||||
}
|
||||
|
||||
void AudioSettingsDialog::onConsoleReset()
|
||||
{
|
||||
on_chkSyncDSiVolume_clicked(Config::DSiVolumeSync);
|
||||
ui->chkSyncDSiVolume->setEnabled(NDS::ConsoleType == 1);
|
||||
}
|
||||
|
||||
void AudioSettingsDialog::on_AudioSettingsDialog_accepted()
|
||||
{
|
||||
Config::MicInputType = grpMicMode->checkedId();
|
||||
@ -102,6 +135,7 @@ void AudioSettingsDialog::on_AudioSettingsDialog_rejected()
|
||||
Config::AudioInterp = oldInterp;
|
||||
Config::AudioBitrate = oldBitrate;
|
||||
Config::AudioVolume = oldVolume;
|
||||
Config::DSiVolumeSync = oldDSiSync;
|
||||
|
||||
closeDlg();
|
||||
}
|
||||
@ -128,9 +162,38 @@ void AudioSettingsDialog::on_cbInterpolation_currentIndexChanged(int idx)
|
||||
|
||||
void AudioSettingsDialog::on_slVolume_valueChanged(int val)
|
||||
{
|
||||
if (Config::DSiVolumeSync && NDS::ConsoleType == 1)
|
||||
{
|
||||
DSi_BPTWL::SetVolumeLevel(val);
|
||||
return;
|
||||
}
|
||||
|
||||
Config::AudioVolume = val;
|
||||
}
|
||||
|
||||
void AudioSettingsDialog::on_chkSyncDSiVolume_clicked(bool checked)
|
||||
{
|
||||
Config::DSiVolumeSync = checked;
|
||||
|
||||
bool state = ui->slVolume->blockSignals(true);
|
||||
if (Config::DSiVolumeSync && NDS::ConsoleType == 1)
|
||||
{
|
||||
ui->slVolume->setMaximum(31);
|
||||
ui->slVolume->setValue(DSi_BPTWL::GetVolumeLevel());
|
||||
ui->slVolume->setPageStep(4);
|
||||
ui->slVolume->setTickPosition(QSlider::TicksBelow);
|
||||
}
|
||||
else
|
||||
{
|
||||
Config::AudioVolume = oldVolume;
|
||||
ui->slVolume->setMaximum(256);
|
||||
ui->slVolume->setValue(Config::AudioVolume);
|
||||
ui->slVolume->setPageStep(16);
|
||||
ui->slVolume->setTickPosition(QSlider::NoTicks);
|
||||
}
|
||||
ui->slVolume->blockSignals(state);
|
||||
}
|
||||
|
||||
void AudioSettingsDialog::onChangeMicMode(int mode)
|
||||
{
|
||||
bool iswav = (mode == 3);
|
||||
|
@ -30,11 +30,11 @@ class AudioSettingsDialog : public QDialog
|
||||
Q_OBJECT
|
||||
|
||||
public:
|
||||
explicit AudioSettingsDialog(QWidget* parent);
|
||||
explicit AudioSettingsDialog(QWidget* parent, bool emuActive);
|
||||
~AudioSettingsDialog();
|
||||
|
||||
static AudioSettingsDialog* currentDlg;
|
||||
static AudioSettingsDialog* openDlg(QWidget* parent)
|
||||
static AudioSettingsDialog* openDlg(QWidget* parent, bool emuActive)
|
||||
{
|
||||
if (currentDlg)
|
||||
{
|
||||
@ -42,7 +42,7 @@ public:
|
||||
return currentDlg;
|
||||
}
|
||||
|
||||
currentDlg = new AudioSettingsDialog(parent);
|
||||
currentDlg = new AudioSettingsDialog(parent, emuActive);
|
||||
currentDlg->show();
|
||||
return currentDlg;
|
||||
}
|
||||
@ -51,6 +51,9 @@ public:
|
||||
currentDlg = nullptr;
|
||||
}
|
||||
|
||||
void onSyncVolumeLevel();
|
||||
void onConsoleReset();
|
||||
|
||||
signals:
|
||||
void updateAudioSettings();
|
||||
|
||||
@ -61,6 +64,7 @@ private slots:
|
||||
void on_cbInterpolation_currentIndexChanged(int idx);
|
||||
void on_cbBitrate_currentIndexChanged(int idx);
|
||||
void on_slVolume_valueChanged(int val);
|
||||
void on_chkSyncDSiVolume_clicked(bool checked);
|
||||
void onChangeMicMode(int mode);
|
||||
void on_btnMicWavBrowse_clicked();
|
||||
|
||||
@ -70,6 +74,7 @@ private:
|
||||
int oldInterp;
|
||||
int oldBitrate;
|
||||
int oldVolume;
|
||||
bool oldDSiSync;
|
||||
QButtonGroup* grpMicMode;
|
||||
};
|
||||
|
||||
|
@ -59,6 +59,16 @@
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item row="3" column="1">
|
||||
<widget class="QCheckBox" name="chkSyncDSiVolume">
|
||||
<property name="whatsThis">
|
||||
<string><html><head/><body><p>Synchronizes the output volume with the DSi hardware volume.</p></body></html></string>
|
||||
</property>
|
||||
<property name="text">
|
||||
<string>Sync with DSi volume</string>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item row="0" column="0">
|
||||
<widget class="QLabel" name="label_2">
|
||||
<property name="text">
|
||||
|
@ -118,6 +118,7 @@ bool SavestateRelocSRAM;
|
||||
int AudioInterp;
|
||||
int AudioBitrate;
|
||||
int AudioVolume;
|
||||
bool DSiVolumeSync;
|
||||
int MicInputType;
|
||||
std::string MicWavPath;
|
||||
|
||||
@ -187,6 +188,9 @@ ConfigEntry ConfigFile[] =
|
||||
{"HKKey_SolarSensorDecrease", 0, &HKKeyMapping[HK_SolarSensorDecrease], -1, true},
|
||||
{"HKKey_SolarSensorIncrease", 0, &HKKeyMapping[HK_SolarSensorIncrease], -1, true},
|
||||
{"HKKey_FrameStep", 0, &HKKeyMapping[HK_FrameStep], -1, true},
|
||||
{"HKKey_PowerButton", 0, &HKKeyMapping[HK_PowerButton], -1, true},
|
||||
{"HKKey_VolumeUp", 0, &HKKeyMapping[HK_VolumeUp], -1, true},
|
||||
{"HKKey_VolumeDown", 0, &HKKeyMapping[HK_VolumeDown], -1, true},
|
||||
|
||||
{"HKJoy_Lid", 0, &HKJoyMapping[HK_Lid], -1, true},
|
||||
{"HKJoy_Mic", 0, &HKJoyMapping[HK_Mic], -1, true},
|
||||
@ -200,6 +204,9 @@ ConfigEntry ConfigFile[] =
|
||||
{"HKJoy_SolarSensorDecrease", 0, &HKJoyMapping[HK_SolarSensorDecrease], -1, true},
|
||||
{"HKJoy_SolarSensorIncrease", 0, &HKJoyMapping[HK_SolarSensorIncrease], -1, true},
|
||||
{"HKJoy_FrameStep", 0, &HKJoyMapping[HK_FrameStep], -1, true},
|
||||
{"HKJoy_PowerButton", 0, &HKJoyMapping[HK_PowerButton], -1, true},
|
||||
{"HKJoy_VolumeUp", 0, &HKJoyMapping[HK_VolumeUp], -1, true},
|
||||
{"HKJoy_VolumeDown", 0, &HKJoyMapping[HK_VolumeDown], -1, true},
|
||||
|
||||
{"JoystickID", 0, &JoystickID, 0, true},
|
||||
|
||||
@ -291,6 +298,7 @@ ConfigEntry ConfigFile[] =
|
||||
{"AudioInterp", 0, &AudioInterp, 0, false},
|
||||
{"AudioBitrate", 0, &AudioBitrate, 0, false},
|
||||
{"AudioVolume", 0, &AudioVolume, 256, true},
|
||||
{"DSiVolumeSync", 0, &DSiVolumeSync, 0, true},
|
||||
{"MicInputType", 0, &MicInputType, 1, false},
|
||||
{"MicWavPath", 2, &MicWavPath, (std::string)"", false},
|
||||
|
||||
|
@ -36,6 +36,9 @@ enum
|
||||
HK_SolarSensorDecrease,
|
||||
HK_SolarSensorIncrease,
|
||||
HK_FrameStep,
|
||||
HK_PowerButton,
|
||||
HK_VolumeUp,
|
||||
HK_VolumeDown,
|
||||
HK_MAX
|
||||
};
|
||||
|
||||
@ -163,6 +166,7 @@ extern bool SavestateRelocSRAM;
|
||||
extern int AudioInterp;
|
||||
extern int AudioBitrate;
|
||||
extern int AudioVolume;
|
||||
extern bool DSiVolumeSync;
|
||||
extern int MicInputType;
|
||||
extern std::string MicWavPath;
|
||||
|
||||
|
@ -52,7 +52,10 @@ static constexpr std::initializer_list<int> hk_general =
|
||||
HK_Lid,
|
||||
HK_Mic,
|
||||
HK_SwapScreens,
|
||||
HK_SwapScreenEmphasis
|
||||
HK_SwapScreenEmphasis,
|
||||
HK_PowerButton,
|
||||
HK_VolumeUp,
|
||||
HK_VolumeDown
|
||||
};
|
||||
|
||||
static constexpr std::initializer_list<const char*> hk_general_labels =
|
||||
@ -66,7 +69,10 @@ static constexpr std::initializer_list<const char*> hk_general_labels =
|
||||
"Close/open lid",
|
||||
"Microphone",
|
||||
"Swap screens",
|
||||
"Swap screen emphasis"
|
||||
"Swap screen emphasis",
|
||||
"DSi Power button",
|
||||
"DSi Volume up",
|
||||
"DSi Volume down"
|
||||
};
|
||||
|
||||
static_assert(hk_general.size() == hk_general_labels.size());
|
||||
|
@ -88,6 +88,7 @@
|
||||
#include "Platform.h"
|
||||
#include "LocalMP.h"
|
||||
#include "Config.h"
|
||||
#include "DSi_I2C.h"
|
||||
|
||||
#include "Savestate.h"
|
||||
|
||||
@ -581,6 +582,7 @@ void EmuThread::run()
|
||||
double lastMeasureTime = lastTime;
|
||||
|
||||
u32 winUpdateCount = 0, winUpdateFreq = 1;
|
||||
u8 dsiVolumeLevel = 0x1F;
|
||||
|
||||
char melontitle[100];
|
||||
|
||||
@ -620,6 +622,42 @@ void EmuThread::run()
|
||||
}
|
||||
}
|
||||
|
||||
if (NDS::ConsoleType == 1)
|
||||
{
|
||||
double currentTime = SDL_GetPerformanceCounter() * perfCountsSec;
|
||||
|
||||
// Handle power button
|
||||
if (Input::HotkeyDown(HK_PowerButton))
|
||||
{
|
||||
DSi_BPTWL::SetPowerButtonHeld(currentTime);
|
||||
}
|
||||
else if (Input::HotkeyReleased(HK_PowerButton))
|
||||
{
|
||||
DSi_BPTWL::SetPowerButtonReleased(currentTime);
|
||||
}
|
||||
|
||||
// Handle volume buttons
|
||||
if (Input::HotkeyDown(HK_VolumeUp))
|
||||
{
|
||||
DSi_BPTWL::SetVolumeSwitchHeld(DSi_BPTWL::volumeKey_Up);
|
||||
}
|
||||
else if (Input::HotkeyReleased(HK_VolumeUp))
|
||||
{
|
||||
DSi_BPTWL::SetVolumeSwitchReleased(DSi_BPTWL::volumeKey_Up);
|
||||
}
|
||||
|
||||
if (Input::HotkeyDown(HK_VolumeDown))
|
||||
{
|
||||
DSi_BPTWL::SetVolumeSwitchHeld(DSi_BPTWL::volumeKey_Down);
|
||||
}
|
||||
else if (Input::HotkeyReleased(HK_VolumeDown))
|
||||
{
|
||||
DSi_BPTWL::SetVolumeSwitchReleased(DSi_BPTWL::volumeKey_Down);
|
||||
}
|
||||
|
||||
DSi_BPTWL::ProcessVolumeSwitchInput(currentTime);
|
||||
}
|
||||
|
||||
if (EmuRunning == 1 || EmuRunning == 3)
|
||||
{
|
||||
EmuStatus = 1;
|
||||
@ -739,6 +777,18 @@ void EmuThread::run()
|
||||
oglContext->SetSwapInterval(0);
|
||||
}
|
||||
|
||||
if (Config::DSiVolumeSync && NDS::ConsoleType == 1)
|
||||
{
|
||||
u8 volumeLevel = DSi_BPTWL::GetVolumeLevel();
|
||||
if (volumeLevel != dsiVolumeLevel)
|
||||
{
|
||||
dsiVolumeLevel = volumeLevel;
|
||||
emit syncVolumeLevel();
|
||||
}
|
||||
|
||||
Config::AudioVolume = volumeLevel * (256.0 / 31.0);
|
||||
}
|
||||
|
||||
if (Config::AudioSync && !fastforward && audioDevice)
|
||||
{
|
||||
SDL_LockMutex(audioSyncLock);
|
||||
@ -2583,7 +2633,7 @@ void MainWindow::onBootFirmware()
|
||||
}
|
||||
|
||||
if (!ROMManager::LoadBIOS())
|
||||
{
|
||||
{
|
||||
// TODO: better error reporting?
|
||||
QMessageBox::critical(this, "melonDS", "This firmware is not bootable.");
|
||||
emuThread->emuUnpause();
|
||||
@ -3027,7 +3077,9 @@ void MainWindow::onCameraSettingsFinished(int res)
|
||||
|
||||
void MainWindow::onOpenAudioSettings()
|
||||
{
|
||||
AudioSettingsDialog* dlg = AudioSettingsDialog::openDlg(this);
|
||||
AudioSettingsDialog* dlg = AudioSettingsDialog::openDlg(this, emuThread->emuIsActive());
|
||||
connect(emuThread, &EmuThread::syncVolumeLevel, dlg, &AudioSettingsDialog::onSyncVolumeLevel);
|
||||
connect(emuThread, &EmuThread::windowEmuStart, dlg, &AudioSettingsDialog::onConsoleReset);
|
||||
connect(dlg, &AudioSettingsDialog::updateAudioSettings, this, &MainWindow::onUpdateAudioSettings);
|
||||
connect(dlg, &AudioSettingsDialog::finished, this, &MainWindow::onAudioSettingsFinished);
|
||||
}
|
||||
@ -3270,7 +3322,8 @@ void MainWindow::onTitleUpdate(QString title)
|
||||
setWindowTitle(title);
|
||||
}
|
||||
|
||||
void ToggleFullscreen(MainWindow* mainWindow) {
|
||||
void ToggleFullscreen(MainWindow* mainWindow)
|
||||
{
|
||||
if (!mainWindow->isFullScreen())
|
||||
{
|
||||
mainWindow->showFullScreen();
|
||||
@ -3289,11 +3342,15 @@ void MainWindow::onFullscreenToggled()
|
||||
ToggleFullscreen(this);
|
||||
}
|
||||
|
||||
void MainWindow::onScreenEmphasisToggled() {
|
||||
void MainWindow::onScreenEmphasisToggled()
|
||||
{
|
||||
int currentSizing = Config::ScreenSizing;
|
||||
if (currentSizing == screenSizing_EmphTop) {
|
||||
if (currentSizing == screenSizing_EmphTop)
|
||||
{
|
||||
Config::ScreenSizing = screenSizing_EmphBot;
|
||||
} else if (currentSizing == screenSizing_EmphBot) {
|
||||
}
|
||||
else if (currentSizing == screenSizing_EmphBot)
|
||||
{
|
||||
Config::ScreenSizing = screenSizing_EmphTop;
|
||||
}
|
||||
|
||||
@ -3436,7 +3493,7 @@ int main(int argc, char** argv)
|
||||
}
|
||||
|
||||
SDL_JoystickEventState(SDL_ENABLE);
|
||||
|
||||
|
||||
SDL_InitSubSystem(SDL_INIT_VIDEO);
|
||||
SDL_EnableScreenSaver(); SDL_DisableScreenSaver();
|
||||
|
||||
|
@ -87,6 +87,8 @@ signals:
|
||||
void swapScreensToggle();
|
||||
void screenEmphasisToggle();
|
||||
|
||||
void syncVolumeLevel();
|
||||
|
||||
private:
|
||||
void drawScreenGL();
|
||||
void initOpenGL();
|
||||
|
Reference in New Issue
Block a user