aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorWaluigiWare64 <68647953+WaluigiWare64@users.noreply.github.com>2021-07-02 17:42:54 +0100
committerGitHub <noreply@github.com>2021-07-02 16:42:54 +0000
commite5240a688c54d07dd6d6b4994a920137d15bbad3 (patch)
tree267691a34b04fb8b121c4df6cbccb9f8d45fa05c
parent5a071c4c29c7d8943c5588e3198564d033a73acb (diff)
Add ROM Header struct and ROM info dialog (#1095)
-rw-r--r--src/NDSCart.cpp24
-rw-r--r--src/NDSCart.h4
-rw-r--r--src/NDS_Header.h119
-rw-r--r--src/frontend/FrontendUtil.h5
-rw-r--r--src/frontend/Util_ROM.cpp68
-rw-r--r--src/frontend/qt_sdl/CMakeLists.txt1
-rw-r--r--src/frontend/qt_sdl/ROMInfoDialog.cpp145
-rw-r--r--src/frontend/qt_sdl/ROMInfoDialog.h75
-rw-r--r--src/frontend/qt_sdl/ROMInfoDialog.ui831
-rw-r--r--src/frontend/qt_sdl/main.cpp17
-rw-r--r--src/frontend/qt_sdl/main.h2
11 files changed, 1284 insertions, 7 deletions
diff --git a/src/NDSCart.cpp b/src/NDSCart.cpp
index 96cbaa3..65bed2b 100644
--- a/src/NDSCart.cpp
+++ b/src/NDSCart.cpp
@@ -58,6 +58,9 @@ u32 CartID;
bool CartIsHomebrew;
bool CartIsDSi;
+NDSHeader Header;
+NDSBanner Banner;
+
CartCommon* Cart;
u32 Key1_KeyBuf[0x412];
@@ -1498,8 +1501,11 @@ void DecryptSecureArea(u8* out)
// * .srl ROMs (VC dumps) have encrypted secure areas but have precomputed
// decryption data at 0x1000 (and at the beginning of the DSi region if any)
- u32 gamecode = *(u32*)&CartROM[0x0C];
- u32 arm9base = *(u32*)&CartROM[0x20];
+ u32 gamecode = (u32)Header.GameCode[3] << 24 |
+ (u32)Header.GameCode[2] << 16 |
+ (u32)Header.GameCode[1] << 8 |
+ (u32)Header.GameCode[0];
+ u32 arm9base = Header.ARM9ROMOffset;
memcpy(out, &CartROM[arm9base], 0x800);
@@ -1526,11 +1532,17 @@ void DecryptSecureArea(u8* out)
bool LoadROMCommon(u32 filelength, const char *sram, bool direct)
{
- u32 gamecode;
- memcpy(&gamecode, CartROM + 0x0C, 4);
- printf("Game code: %c%c%c%c\n", gamecode&0xFF, (gamecode>>8)&0xFF, (gamecode>>16)&0xFF, gamecode>>24);
+ memcpy(&Header, CartROM, sizeof(Header));
+ memcpy(&Banner, CartROM + Header.BannerOffset, sizeof(Banner));
+
+ printf("Game code: %.4s\n", Header.GameCode);
+
+ u32 gamecode = (u32)Header.GameCode[3] << 24 |
+ (u32)Header.GameCode[2] << 16 |
+ (u32)Header.GameCode[1] << 8 |
+ (u32)Header.GameCode[0];
- u8 unitcode = CartROM[0x12];
+ u8 unitcode = Header.UnitCode;
CartIsDSi = (unitcode & 0x02) != 0;
ROMListEntry romparams;
diff --git a/src/NDSCart.h b/src/NDSCart.h
index 0345297..cb7f1e2 100644
--- a/src/NDSCart.h
+++ b/src/NDSCart.h
@@ -20,6 +20,7 @@
#define NDSCART_H
#include "types.h"
+#include "NDS_Header.h"
namespace NDSCart
{
@@ -191,6 +192,9 @@ extern u32 CartROMSize;
extern u32 CartID;
+extern NDSHeader Header;
+extern NDSBanner Banner;
+
bool Init();
void DeInit();
void Reset();
diff --git a/src/NDS_Header.h b/src/NDS_Header.h
new file mode 100644
index 0000000..d2e70fa
--- /dev/null
+++ b/src/NDS_Header.h
@@ -0,0 +1,119 @@
+/*
+ Copyright 2016-2021 Arisotura, WaluigiWare64
+
+ 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 NDS_HEADER_H
+#define NDS_HEADER_H
+
+#include "types.h"
+
+// Consult GBATEK for info on what these are
+struct NDSHeader
+{
+ char GameTitle[12];
+ char GameCode[4];
+ char MakerCode[2];
+ u8 UnitCode;
+ u8 EncryptionSeedSelect;
+ u8 CardSize;
+ u8 Reserved1[8];
+ u8 NDSRegion;
+ u8 ROMVersion;
+ u8 Autostart;
+
+ u32 ARM9ROMOffset;
+ u32 ARM9EntryAddress;
+ u32 ARM9RAMAddress;
+ u32 ARM9Size;
+
+ u32 ARM7ROMOffset;
+ u32 ARM7EntryAddress;
+ u32 ARM7RAMAddress;
+ u32 ARM7Size;
+
+ u32 FNTOffset;
+ u32 FNTSize;
+ u32 FATOffset;
+ u32 FATSize;
+
+ u32 ARM9OverlayOffset;
+ u32 ARM9OverlaySize;
+ u32 ARM7OverlayOffset;
+ u32 ARM7OverlaySize;
+
+ u32 NormalCommandSettings;
+ u32 Key1CommandSettings;
+
+ u32 BannerOffset;
+
+ u16 SecureAreaCRC16;
+ u16 SecureAreaDelay;
+
+ // GBATEK lists the following two with a question mark
+ u32 ARM9AutoLoadListAddress;
+ u32 ARM7AutoLoadListAddress;
+
+ u64 SecureAreaDisable;
+
+ u32 ROMSize;
+ u32 HeaderSize;
+
+ u32 Unknown1;
+ u8 Reserved2[52];
+
+ u8 NintendoLogo[156];
+ u16 NintendoLogoCRC16;
+ u16 HeaderCRC16;
+
+ u32 DebugROMOffset;
+ u32 DebugSize;
+ u32 DebugRAMAddress;
+
+ u32 Reserved4;
+ u8 Reserved5[144];
+};
+
+static_assert(sizeof(NDSHeader) == 512, "NDSHeader is not 512 bytes!");
+
+struct NDSBanner
+{
+ u16 Version;
+ u16 CRC16[4];
+ u8 Reserved1[22];
+ u8 Icon[512];
+ u16 Palette[16];
+
+ char16_t JapaneseTitle[128];
+ char16_t EnglishTitle[128];
+ char16_t FrenchTitle[128];
+ char16_t GermanTitle[128];
+ char16_t ItalianTitle[128];
+ char16_t SpanishTitle[128];
+ char16_t ChineseTitle[128];
+ char16_t KoreanTitle[128];
+
+ u8 Reserved2[2048];
+
+ u8 DSiIcon[8][512];
+ u16 DSiPalette[8][16];
+ u16 DSiSequence[64];
+};
+
+static_assert(sizeof(NDSBanner) == 9152, "NDSBanner is not 9152 bytes!");
+
+
+#endif //NDS_HEADER_H
diff --git a/src/frontend/FrontendUtil.h b/src/frontend/FrontendUtil.h
index f051c6c..b361c2a 100644
--- a/src/frontend/FrontendUtil.h
+++ b/src/frontend/FrontendUtil.h
@@ -21,6 +21,8 @@
#include "types.h"
+#include <vector>
+
namespace Frontend
{
@@ -84,6 +86,9 @@ int LoadROM(const u8 *romdata, u32 romlength, const char *archivefilename, const
// simulating ejection of the cartridge
void UnloadROM(int slot);
+void ROMIcon(u8 (&data)[512], u16 (&palette)[16], u32* iconRef);
+void AnimatedROMIcon(u8 (&data)[8][512], u16 (&palette)[8][16], u16 (&sequence)[64], u32 (&animatedTexRef)[32 * 32 * 64], std::vector<int> &animatedSequenceRef);
+
// reset execution of the current ROM
int Reset();
diff --git a/src/frontend/Util_ROM.cpp b/src/frontend/Util_ROM.cpp
index 8d691b3..19023fb 100644
--- a/src/frontend/Util_ROM.cpp
+++ b/src/frontend/Util_ROM.cpp
@@ -19,6 +19,8 @@
#include <stdio.h>
#include <string.h>
+#include <utility>
+
#ifdef ARCHIVE_SUPPORT_ENABLED
#include "ArchiveUtil.h"
#endif
@@ -461,6 +463,72 @@ int LoadROM(const char* file, int slot)
}
}
+void ROMIcon(u8 (&data)[512], u16 (&palette)[16], u32* iconRef)
+{
+ int index = 0;
+ for (int i = 0; i < 4; i++)
+ {
+ for (int j = 0; j < 4; j++)
+ {
+ for (int k = 0; k < 8; k++)
+ {
+ for (int l = 0; l < 8; l++)
+ {
+ u8 pal_index = index % 2 ? data[index/2] >> 4 : data[index/2] & 0x0F;
+ u8 r = ((palette[pal_index] >> 0) & 0x1F) * 255 / 31;
+ u8 g = ((palette[pal_index] >> 5) & 0x1F) * 255 / 31;
+ u8 b = ((palette[pal_index] >> 10) & 0x1F) * 255 / 31;
+ u8 a = pal_index ? 255: 0;
+ u32* row = &iconRef[256 * i + 32 * k + 8 * j];
+ row[l] = (a << 24) | (r << 16) | (g << 8) | b;
+ index++;
+ }
+ }
+ }
+ }
+}
+
+#define SEQ_FLIPV(i) ((i & 0b1000000000000000) >> 15)
+#define SEQ_FLIPH(i) ((i & 0b0100000000000000) >> 14)
+#define SEQ_PAL(i) ((i & 0b0011100000000000) >> 11)
+#define SEQ_BMP(i) ((i & 0b0000011100000000) >> 8)
+#define SEQ_DUR(i) ((i & 0b0000000011111111) >> 0)
+
+void AnimatedROMIcon(u8 (&data)[8][512], u16 (&palette)[8][16], u16 (&sequence)[64], u32 (&animatedTexRef)[32 * 32 * 64], std::vector<int> &animatedSequenceRef)
+{
+ for (int i = 0; i < 64; i++)
+ {
+ if (!sequence[i])
+ break;
+ u32* frame = &animatedTexRef[32 * 32 * i];
+ ROMIcon(data[SEQ_BMP(sequence[i])], palette[SEQ_PAL(sequence[i])], frame);
+
+ if (SEQ_FLIPH(sequence[i]))
+ {
+ for (int x = 0; x < 32; x++)
+ {
+ for (int y = 0; y < 32/2; y++)
+ {
+ std::swap(frame[x * 32 + y], frame[x * 32 + (32 - 1 - y)]);
+ }
+ }
+ }
+ if (SEQ_FLIPV(sequence[i]))
+ {
+ for (int x = 0; x < 32/2; x++)
+ {
+ for (int y = 0; y < 32; y++)
+ {
+ std::swap(frame[x * 32 + y], frame[(32 - 1 - x) * 32 + y]);
+ }
+ }
+ }
+
+ for (int j = 0; j < SEQ_DUR(sequence[i]); j++)
+ animatedSequenceRef.push_back(i);
+ }
+}
+
void UnloadROM(int slot)
{
if (slot == ROMSlot_NDS)
diff --git a/src/frontend/qt_sdl/CMakeLists.txt b/src/frontend/qt_sdl/CMakeLists.txt
index 05dce4a..1ec01b1 100644
--- a/src/frontend/qt_sdl/CMakeLists.txt
+++ b/src/frontend/qt_sdl/CMakeLists.txt
@@ -10,6 +10,7 @@ SET(SOURCES_QT_SDL
AudioSettingsDialog.cpp
WifiSettingsDialog.cpp
InterfaceSettingsDialog.cpp
+ ROMInfoDialog.cpp
Input.cpp
LAN_PCap.cpp
LAN_Socket.cpp
diff --git a/src/frontend/qt_sdl/ROMInfoDialog.cpp b/src/frontend/qt_sdl/ROMInfoDialog.cpp
new file mode 100644
index 0000000..673aaee
--- /dev/null
+++ b/src/frontend/qt_sdl/ROMInfoDialog.cpp
@@ -0,0 +1,145 @@
+/*
+ Copyright 2016-2021 Arisotura, WaluigiWare64
+
+ 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 "ROMInfoDialog.h"
+#include "ui_ROMInfoDialog.h"
+
+#include <QFileDialog>
+
+#include "NDS.h"
+#include "NDSCart.h"
+#include "Platform.h"
+#include "Config.h"
+#include "PlatformConfig.h"
+
+QString IntToHex(u64 num)
+{
+ return ("0x" + QString::number(num, 16).toUpper());
+}
+
+QString QStringBytes(u64 num)
+{
+ return (QString::number(num) + " Bytes");
+}
+
+ROMInfoDialog* ROMInfoDialog::currentDlg = nullptr;
+
+ROMInfoDialog::ROMInfoDialog(QWidget* parent) : QDialog(parent), ui(new Ui::ROMInfoDialog)
+{
+ ui->setupUi(this);
+ setAttribute(Qt::WA_DeleteOnClose);
+
+
+ u32 iconData[32 * 32];
+ Frontend::ROMIcon(NDSCart::Banner.Icon, NDSCart::Banner.Palette, iconData);
+ iconImage = QImage(reinterpret_cast<unsigned char*>(iconData), 32, 32, QImage::Format_ARGB32).copy();
+ ui->iconImage->setPixmap(QPixmap::fromImage(iconImage));
+
+ if (NDSCart::Banner.Version == 0x103)
+ {
+ u32 animatedIconData[32 * 32 * 64] = {0};
+ Frontend::AnimatedROMIcon(NDSCart::Banner.DSiIcon, NDSCart::Banner.DSiPalette, NDSCart::Banner.DSiSequence, animatedIconData, animatedSequence);
+
+ for (int i = 0; i < 64; i++)
+ {
+ if (animatedIconData[32 * 32 * i] == 0)
+ break;
+ animatedIconImages.push_back(QPixmap::fromImage(QImage(reinterpret_cast<unsigned char*>(&animatedIconData[32 * 32 * i]), 32, 32, QImage::Format_ARGB32).copy()));
+ }
+
+ iconTimeline = new QTimeLine(animatedSequence.size() / 60 * 1000, this);
+ iconTimeline->setFrameRange(0, animatedSequence.size() - 1);
+ iconTimeline->setLoopCount(0);
+ iconTimeline->setEasingCurve(QEasingCurve::Linear);
+ connect(iconTimeline, &QTimeLine::frameChanged, this, &ROMInfoDialog::iconSetFrame);
+ iconTimeline->start();
+ }
+ else
+ {
+ ui->dsiIconImage->setPixmap(QPixmap::fromImage(iconImage));
+ }
+
+ ui->iconTitle->setText(QString::fromUtf16(NDSCart::Banner.EnglishTitle));
+
+ ui->japaneseTitle->setText(QString::fromUtf16(NDSCart::Banner.JapaneseTitle));
+ ui->englishTitle->setText(QString::fromUtf16(NDSCart::Banner.EnglishTitle));
+ ui->frenchTitle->setText(QString::fromUtf16(NDSCart::Banner.FrenchTitle));
+ ui->germanTitle->setText(QString::fromUtf16(NDSCart::Banner.GermanTitle));
+ ui->italianTitle->setText(QString::fromUtf16(NDSCart::Banner.ItalianTitle));
+ ui->spanishTitle->setText(QString::fromUtf16(NDSCart::Banner.SpanishTitle));
+
+ if (NDSCart::Banner.Version > 1)
+ ui->chineseTitle->setText(QString::fromUtf16(NDSCart::Banner.ChineseTitle));
+ else
+ ui->chineseTitle->setText("None");
+
+ if (NDSCart::Banner.Version > 2)
+ ui->koreanTitle->setText(QString::fromUtf16(NDSCart::Banner.KoreanTitle));
+ else
+ ui->koreanTitle->setText("None");
+
+ ui->gameTitle->setText(QString::fromLatin1(NDSCart::Header.GameTitle, 12));
+ ui->gameCode->setText(QString::fromLatin1(NDSCart::Header.GameCode, 4));
+ ui->makerCode->setText(QString::fromLatin1(NDSCart::Header.MakerCode, 2));
+ ui->cardSize->setText(QString::number(128 << NDSCart::Header.CardSize) + " KB");
+
+ ui->arm9RomOffset->setText(IntToHex(NDSCart::Header.ARM9ROMOffset));
+ ui->arm9EntryAddress->setText(IntToHex(NDSCart::Header.ARM9EntryAddress));
+ ui->arm9RamAddress->setText(IntToHex(NDSCart::Header.ARM9RAMAddress));
+ ui->arm9Size->setText(QStringBytes(NDSCart::Header.ARM9Size));
+
+ ui->arm7RomOffset->setText(IntToHex(NDSCart::Header.ARM7ROMOffset));
+ ui->arm7EntryAddress->setText(IntToHex(NDSCart::Header.ARM7EntryAddress));
+ ui->arm7RamAddress->setText(IntToHex(NDSCart::Header.ARM7RAMAddress));
+ ui->arm7Size->setText(QStringBytes(NDSCart::Header.ARM7Size));
+
+ ui->fntOffset->setText(IntToHex(NDSCart::Header.FNTOffset));
+ ui->fntSize->setText(QStringBytes(NDSCart::Header.FNTSize));
+ ui->fatOffset->setText(IntToHex(NDSCart::Header.FATOffset));
+ ui->fatSize->setText(QStringBytes(NDSCart::Header.FATSize));
+
+}
+
+ROMInfoDialog::~ROMInfoDialog()
+{
+ delete ui;
+}
+
+void ROMInfoDialog::done(int r)
+{
+ QDialog::done(r);
+
+ closeDlg();
+}
+
+void ROMInfoDialog::on_saveIconButton_clicked()
+{
+ QString filename = QFileDialog::getSaveFileName(this,
+ "Save Icon",
+ Config::LastROMFolder,
+ "PNG Images (*.png)");
+ if (filename.isEmpty())
+ return;
+
+ iconImage.save(filename, "PNG");
+}
+
+void ROMInfoDialog::iconSetFrame(int frame)
+{
+ ui->dsiIconImage->setPixmap(animatedIconImages[animatedSequence[frame]]);
+}
diff --git a/src/frontend/qt_sdl/ROMInfoDialog.h b/src/frontend/qt_sdl/ROMInfoDialog.h
new file mode 100644
index 0000000..5193554
--- /dev/null
+++ b/src/frontend/qt_sdl/ROMInfoDialog.h
@@ -0,0 +1,75 @@
+/*
+ Copyright 2016-2021 Arisotura, WaluigiWare64
+
+ 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 ROMINFODIALOG_H
+#define ROMINFODIALOG_H
+
+#include <QDialog>
+#include <QTimeLine>
+#include <QPixmap>
+#include <QImage>
+
+#include "types.h"
+#include "FrontendUtil.h"
+
+namespace Ui { class ROMInfoDialog; }
+class ROMInfoDialog;
+
+class ROMInfoDialog : public QDialog
+{
+ Q_OBJECT
+
+public:
+ explicit ROMInfoDialog(QWidget* parent);
+ ~ROMInfoDialog();
+
+ static ROMInfoDialog* currentDlg;
+ static ROMInfoDialog* openDlg(QWidget* parent)
+ {
+ if (currentDlg)
+ {
+ currentDlg->activateWindow();
+ return currentDlg;
+ }
+
+ currentDlg = new ROMInfoDialog(parent);
+ currentDlg->open();
+ return currentDlg;
+ }
+ static void closeDlg()
+ {
+ currentDlg = nullptr;
+ }
+
+private slots:
+ void done(int r);
+
+ void on_saveIconButton_clicked();
+
+ void iconSetFrame(int frame);
+
+private:
+ Ui::ROMInfoDialog* ui;
+
+ QImage iconImage;
+ QTimeLine* iconTimeline;
+ std::vector<QPixmap> animatedIconImages;
+ std::vector<int> animatedSequence;
+};
+
+#endif // ROMINFODIALOG_H
diff --git a/src/frontend/qt_sdl/ROMInfoDialog.ui b/src/frontend/qt_sdl/ROMInfoDialog.ui
new file mode 100644
index 0000000..4c5d7d3
--- /dev/null
+++ b/src/frontend/qt_sdl/ROMInfoDialog.ui
@@ -0,0 +1,831 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<ui version="4.0">
+ <class>ROMInfoDialog</class>
+ <widget class="QDialog" name="ROMInfoDialog">
+ <property name="geometry">
+ <rect>
+ <x>0</x>
+ <y>0</y>
+ <width>427</width>
+ <height>434</height>
+ </rect>
+ </property>
+ <property name="sizePolicy">
+ <sizepolicy hsizetype="Fixed" vsizetype="Fixed">
+ <horstretch>0</horstretch>
+ <verstretch>0</verstretch>
+ </sizepolicy>
+ </property>
+ <property name="windowTitle">
+ <string>ROM Info - melonDS</string>
+ </property>
+ <layout class="QGridLayout" name="gridLayout">
+ <item row="2" column="0">
+ <widget class="QGroupBox" name="titles">
+ <property name="sizePolicy">
+ <sizepolicy hsizetype="MinimumExpanding" vsizetype="MinimumExpanding">
+ <horstretch>0</horstretch>
+ <verstretch>0</verstretch>
+ </sizepolicy>
+ </property>
+ <property name="title">
+ <string>Titles</string>
+ </property>
+ <layout class="QFormLayout" name="formLayout">
+ <item row="0" column="0">
+ <widget class="QLabel" name="label_2">
+ <property name="font">
+ <font>
+ <underline>false</underline>
+ </font>
+ </property>
+ <property name="text">
+ <string>Japanese Title:</string>
+ </property>
+ </widget>
+ </item>
+ <item row="0" column="1">
+ <widget class="QLabel" name="japaneseTitle">
+ <property name="text">
+ <string>[japanese title]</string>
+ </property>
+ </widget>
+ </item>
+ <item row="1" column="0">
+ <widget class="QLabel" name="label_3">
+ <property name="font">
+ <font>
+ <underline>false</underline>
+ </font>
+ </property>
+ <property name="text">
+ <string>English Title:</string>
+ </property>
+ </widget>
+ </item>
+ <item row="1" column="1">
+ <widget class="QLabel" name="englishTitle">
+ <property name="text">
+ <string>[english title]</string>
+ </property>
+ </widget>
+ </item>
+ <item row="2" column="0">
+ <widget class="QLabel" name="label_4">
+ <property name="font">
+ <font>
+ <underline>false</underline>
+ </font>
+ </property>
+ <property name="text">
+ <string>French Title:</string>
+ </property>
+ </widget>
+ </item>
+ <item row="2" column="1">
+ <widget class="QLabel" name="frenchTitle">
+ <property name="text">
+ <string>[french title]</string>
+ </property>
+ </widget>
+ </item>
+ <item row="3" column="0">
+ <widget class="QLabel" name="label_5">
+ <property name="font">
+ <font>
+ <underline>false</underline>
+ </font>
+ </property>
+ <property name="text">
+ <string>German Title:</string>
+ </property>
+ </widget>
+ </item>
+ <item row="3" column="1">
+ <widget class="QLabel" name="germanTitle">
+ <property name="text">
+ <string>[german title]</string>
+ </property>
+ </widget>
+ </item>
+ <item row="4" column="0">
+ <widget class="QLabel" name="label_6">
+ <property name="font">
+ <font>
+ <underline>false</underline>
+ </font>
+ </property>
+ <property name="text">
+ <string>Italian Title:</string>
+ </property>
+ </widget>
+ </item>
+ <item row="4" column="1">
+ <widget class="QLabel" name="italianTitle">
+ <property name="text">
+ <string>[italian title]</string>
+ </property>
+ </widget>
+ </item>
+ <item row="5" column="0">
+ <widget class="QLabel" name="label_7">
+ <property name="font">
+ <font>
+ <underline>false</underline>
+ </font>
+ </property>
+ <property name="text">
+ <string>Spanish Title:</string>
+ </property>
+ </widget>
+ </item>
+ <item row="5" column="1">
+ <widget class="QLabel" name="spanishTitle">
+ <property name="text">
+ <string>[spanish title]</string>
+ </property>
+ </widget>
+ </item>
+ <item row="6" column="0">
+ <widget class="QLabel" name="label_25">
+ <property name="font">
+ <font>
+ <underline>false</underline>
+ </font>
+ </property>
+ <property name="text">
+ <string>Chinese Title:</string>
+ </property>
+ </widget>
+ </item>
+ <item row="6" column="1">
+ <widget class="QLabel" name="chineseTitle">
+ <property name="text">
+ <string>[chinese title]</string>
+ </property>
+ </widget>
+ </item>
+ <item row="7" column="0">
+ <widget class="QLabel" name="label_23">
+ <property name="font">
+ <font>
+ <underline>false</underline>
+ </font>
+ </property>
+ <property name="text">
+ <string>Korean Title:</string>
+ </property>
+ </widget>
+ </item>
+ <item row="7" column="1">
+ <widget class="QLabel" name="koreanTitle">
+ <property name="text">
+ <string>[korean title]</string>
+ </property>
+ </widget>
+ </item>
+ </layout>
+ </widget>
+ </item>
+ <item row="2" column="1">
+ <widget class="QGroupBox" name="arm9AndArm7Binaries">
+ <property name="title">
+ <string>ARM7 and ARM9 binaries</string>
+ </property>
+ <layout class="QFormLayout" name="formLayout_2">
+ <item row="0" column="0">
+ <widget class="QLabel" name="label_11">
+ <property name="font">
+ <font>
+ <underline>false</underline>
+ </font>
+ </property>
+ <property name="text">
+ <string>ARM9 ROM Offset: </string>
+ </property>
+ </widget>
+ </item>
+ <item row="0" column="1">
+ <widget class="QLabel" name="arm9RomOffset">
+ <property name="text">
+ <string>[arm9 rom offset]</string>
+ </property>
+ </widget>
+ </item>
+ <item row="1" column="0">
+ <widget class="QLabel" name="label_12">
+ <property name="font">
+ <font>
+ <underline>false</underline>
+ </font>
+ </property>
+ <property name="text">
+ <string>ARM9 Entry Address:</string>
+ </property>
+ </widget>
+ </item>
+ <item row="1" column="1">
+ <widget class="QLabel" name="arm9EntryAddress">
+ <property name="text">
+ <string>[arm9 entry address]</string>
+ </property>
+ </widget>
+ </item>
+ <item row="2" column="0">
+ <widget class="QLabel" name="label_14">
+ <property name="font">
+ <font>
+ <underline>false</underline>
+ </font>
+ </property>
+ <property name="text">
+ <string>ARM9 RAM Address:</string>
+ </property>
+ </widget>
+ </item>
+ <item row="2" column="1">
+ <widget class="QLabel" name="arm9RamAddress">
+ <property name="text">
+ <string>[arm9 ram address]</string>
+ </property>
+ </widget>
+ </item>
+ <item row="3" column="0">
+ <widget class="QLabel" name="label_16">
+ <property name="font">
+ <font>
+ <underline>false</underline>
+ </font>
+ </property>
+ <property name="text">
+ <string>ARM9 Size:</string>
+ </property>
+ </widget>
+ </item>
+ <item row="3" column="1">
+ <widget class="QLabel" name="arm9Size">
+ <property name="text">
+ <string>[arm9 size]</string>
+ </property>
+ </widget>
+ </item>
+ <item row="4" column="0">
+ <widget class="QLabel" name="label_15">
+ <property name="font">
+ <font>
+ <underline>false</underline>
+ </font>
+ </property>
+ <property name="text">
+ <string>ARM7 ROM Offset: </string>
+ </property>
+ </widget>
+ </item>
+ <item row="4" column="1">
+ <widget class="QLabel" name="arm7RomOffset">
+ <property name="text">
+ <string>[arm7 rom offset]</string>
+ </property>
+ </widget>
+ </item>
+ <item row="5" column="0">
+ <widget class="QLabel" name="label_13">
+ <property name="font">
+ <font>
+ <underline>false</underline>
+ </font>
+ </property>
+ <property name="text">
+ <string>ARM7 Entry Address:</string>
+ </property>
+ </widget>
+ </item>
+ <item row="5" column="1">
+ <widget class="QLabel" name="arm7EntryAddress">
+ <property name="text">
+ <string>[arm7 entry address]</string>
+ </property>
+ </widget>
+ </item>
+ <item row="6" column="0">
+ <widget class="QLabel" name="label_18">
+ <property name="font">
+ <font>
+ <underline>false</underline>
+ </font>
+ </property>
+ <property name="text">
+ <string>ARM7 RAM Address:</string>
+ </property>
+ </widget>
+ </item>
+ <item row="6" column="1">
+ <widget class="QLabel" name="arm7RamAddress">
+ <property name="text">
+ <string>[arm7 ram address]</string>
+ </property>
+ </widget>
+ </item>
+ <item row="7" column="0">
+ <widget class="QLabel" name="label_17">
+ <property name="font">
+ <font>
+ <underline>false</underline>
+ </font>
+ </property>
+ <property name="text">
+ <string>ARM7 Size:</string>
+ </property>
+ </widget>
+ </item>
+ <item row="7" column="1">
+ <widget class="QLabel" name="arm7Size">
+ <property name="text">
+ <string>[arm7 size]</string>
+ </property>
+ </widget>
+ </item>
+ </layout>
+ </widget>
+ </item>
+ <item row="3" column="1">
+ <widget class="QGroupBox" name="filesystem">
+ <property name="sizePolicy">
+ <sizepolicy hsizetype="MinimumExpanding" vsizetype="MinimumExpanding">
+ <horstretch>0</horstretch>
+ <verstretch>0</verstretch>
+ </sizepolicy>
+ </property>
+ <property name="title">
+ <string>Filesystem</string>
+ </property>
+ <layout class="QFormLayout" name="formLayout_4">
+ <item row="0" column="0">
+ <widget class="QLabel" name="label_19">
+ <property name="font">
+ <font>
+ <underline>false</underline>
+ </font>
+ </property>
+ <property name="text">
+ <string>FNT Offset:</string>
+ </property>
+ </widget>
+ </item>
+ <item row="0" column="1">
+ <widget class="QLabel" name="fntOffset">
+ <property name="text">
+ <string>[fnt offset]</string>
+ </property>
+ </widget>
+ </item>
+ <item row="1" column="0">
+ <widget class="QLabel" name="label_20">
+ <property name="font">
+ <font>
+ <underline>false</underline>
+ </font>
+ </property>
+ <property name="text">
+ <string>FNT Size:</string>
+ </property>
+ </widget>
+ </item>
+ <item row="1" column="1">
+ <widget class="QLabel" name="fntSize">
+ <property name="text">
+ <string>[fnt size]</string>
+ </property>
+ </widget>
+ </item>
+ <item row="2" column="0">
+ <widget class="QLabel" name="label_21">
+ <property name="font">
+ <font>
+ <underline>false</underline>
+ </font>
+ </property>
+ <property name="text">
+ <string>FAT Offset:</string>
+ </property>
+ </widget>
+ </item>
+ <item row="2" column="1">
+ <widget class="QLabel" name="fatOffset">
+ <property name="text">
+ <string>[fat offset]</string>
+ </property>
+ </widget>
+ </item>
+ <item row="3" column="0">
+ <widget class="QLabel" name="label_22">
+ <property name="font">
+ <font>
+ <underline>false</underline>
+ </font>
+ </property>
+ <property name="text">
+ <string>FAT Size:</string>
+ </property>
+ </widget>
+ </item>
+ <item row="3" column="1">
+ <widget class="QLabel" name="fatSize">
+ <property name="text">
+ <string>[fat size]</string>
+ </property>
+ </widget>
+ </item>
+ </layout>
+ </widget>
+ </item>
+ <item row="3" column="0">
+ <widget class="QGroupBox" name="generalInfo">
+ <property name="sizePolicy">
+ <sizepolicy hsizetype="MinimumExpanding" vsizetype="MinimumExpanding">
+ <horstretch>0</horstretch>
+ <verstretch>0</verstretch>
+ </sizepolicy>
+ </property>
+ <property name="title">
+ <string>General Info</string>
+ </property>
+ <layout class="QFormLayout" name="formLayout_3">
+ <item row="0" column="0">
+ <widget class="QLabel" name="label">
+ <property name="font">
+ <font>
+ <underline>false</underline>
+ </font>
+ </property>
+ <property name="text">
+ <string>Game Title:</string>
+ </property>
+ </widget>
+ </item>
+ <item row="0" column="1">
+ <widget class="QLabel" name="gameTitle">
+ <property name="text">
+ <string>[game title]</string>
+ </property>
+ </widget>
+ </item>
+ <item row="1" column="0">
+ <widget class="QLabel" name="label_8">
+ <property name="font">
+ <font>
+ <underline>false</underline>
+ </font>
+ </property>
+ <property name="text">
+ <string>Game Code:</string>
+ </property>
+ </widget>
+ </item>
+ <item row="1" column="1">
+ <widget class="QLabel" name="gameCode">
+ <property name="text">
+ <string>[game code]</string>
+ </property>
+ </widget>
+ </item>
+ <item row="2" column="0">
+ <widget class="QLabel" name="label_9">
+ <property name="font">
+ <font>
+ <underline>false</underline>
+ </font>
+ </property>
+ <property name="text">
+ <string>Maker Code:</string>
+ </property>
+ </widget>
+ </item>
+ <item row="2" column="1">
+ <widget class="QLabel" name="makerCode">
+ <property name="text">
+ <string>[maker code]</string>
+ </property>
+ </widget>
+ </item>
+ <item row="3" column="0">
+ <widget class="QLabel" name="label_10">
+ <property name="font">
+ <font>
+ <underline>false</underline>
+ </font>
+ </property>
+ <property name="text">
+ <string>Card Size:</string>
+ </property>
+ </widget>
+ </item>
+ <item row="3" column="1">
+ <widget class="QLabel" name="cardSize">
+ <property name="text">
+ <string>[card size]</string>
+ </property>
+ </widget>
+ </item>
+ </layout>
+ </widget>
+ </item>
+ <item row="4" column="0" colspan="2">
+ <widget class="QDialogButtonBox" name="buttonBox">
+ <property name="orientation">
+ <enum>Qt::Horizontal</enum>
+ </property>
+ <property name="standardButtons">
+ <set>QDialogButtonBox::Ok</set>
+ </property>
+ </widget>
+ </item>
+ <item row="0" column="0" colspan="2">
+ <widget class="QGroupBox" name="groupBox_2">
+ <layout class="QGridLayout" name="gridLayout_9">
+ <item row="0" column="1">
+ <widget class="QGroupBox" name="iconBox">
+ <property name="sizePolicy">
+ <sizepolicy hsizetype="Preferred" vsizetype="Preferred">
+ <horstretch>0</horstretch>
+ <verstretch>0</verstretch>
+ </sizepolicy>
+ </property>
+ <property name="styleSheet">
+ <string notr="true">#iconBox {
+ border: 1px solid black;
+ background-color: qlineargradient(x1: 0, y1: 0, x2: 0, y2: 1,
+ stop: 0 white,
+ stop: 1 lightgrey);
+}
+
+#titleBox {
+ border: 0.5px solid grey;
+ background-color: #fbfbfb;
+}
+
+#iconTitle {
+ color: black;
+}
+</string>
+ </property>
+ <property name="title">
+ <string/>
+ </property>
+ <property name="alignment">
+ <set>Qt::AlignCenter</set>
+ </property>
+ <property name="flat">
+ <bool>false</bool>
+ </property>
+ <property name="checkable">
+ <bool>false</bool>
+ </property>
+ <layout class="QGridLayout" name="gridLayout_2">
+ <property name="topMargin">
+ <number>2</number>
+ </property>
+ <property name="bottomMargin">
+ <number>2</number>
+ </property>
+ <item row="0" column="1">
+ <widget class="QLabel" name="iconImage">
+ <property name="sizePolicy">
+ <sizepolicy hsizetype="Preferred" vsizetype="Preferred">
+ <horstretch>0</horstretch>
+ <verstretch>0</verstretch>
+ </sizepolicy>
+ </property>
+ <property name="minimumSize">
+ <size>
+ <width>32</width>
+ <height>32</height>
+ </size>
+ </property>
+ <property name="maximumSize">
+ <size>
+ <width>32</width>
+ <height>32</height>
+ </size>
+ </property>
+ <property name="text">
+ <string>[icon]</string>
+ </property>
+ </widget>
+ </item>
+ <item row="0" column="2">
+ <widget class="QGroupBox" name="titleBox">
+ <property name="sizePolicy">
+ <sizepolicy hsizetype="Expanding" vsizetype="Expanding">
+ <horstretch>0</horstretch>
+ <verstretch>0</verstretch>
+ </sizepolicy>
+ </property>
+ <property name="title">
+ <string/>
+ </property>
+ <layout class="QGridLayout" name="gridLayout_4">
+ <property name="leftMargin">
+ <number>1</number>
+ </property>
+ <property name="topMargin">
+ <number>1</number>
+ </property>
+ <property name="rightMargin">
+ <number>1</number>
+ </property>
+ <property name="bottomMargin">
+ <number>1</number>
+ </property>
+ <item row="0" column="0">
+ <widget class="QLabel" name="iconTitle">
+ <property name="sizePolicy">
+ <sizepolicy hsizetype="MinimumExpanding" vsizetype="MinimumExpanding">
+ <horstretch>0</horstretch>
+ <verstretch>0</verstretch>
+ </sizepolicy>
+ </property>
+ <property name="font">
+ <font>
+ <family>Courier New</family>
+ <pointsize>8</pointsize>
+ <weight>50</weight>
+ <italic>false</italic>
+ <bold>false</bold>
+ </font>
+ </property>
+ <property name="text">
+ <string>[title]</string>
+ </property>
+ <property name="alignment">
+ <set>Qt::AlignCenter</set>
+ </property>
+ </widget>
+ </item>
+ </layout>
+ </widget>
+ </item>
+ </layout>
+ </widget>
+ </item>
+ <item row="0" column="3">
+ <widget class="QGroupBox" name="dsiIconBox">
+ <property name="sizePolicy">
+ <sizepolicy hsizetype="Minimum" vsizetype="Minimum">
+ <horstretch>0</horstretch>
+ <verstretch>0</verstretch>
+ </sizepolicy>
+ </property>
+ <property name="styleSheet">
+ <string notr="true">#dsiIconBox {
+ border-radius: 4px;
+ background-color: #515151;
+}
+
+#dsiIconImage {
+ background-color: white;
+}</string>
+ </property>
+ <property name="title">
+ <string/>
+ </property>
+ <property name="alignment">
+ <set>Qt::AlignCenter</set>
+ </property>
+ <property name="flat">
+ <bool>false</bool>
+ </property>
+ <property name="checkable">
+ <bool>false</bool>
+ </property>
+ <layout class="QGridLayout" name="gridLayout_10">
+ <property name="leftMargin">
+ <number>8</number>
+ </property>
+ <property name="topMargin">
+ <number>6</number>
+ </property>
+ <property name="rightMargin">
+ <number>8</number>
+ </property>
+ <property name="bottomMargin">
+ <number>6</number>
+ </property>
+ <item row="0" column="0">
+ <widget class="QLabel" name="dsiIconImage">
+ <property name="sizePolicy">
+ <sizepolicy hsizetype="Minimum" vsizetype="Minimum">
+ <horstretch>0</horstretch>
+ <verstretch>0</verstretch>
+ </sizepolicy>
+ </property>
+ <property name="minimumSize">
+ <size>
+ <width>32</width>
+ <height>32</height>
+ </size>
+ </property>
+ <property name="maximumSize">
+ <size>
+ <width>32</width>
+ <height>32</height>
+ </size>
+ </property>
+ <property name="text">
+ <string>[dsi icon]</string>
+ </property>
+ <property name="alignment">
+ <set>Qt::AlignCenter</set>
+ </property>
+ </widget>
+ </item>
+ </layout>
+ </widget>
+ </item>
+ <item row="0" column="0">
+ <spacer name="horizontalSpacer">
+ <property name="orientation">
+ <enum>Qt::Horizontal</enum>
+ </property>
+ <property name="sizeHint" stdset="0">
+ <size>
+ <width>55</width>
+ <height>20</height>
+ </size>
+ </property>
+ </spacer>
+ </item>
+ <item row="0" column="4">
+ <spacer name="horizontalSpacer_3">
+ <property name="orientation">
+ <enum>Qt::Horizontal</enum>
+ </property>
+ <property name="sizeHint" stdset="0">
+ <size>
+ <width>40</width>
+ <height>20</height>
+ </size>
+ </property>
+ </spacer>
+ </item>
+ <item row="0" column="2">
+ <spacer name="horizontalSpacer_2">
+ <property name="orientation">
+ <enum>Qt::Horizontal</enum>
+ </property>
+ <property name="sizeHint" stdset="0">
+ <size>
+ <width>40</width>
+ <height>20</height>
+ </size>
+ </property>
+ </spacer>
+ </item>
+ <item row="1" column="1">
+ <widget class="QPushButton" name="saveIconButton">
+ <property name="text">
+ <string>Save Icon</string>
+ </property>
+ </widget>
+ </item>
+ </layout>
+ </widget>
+ </item>
+ </layout>
+ </widget>
+ <resources/>
+ <connections>
+ <connection>
+ <sender>buttonBox</sender>
+ <signal>accepted()</signal>
+ <receiver>ROMInfoDialog</receiver>
+ <slot>accept()</slot>
+ <hints>
+ <hint type="sourcelabel">
+ <x>248</x>
+ <y>254</y>
+ </hint>
+ <hint type="destinationlabel">
+ <x>157</x>
+ <y>274</y>
+ </hint>
+ </hints>
+ </connection>
+ <connection>
+ <sender>buttonBox</sender>
+ <signal>rejected()</signal>
+ <receiver>ROMInfoDialog</receiver>
+ <slot>reject()</slot>
+ <hints>
+ <hint type="sourcelabel">
+ <x>316</x>
+ <y>260</y>
+ </hint>
+ <hint type="destinationlabel">
+ <x>286</x>
+ <y>274</y>
+ </hint>
+ </hints>
+ </connection>
+ </connections>
+</ui>
diff --git a/src/frontend/qt_sdl/main.cpp b/src/frontend/qt_sdl/main.cpp
index 8407acb..acb8d29 100644
--- a/src/frontend/qt_sdl/main.cpp
+++ b/src/frontend/qt_sdl/main.cpp
@@ -57,6 +57,7 @@
#include "AudioSettingsDialog.h"
#include "WifiSettingsDialog.h"
#include "InterfaceSettingsDialog.h"
+#include "ROMInfoDialog.h"
#include "types.h"
#include "version.h"
@@ -65,6 +66,7 @@
#include "OSD.h"
#include "NDS.h"
+#include "NDSCart.h"
#include "GBACart.h"
#include "GPU.h"
#include "SPU.h"
@@ -1331,6 +1333,10 @@ MainWindow::MainWindow(QWidget* parent) : QMainWindow(parent)
actSetupCheats = menu->addAction("Setup cheat codes");
actSetupCheats->setMenuRole(QAction::NoRole);
connect(actSetupCheats, &QAction::triggered, this, &MainWindow::onSetupCheats);
+
+ menu->addSeparator();
+ actROMInfo = menu->addAction("ROM Info");
+ connect(actROMInfo, &QAction::triggered, this, &MainWindow::onROMInfo);
}
{
QMenu* menu = menubar->addMenu("Config");
@@ -1533,9 +1539,10 @@ MainWindow::MainWindow(QWidget* parent) : QMainWindow(parent)
actSetupCheats->setEnabled(false);
-
actEnableCheats->setChecked(Config::EnableCheats != 0);
+ actROMInfo->setEnabled(false);
+
actSavestateSRAMReloc->setChecked(Config::SavestateRelocSRAM != 0);
actScreenRotation[Config::ScreenRotation]->setChecked(true);
@@ -2335,6 +2342,10 @@ void MainWindow::onCheatsDialogFinished(int res)
emuThread->emuUnpause();
}
+void MainWindow::onROMInfo()
+{
+ ROMInfoDialog* dlg = ROMInfoDialog::openDlg(this);
+}
void MainWindow::onOpenEmuSettings()
{
@@ -2589,6 +2600,8 @@ void MainWindow::onEmuStart()
actImportSavefile->setEnabled(true);
actSetupCheats->setEnabled(true);
+
+ actROMInfo->setEnabled(true);
}
void MainWindow::onEmuStop()
@@ -2609,6 +2622,8 @@ void MainWindow::onEmuStop()
actFrameStep->setEnabled(false);
actSetupCheats->setEnabled(false);
+
+ actROMInfo->setEnabled(false);
}
void MainWindow::onUpdateVideoSettings(bool glchange)
diff --git a/src/frontend/qt_sdl/main.h b/src/frontend/qt_sdl/main.h
index 024af8a..9d9e40e 100644
--- a/src/frontend/qt_sdl/main.h
+++ b/src/frontend/qt_sdl/main.h
@@ -235,6 +235,7 @@ private slots:
void onEnableCheats(bool checked);
void onSetupCheats();
void onCheatsDialogFinished(int res);
+ void onROMInfo();
void onOpenEmuSettings();
void onEmuSettingsDialogFinished(int res);
@@ -310,6 +311,7 @@ public:
QAction* actFrameStep;
QAction* actEnableCheats;
QAction* actSetupCheats;
+ QAction* actROMInfo;
QAction* actEmuSettings;
QAction* actInputConfig;