diff options
author | Adrian Siekierka <kontakt@asie.pl> | 2021-10-02 20:16:27 +0200 |
---|---|---|
committer | GitHub <noreply@github.com> | 2021-10-02 20:16:27 +0200 |
commit | d378b0252f0f8ea7a97889e35320a49b9192affc (patch) | |
tree | 90b378c11ba35cc37d26cb75c919264e5704e018 | |
parent | b92622b765c6a94d050aaa16b6b30d59325fe495 (diff) |
Generate a simple non-bootable firmware when not provided. (v2) (#1175)
* Generate a simple non-bootable firmware when not provided.
* Expose Username and Language into settings dialog.
* Add firmware overrides for more settings. Also make override optionals when a firmware is provided.
* Refactor firmware settings into separate dialog.
* use usernameLength instead of u16Username.length() (#3)
* Fix curly braces code-style.
* LoadUserSettingsFromConfig: convert from UTF-8 to UTF-16 via wstring_convert
* Fix firmware username capitalization.
* cleanup firmware backup logic
* Put brace where it should be
Co-authored-by: Rayyan Ansari <68647953+RayyanAnsari@users.noreply.github.com>
Co-authored-by: Filippo Scognamiglio <flscogna@gmail.com>
Co-authored-by: kyandora <71771686+kyandora@users.noreply.github.com>
Co-authored-by: Filippo Scognamiglio <filippo.scognamiglio@felgo.com>
Co-authored-by: RSDuck <RSDuck@users.noreply.github.com>
Co-authored-by: Rayyan Ansari <68647953+RayyanAnsari@users.noreply.github.com>
-rw-r--r-- | src/Config.cpp | 16 | ||||
-rw-r--r-- | src/Config.h | 8 | ||||
-rw-r--r-- | src/SPI.cpp | 108 | ||||
-rw-r--r-- | src/frontend/Util_ROM.cpp | 2 | ||||
-rw-r--r-- | src/frontend/qt_sdl/CMakeLists.txt | 1 | ||||
-rw-r--r-- | src/frontend/qt_sdl/EmuSettingsDialog.cpp | 2 | ||||
-rw-r--r-- | src/frontend/qt_sdl/FirmwareSettingsDialog.cpp | 72 | ||||
-rw-r--r-- | src/frontend/qt_sdl/FirmwareSettingsDialog.h | 92 | ||||
-rw-r--r-- | src/frontend/qt_sdl/FirmwareSettingsDialog.ui | 144 | ||||
-rw-r--r-- | src/frontend/qt_sdl/main.cpp | 12 | ||||
-rw-r--r-- | src/frontend/qt_sdl/main.h | 3 |
11 files changed, 437 insertions, 23 deletions
diff --git a/src/Config.cpp b/src/Config.cpp index 9c5103a..67b2f24 100644 --- a/src/Config.cpp +++ b/src/Config.cpp @@ -35,6 +35,14 @@ char FirmwarePath[1024]; int DLDIEnable; char DLDISDPath[1024]; +char FirmwareUsername[64]; +int FirmwareLanguage; +bool FirmwareOverrideSettings; +int FirmwareBirthdayMonth; +int FirmwareBirthdayDay; +int FirmwareFavouriteColour; +char FirmwareMessage[1024]; + char DSiBIOS9Path[1024]; char DSiBIOS7Path[1024]; char DSiFirmwarePath[1024]; @@ -63,6 +71,14 @@ ConfigEntry ConfigFile[] = {"DLDIEnable", 0, &DLDIEnable, 0, NULL, 0}, {"DLDISDPath", 1, DLDISDPath, 0, "", 1023}, + {"FirmwareUsername", 1, FirmwareUsername, 0, "melonDS", 63}, + {"FirmwareLanguage", 0, &FirmwareLanguage, 1, NULL, 0}, + {"FirmwareOverrideSettings", 0, &FirmwareOverrideSettings, false, NULL, 0}, + {"FirmwareBirthdayMonth", 0, &FirmwareBirthdayMonth, 0, NULL, 0}, + {"FirmwareBirthdayDay", 0, &FirmwareBirthdayDay, 0, NULL, 0}, + {"FirmwareFavouriteColour", 0, &FirmwareFavouriteColour, 0, NULL, 0}, + {"FirmwareMessage", 1, FirmwareMessage, 0, "", 1023}, + {"DSiBIOS9Path", 1, DSiBIOS9Path, 0, "", 1023}, {"DSiBIOS7Path", 1, DSiBIOS7Path, 0, "", 1023}, {"DSiFirmwarePath", 1, DSiFirmwarePath, 0, "", 1023}, diff --git a/src/Config.h b/src/Config.h index 4dd0b06..bf7214e 100644 --- a/src/Config.h +++ b/src/Config.h @@ -48,6 +48,14 @@ extern char FirmwarePath[1024]; extern int DLDIEnable; extern char DLDISDPath[1024]; +extern char FirmwareUsername[64]; +extern int FirmwareLanguage; +extern bool FirmwareOverrideSettings; +extern int FirmwareBirthdayMonth; +extern int FirmwareBirthdayDay; +extern int FirmwareFavouriteColour; +extern char FirmwareMessage[1024]; + extern char DSiBIOS9Path[1024]; extern char DSiBIOS7Path[1024]; extern char DSiFirmwarePath[1024]; diff --git a/src/SPI.cpp b/src/SPI.cpp index 54444d9..2f990c0 100644 --- a/src/SPI.cpp +++ b/src/SPI.cpp @@ -19,6 +19,10 @@ #include <stdio.h> #include <string.h> #include <stdlib.h> +#include <string> +#include <algorithm> +#include <codecvt> +#include <locale> #include "Config.h" #include "NDS.h" #include "DSi.h" @@ -112,25 +116,25 @@ u32 FixFirmwareLength(u32 originalLength) return originalLength; } -void Reset() +void LoadDefaultFirmware() { - if (Firmware) delete[] Firmware; - Firmware = NULL; + FirmwareLength = 0x20000; + Firmware = new u8[FirmwareLength]; + memset(Firmware, 0xFF, FirmwareLength); + FirmwareMask = FirmwareLength - 1; - if (NDS::ConsoleType == 1) - strncpy(FirmwarePath, Config::DSiFirmwarePath, 1023); - else - strncpy(FirmwarePath, Config::FirmwarePath, 1023); + u32 userdata = 0x7FE00 & FirmwareMask; - FILE* f = Platform::OpenLocalFile(FirmwarePath, "rb"); - if (!f) - { - printf("Firmware not found\n"); + memset(Firmware + userdata, 0, 0x74); - // TODO: generate default firmware - return; - } + // user settings offset + *(u16*)&Firmware[0x20] = (FirmwareLength - 0x200) >> 3; + Firmware[userdata+0x00] = 5; // version +} + +void LoadFirmwareFromFile(FILE* f) +{ fseek(f, 0, SEEK_END); FirmwareLength = FixFirmwareLength((u32)ftell(f)); @@ -143,19 +147,76 @@ void Reset() fclose(f); // take a backup - char firmbkp[1028]; + char fwBackupPath[sizeof(FirmwarePath) + 4]; int fplen = strlen(FirmwarePath); - strncpy(&firmbkp[0], FirmwarePath, fplen); - strncpy(&firmbkp[fplen], ".bak", 1028-fplen); - firmbkp[fplen+4] = '\0'; - f = Platform::OpenLocalFile(firmbkp, "rb"); - if (f) fclose(f); + strcpy(&fwBackupPath[0], FirmwarePath); + strncpy(&fwBackupPath[fplen], ".bak", sizeof(fwBackupPath) - fplen); + fwBackupPath[fplen+4] = '\0'; + f = Platform::OpenLocalFile(fwBackupPath, "rb"); + if (!f) + { + f = Platform::OpenLocalFile(fwBackupPath, "wb"); + if (f) + { + fwrite(Firmware, 1, FirmwareLength, f); + fclose(f); + } + else + { + printf("Could not write firmware backup!\n"); + } + } else { - f = Platform::OpenLocalFile(firmbkp, "wb"); - fwrite(Firmware, 1, FirmwareLength, f); fclose(f); } +} + +void LoadUserSettingsFromConfig() +{ + // setting up username + std::u16string username = std::wstring_convert<std::codecvt_utf8_utf16<char16_t>, char16_t>{}.from_bytes(Config::FirmwareUsername); + size_t usernameLength = std::min(username.length(), (size_t) 10); + memcpy(Firmware + UserSettings + 0x06, username.data(), usernameLength * sizeof(char16_t)); + Firmware[UserSettings+0x1A] = usernameLength; + + // setting language + Firmware[UserSettings+0x64] = Config::FirmwareLanguage; + + // setting up color + Firmware[UserSettings+0x02] = Config::FirmwareFavouriteColour; + + // setting up birthday + Firmware[UserSettings+0x03] = Config::FirmwareBirthdayMonth; + Firmware[UserSettings+0x04] = Config::FirmwareBirthdayDay; + + // setup message + std::u16string message = std::wstring_convert<std::codecvt_utf8_utf16<char16_t>, char16_t>{}.from_bytes(Config::FirmwareMessage); + size_t messageLength = std::min(message.length(), (size_t) 26); + memcpy(Firmware + UserSettings + 0x1C, message.data(), messageLength * sizeof(char16_t)); + Firmware[UserSettings+0x50] = messageLength; +} + +void Reset() +{ + if (Firmware) delete[] Firmware; + Firmware = NULL; + + if (NDS::ConsoleType == 1) + strncpy(FirmwarePath, Config::DSiFirmwarePath, sizeof(FirmwarePath) - 1); + else + strncpy(FirmwarePath, Config::FirmwarePath, sizeof(FirmwarePath) - 1); + + FILE* f = Platform::OpenLocalFile(FirmwarePath, "rb"); + if (!f) + { + printf("Firmware not found! Generating default firmware.\n"); + LoadDefaultFirmware(); + } + else + { + LoadFirmwareFromFile(f); + } FirmwareMask = FirmwareLength - 1; @@ -168,6 +229,9 @@ void Reset() UserSettings = userdata; + if (!f || Config::FirmwareOverrideSettings) + LoadUserSettingsFromConfig(); + // fix touchscreen coords *(u16*)&Firmware[userdata+0x58] = 0; *(u16*)&Firmware[userdata+0x5A] = 0; diff --git a/src/frontend/Util_ROM.cpp b/src/frontend/Util_ROM.cpp index 4d55299..29247e4 100644 --- a/src/frontend/Util_ROM.cpp +++ b/src/frontend/Util_ROM.cpp @@ -165,7 +165,7 @@ int VerifyDSFirmware() long len; f = Platform::OpenLocalFile(Config::FirmwarePath, "rb"); - if (!f) return Load_FirmwareMissing; + if (!f) return Load_FirmwareNotBootable; fseek(f, 0, SEEK_END); len = ftell(f); diff --git a/src/frontend/qt_sdl/CMakeLists.txt b/src/frontend/qt_sdl/CMakeLists.txt index 61a2d20..cb81049 100644 --- a/src/frontend/qt_sdl/CMakeLists.txt +++ b/src/frontend/qt_sdl/CMakeLists.txt @@ -10,6 +10,7 @@ SET(SOURCES_QT_SDL InputConfig/resources/ds.qrc VideoSettingsDialog.cpp AudioSettingsDialog.cpp + FirmwareSettingsDialog.cpp WifiSettingsDialog.cpp InterfaceSettingsDialog.cpp ROMInfoDialog.cpp diff --git a/src/frontend/qt_sdl/EmuSettingsDialog.cpp b/src/frontend/qt_sdl/EmuSettingsDialog.cpp index b7de274..31e2e52 100644 --- a/src/frontend/qt_sdl/EmuSettingsDialog.cpp +++ b/src/frontend/qt_sdl/EmuSettingsDialog.cpp @@ -19,6 +19,8 @@ #include <stdio.h> #include <QFileDialog> #include <QMessageBox> +#include <QList> +#include <QDateEdit> #include "types.h" #include "Platform.h" diff --git a/src/frontend/qt_sdl/FirmwareSettingsDialog.cpp b/src/frontend/qt_sdl/FirmwareSettingsDialog.cpp new file mode 100644 index 0000000..7857cdc --- /dev/null +++ b/src/frontend/qt_sdl/FirmwareSettingsDialog.cpp @@ -0,0 +1,72 @@ +/* + Copyright 2016-2020 Arisotura + + This file is part of melonDS. + + melonDS is free software: you can redistribute it and/or modify it under + the terms of the GNU General Public License as published by the Free + Software Foundation, either version 3 of the License, or (at your option) + any later version. + + melonDS is distributed in the hope that it will be useful, but WITHOUT ANY + WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS + FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. + + You should have received a copy of the GNU General Public License along + with melonDS. If not, see http://www.gnu.org/licenses/. +*/ + +#include "Config.h" +#include "FirmwareSettingsDialog.h" +#include "ui_FirmwareSettingsDialog.h" + +FirmwareSettingsDialog* FirmwareSettingsDialog::currentDlg = nullptr; + +FirmwareSettingsDialog::FirmwareSettingsDialog(QWidget* parent) : QDialog(parent), ui(new Ui::FirmwareSettingsDialog) +{ + ui->setupUi(this); + setAttribute(Qt::WA_DeleteOnClose); + + ui->usernameEdit->setText(Config::FirmwareUsername); + + ui->languageBox->addItems(languages); + ui->languageBox->setCurrentIndex(Config::FirmwareLanguage); + + QDate birthDate = QDate(QDate::currentDate().year(), Config::FirmwareBirthdayMonth, Config::FirmwareBirthdayDay); + ui->birthdayEdit->setDate(birthDate); + + ui->colorsEdit->addItems(colours); + ui->colorsEdit->setCurrentIndex(Config::FirmwareFavouriteColour); + + ui->messageEdit->setText(Config::FirmwareMessage); + + ui->overrideFirmwareBox->setChecked(Config::FirmwareOverrideSettings); +} + +FirmwareSettingsDialog::~FirmwareSettingsDialog() +{ + delete ui; +} + +void FirmwareSettingsDialog::on_dialogButtons_accepted() +{ + std::string newName = ui->usernameEdit->text().toStdString(); + strncpy(Config::FirmwareUsername, newName.c_str(), 63); Config::FirmwareUsername[63] = '\0'; + + Config::FirmwareLanguage = ui->languageBox->currentIndex(); + Config::FirmwareFavouriteColour = ui->colorsEdit->currentIndex(); + Config::FirmwareBirthdayDay = ui->birthdayEdit->date().day(); + Config::FirmwareBirthdayMonth = ui->birthdayEdit->date().month(); + Config::FirmwareOverrideSettings = ui->overrideFirmwareBox->isChecked(); + + std::string newMessage = ui->messageEdit->text().toStdString(); + strncpy(Config::FirmwareMessage, newMessage.c_str(), 1023); Config::FirmwareMessage[1023] = '\0'; + Config::Save(); + + closeDlg(); +} + +void FirmwareSettingsDialog::on_dialogButtons_rejected() +{ + closeDlg(); +} diff --git a/src/frontend/qt_sdl/FirmwareSettingsDialog.h b/src/frontend/qt_sdl/FirmwareSettingsDialog.h new file mode 100644 index 0000000..5f8e5ff --- /dev/null +++ b/src/frontend/qt_sdl/FirmwareSettingsDialog.h @@ -0,0 +1,92 @@ +/* + Copyright 2016-2020 Arisotura + + This file is part of melonDS. + + melonDS is free software: you can redistribute it and/or modify it under + the terms of the GNU General Public License as published by the Free + Software Foundation, either version 3 of the License, or (at your option) + any later version. + + melonDS is distributed in the hope that it will be useful, but WITHOUT ANY + WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS + FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. + + You should have received a copy of the GNU General Public License along + with melonDS. If not, see http://www.gnu.org/licenses/. +*/ + +#ifndef FIRMWARESETTINGSDIALOG_H +#define FIRMWARESETTINGSDIALOG_H + +#include <QDialog> +#include <QWidget> + +namespace Ui { class FirmwareSettingsDialog; } +class FirmwareSettingsDialog; + +class FirmwareSettingsDialog : public QDialog +{ + Q_OBJECT + +public: + const QStringList colours + { + "Greyish Blue", + "Brown", + "Red", + "Light Pink", + "Orange", + "Yellow", + "Lime", + "Light Green", + "Dark Green", + "Turqoise", + "Light Blue", + "Blue", + "Dark Blue", + "Dark Purple", + "Light Purple", + "Dark Pink" + }; + + const QStringList languages + { + "Japanese", + "English", + "French", + "German", + "Italian", + "Spanish" + }; + + explicit FirmwareSettingsDialog(QWidget* parent); + ~FirmwareSettingsDialog(); + + static FirmwareSettingsDialog* currentDlg; + static FirmwareSettingsDialog* openDlg(QWidget* parent) + { + if (currentDlg) + { + currentDlg->activateWindow(); + return currentDlg; + } + + currentDlg = new FirmwareSettingsDialog(parent); + currentDlg->show(); + return currentDlg; + } + static void closeDlg() + { + currentDlg = nullptr; + } + +private slots: + void on_dialogButtons_accepted(); + void on_dialogButtons_rejected(); + +private: + Ui::FirmwareSettingsDialog* ui; +}; + +#endif // FIRMWARESETTINGSDIALOG_H diff --git a/src/frontend/qt_sdl/FirmwareSettingsDialog.ui b/src/frontend/qt_sdl/FirmwareSettingsDialog.ui new file mode 100644 index 0000000..2e27946 --- /dev/null +++ b/src/frontend/qt_sdl/FirmwareSettingsDialog.ui @@ -0,0 +1,144 @@ +<?xml version="1.0" encoding="UTF-8"?> +<ui version="4.0"> + <class>FirmwareSettingsDialog</class> + <widget class="QDialog" name="FirmwareSettingsDialog"> + <property name="geometry"> + <rect> + <x>0</x> + <y>0</y> + <width>511</width> + <height>272</height> + </rect> + </property> + <property name="sizePolicy"> + <sizepolicy hsizetype="Fixed" vsizetype="Fixed"> + <horstretch>0</horstretch> + <verstretch>0</verstretch> + </sizepolicy> + </property> + <property name="windowTitle"> + <string>Firmware settings - melonDS</string> + </property> + <layout class="QVBoxLayout" name="verticalLayout"> + <property name="sizeConstraint"> + <enum>QLayout::SetFixedSize</enum> + </property> + <item> + <layout class="QFormLayout" name="formLayout"> + <item row="0" column="0"> + <widget class="QLabel" name="usernameLabel"> + <property name="text"> + <string>Username</string> + </property> + </widget> + </item> + <item row="0" column="1"> + <widget class="QLineEdit" name="usernameEdit"> + <property name="text"> + <string>MelonDS</string> + </property> + <property name="maxLength"> + <number>10</number> + </property> + <property name="clearButtonEnabled"> + <bool>false</bool> + </property> + </widget> + </item> + <item row="1" column="0"> + <widget class="QLabel" name="label"> + <property name="text"> + <string>Language</string> + </property> + </widget> + </item> + <item row="1" column="1"> + <widget class="QComboBox" name="languageBox"/> + </item> + <item row="2" column="0"> + <widget class="QLabel" name="label_4"> + <property name="text"> + <string>Birthday</string> + </property> + </widget> + </item> + <item row="2" column="1"> + <widget class="QDateEdit" name="birthdayEdit"/> + </item> + <item row="3" column="0"> + <widget class="QLabel" name="label_2"> + <property name="text"> + <string>Color</string> + </property> + </widget> + </item> + <item row="3" column="1"> + <widget class="QComboBox" name="colorsEdit"/> + </item> + <item row="4" column="0"> + <widget class="QLabel" name="label_3"> + <property name="text"> + <string>Message</string> + </property> + </widget> + </item> + <item row="4" column="1"> + <widget class="QLineEdit" name="messageEdit"/> + </item> + <item row="5" column="0" colspan="2"> + <widget class="QCheckBox" name="overrideFirmwareBox"> + <property name="text"> + <string>Override firmware settings</string> + </property> + </widget> + </item> + </layout> + </item> + <item> + <widget class="QDialogButtonBox" name="dialogButtons"> + <property name="orientation"> + <enum>Qt::Horizontal</enum> + </property> + <property name="standardButtons"> + <set>QDialogButtonBox::Cancel|QDialogButtonBox::Ok</set> + </property> + </widget> + </item> + </layout> + </widget> + <resources/> + <connections> + <connection> + <sender>dialogButtons</sender> + <signal>accepted()</signal> + <receiver>FirmwareSettingsDialog</receiver> + <slot>accept()</slot> + <hints> + <hint type="sourcelabel"> + <x>255</x> + <y>250</y> + </hint> + <hint type="destinationlabel"> + <x>255</x> + <y>135</y> + </hint> + </hints> + </connection> + <connection> + <sender>dialogButtons</sender> + <signal>rejected()</signal> + <receiver>FirmwareSettingsDialog</receiver> + <slot>reject()</slot> + <hints> + <hint type="sourcelabel"> + <x>255</x> + <y>250</y> + </hint> + <hint type="destinationlabel"> + <x>255</x> + <y>135</y> + </hint> + </hints> + </connection> + </connections> +</ui> diff --git a/src/frontend/qt_sdl/main.cpp b/src/frontend/qt_sdl/main.cpp index d6acc91..fb1caea 100644 --- a/src/frontend/qt_sdl/main.cpp +++ b/src/frontend/qt_sdl/main.cpp @@ -55,6 +55,7 @@ #include "InputConfig/InputConfigDialog.h" #include "VideoSettingsDialog.h" #include "AudioSettingsDialog.h" +#include "FirmwareSettingsDialog.h" #include "WifiSettingsDialog.h" #include "InterfaceSettingsDialog.h" #include "ROMInfoDialog.h" @@ -1411,6 +1412,9 @@ MainWindow::MainWindow(QWidget* parent) : QMainWindow(parent) actInterfaceSettings = menu->addAction("Interface settings"); connect(actInterfaceSettings, &QAction::triggered, this, &MainWindow::onOpenInterfaceSettings); + actFirmwareSettings = menu->addAction("Firmware settings"); + connect(actFirmwareSettings, &QAction::triggered, this, &MainWindow::onOpenFirmwareSettings); + { QMenu* submenu = menu->addMenu("Savestate settings"); @@ -2446,6 +2450,14 @@ void MainWindow::onOpenAudioSettings() connect(dlg, &AudioSettingsDialog::finished, this, &MainWindow::onAudioSettingsFinished); } +void MainWindow::onOpenFirmwareSettings() +{ + FirmwareSettingsDialog* dlg = FirmwareSettingsDialog::openDlg(this); + connect(dlg, &FirmwareSettingsDialog::finished, this, &MainWindow::onFirmwareSettingsFinished); +} + +void MainWindow::onFirmwareSettingsFinished(int res) {} + void MainWindow::onUpdateAudioSettings() { SPU::SetInterpolation(Config::AudioInterp); diff --git a/src/frontend/qt_sdl/main.h b/src/frontend/qt_sdl/main.h index 1378417..0f9034f 100644 --- a/src/frontend/qt_sdl/main.h +++ b/src/frontend/qt_sdl/main.h @@ -256,10 +256,12 @@ private slots: void onInputConfigFinished(int res); void onOpenVideoSettings(); void onOpenAudioSettings(); + void onOpenFirmwareSettings(); void onUpdateAudioSettings(); void onAudioSettingsFinished(int res); void onOpenWifiSettings(); void onWifiSettingsFinished(int res); + void onFirmwareSettingsFinished(int res); void onOpenInterfaceSettings(); void onInterfaceSettingsFinished(int res); void onUpdateMouseTimer(); @@ -331,6 +333,7 @@ public: QAction* actVideoSettings; QAction* actAudioSettings; QAction* actWifiSettings; + QAction* actFirmwareSettings; QAction* actInterfaceSettings; QAction* actSavestateSRAMReloc; QAction* actScreenSize[4]; |