Skip to content

Commit

Permalink
Browse files Browse the repository at this point in the history
Merge pull request #8875 from JosJuice/nkit-warning
DolphinQt: Show a warning when launching an NKit disc image
  • Loading branch information
degasus committed Jul 30, 2020
2 parents 3d680ff + 2e8c5b4 commit 9d44df0
Show file tree
Hide file tree
Showing 14 changed files with 160 additions and 15 deletions.
5 changes: 5 additions & 0 deletions Source/Core/Core/Config/MainSettings.cpp
Expand Up @@ -142,11 +142,16 @@ const Info<std::string> MAIN_FS_PATH{{System::Main, "General", "NANDRootPath"},
const Info<std::string> MAIN_SD_PATH{{System::Main, "General", "WiiSDCardPath"}, ""};

// Main.Network

const Info<bool> MAIN_NETWORK_SSL_DUMP_READ{{System::Main, "Network", "SSLDumpRead"}, false};
const Info<bool> MAIN_NETWORK_SSL_DUMP_WRITE{{System::Main, "Network", "SSLDumpWrite"}, false};
const Info<bool> MAIN_NETWORK_SSL_VERIFY_CERTIFICATES{
{System::Main, "Network", "SSLVerifyCertificates"}, true};
const Info<bool> MAIN_NETWORK_SSL_DUMP_ROOT_CA{{System::Main, "Network", "SSLDumpRootCA"}, false};
const Info<bool> MAIN_NETWORK_SSL_DUMP_PEER_CERT{{System::Main, "Network", "SSLDumpPeerCert"},
false};

// Main.Interface

const Info<bool> MAIN_SKIP_NKIT_WARNING{{System::Main, "Interface", "SkipNKitWarning"}, false};
} // namespace Config
4 changes: 4 additions & 0 deletions Source/Core/Core/Config/MainSettings.h
Expand Up @@ -126,4 +126,8 @@ extern const Info<bool> MAIN_NETWORK_SSL_DUMP_WRITE;
extern const Info<bool> MAIN_NETWORK_SSL_VERIFY_CERTIFICATES;
extern const Info<bool> MAIN_NETWORK_SSL_DUMP_ROOT_CA;
extern const Info<bool> MAIN_NETWORK_SSL_DUMP_PEER_CERT;

// Main.Interface

extern const Info<bool> MAIN_SKIP_NKIT_WARNING;
} // namespace Config
6 changes: 5 additions & 1 deletion Source/Core/Core/ConfigLoaders/IsSettingSaveable.cpp
Expand Up @@ -32,7 +32,7 @@ bool IsSettingSaveable(const Config::Location& config_location)
}
}

static constexpr std::array<const Config::Location*, 12> s_setting_saveable = {
static constexpr std::array<const Config::Location*, 13> s_setting_saveable = {
// Main.Core

&Config::MAIN_DEFAULT_ISO.location,
Expand All @@ -47,6 +47,10 @@ bool IsSettingSaveable(const Config::Location& config_location)
&Config::MAIN_MEM2_SIZE.location,
&Config::MAIN_GFX_BACKEND.location,

// Main.Interface

&Config::MAIN_SKIP_NKIT_WARNING.location,

// UI.General

&Config::MAIN_USE_DISCORD_PRESENCE.location,
Expand Down
1 change: 1 addition & 0 deletions Source/Core/DiscIO/Volume.h
Expand Up @@ -116,6 +116,7 @@ class Volume
}
virtual Platform GetVolumeType() const = 0;
virtual bool IsDatelDisc() const = 0;
virtual bool IsNKit() const = 0;
virtual bool SupportsIntegrityCheck() const { return false; }
virtual bool CheckH3TableIntegrity(const Partition& partition) const { return false; }
virtual bool CheckBlockIntegrity(u64 block_index, const std::vector<u8>& encrypted_data,
Expand Down
6 changes: 6 additions & 0 deletions Source/Core/DiscIO/VolumeDisc.cpp
Expand Up @@ -84,4 +84,10 @@ std::optional<u8> VolumeDisc::GetDiscNumber(const Partition& partition) const
return ReadSwapped<u8>(6, partition);
}

bool VolumeDisc::IsNKit() const
{
constexpr u32 NKIT_MAGIC = 0x4E4B4954; // "NKIT"
return ReadSwapped<u32>(0x200, PARTITION_NONE) == NKIT_MAGIC;
}

} // namespace DiscIO
1 change: 1 addition & 0 deletions Source/Core/DiscIO/VolumeDisc.h
Expand Up @@ -22,6 +22,7 @@ class VolumeDisc : public Volume
std::string GetInternalName(const Partition& partition = PARTITION_NONE) const override;
std::string GetApploaderDate(const Partition& partition) const override;
std::optional<u8> GetDiscNumber(const Partition& partition = PARTITION_NONE) const override;
bool IsNKit() const override;

protected:
Region RegionCodeToRegion(std::optional<u32> region_code) const;
Expand Down
24 changes: 10 additions & 14 deletions Source/Core/DiscIO/VolumeVerifier.cpp
Expand Up @@ -988,22 +988,18 @@ void VolumeVerifier::CheckMisc()
}
}

if (IsDisc(m_volume.GetVolumeType()))
if (m_volume.IsNKit())
{
constexpr u32 NKIT_MAGIC = 0x4E4B4954; // "NKIT"
if (m_volume.ReadSwapped<u32>(0x200, PARTITION_NONE) == NKIT_MAGIC)
{
AddProblem(
Severity::Low,
Common::GetStringT("This disc image is in the NKit format. It is not a good dump in its "
"current form, but it might become a good dump if converted back. "
"The CRC32 of this file might match the CRC32 of a good dump even "
"though the files are not identical."));
}

if (StringBeginsWith(game_id_unencrypted, "R8P"))
CheckSuperPaperMario();
AddProblem(
Severity::Low,
Common::GetStringT("This disc image is in the NKit format. It is not a good dump in its "
"current form, but it might become a good dump if converted back. "
"The CRC32 of this file might match the CRC32 of a good dump even "
"though the files are not identical."));
}

if (IsDisc(m_volume.GetVolumeType()) && StringBeginsWith(game_id_unencrypted, "R8P"))
CheckSuperPaperMario();
}

void VolumeVerifier::CheckSuperPaperMario()
Expand Down
5 changes: 5 additions & 0 deletions Source/Core/DiscIO/VolumeWad.cpp
Expand Up @@ -289,6 +289,11 @@ bool VolumeWAD::IsDatelDisc() const
return false;
}

bool VolumeWAD::IsNKit() const
{
return false;
}

std::map<Language, std::string> VolumeWAD::GetLongNames() const
{
if (!m_tmd.IsValid() || !IOS::ES::IsChannel(m_tmd.GetTitleId()))
Expand Down
1 change: 1 addition & 0 deletions Source/Core/DiscIO/VolumeWad.h
Expand Up @@ -60,6 +60,7 @@ class VolumeWAD : public Volume
}
Platform GetVolumeType() const override;
bool IsDatelDisc() const override;
bool IsNKit() const override;
Region GetRegion() const override;
Country GetCountry(const Partition& partition = PARTITION_NONE) const override;

Expand Down
2 changes: 2 additions & 0 deletions Source/Core/DolphinQt/CMakeLists.txt
Expand Up @@ -37,6 +37,8 @@ add_executable(dolphin-emu
MainWindow.h
MenuBar.cpp
MenuBar.h
NKitWarningDialog.cpp
NKitWarningDialog.h
RenderWidget.cpp
RenderWidget.h
Resources.cpp
Expand Down
3 changes: 3 additions & 0 deletions Source/Core/DolphinQt/DolphinQt.vcxproj
Expand Up @@ -178,6 +178,7 @@
<QtMoc Include="NetPlay\NetPlayDialog.h" />
<QtMoc Include="NetPlay\NetPlaySetupDialog.h" />
<QtMoc Include="NetPlay\PadMappingDialog.h" />
<QtMoc Include="NKitWarningDialog.h" />
<QtMoc Include="QtUtils\AspectRatioWidget.h" />
<QtMoc Include="QtUtils\BlockUserInputFilter.h" />
<QtMoc Include="QtUtils\DoubleClickEventFilter.h" />
Expand Down Expand Up @@ -290,6 +291,7 @@
<ClCompile Include="$(QtMocOutPrefix)NetPlaySetupDialog.cpp" />
<ClCompile Include="$(QtMocOutPrefix)NewBreakpointDialog.cpp" />
<ClCompile Include="$(QtMocOutPrefix)NewPatchDialog.cpp" />
<ClCompile Include="$(QtMocOutPrefix)NKitWarningDialog.cpp" />
<ClCompile Include="$(QtMocOutPrefix)PadMappingDialog.cpp" />
<ClCompile Include="$(QtMocOutPrefix)ParallelProgressDialog.cpp" />
<ClCompile Include="$(QtMocOutPrefix)UTF8CodePointCountValidator.cpp" />
Expand Down Expand Up @@ -394,6 +396,7 @@
<ClCompile Include="DiscordJoinRequestDialog.cpp" />
<ClCompile Include="FIFO\FIFOAnalyzer.cpp" />
<ClCompile Include="FIFO\FIFOPlayerWindow.cpp" />
<ClCompile Include="NKitWarningDialog.cpp" />
<ClCompile Include="QtUtils\WinIconHelper.cpp" />
<ClCompile Include="ResourcePackManager.cpp" />
<ClCompile Include="TAS\GCTASInputWindow.cpp" />
Expand Down
11 changes: 11 additions & 0 deletions Source/Core/DolphinQt/MainWindow.cpp
Expand Up @@ -18,6 +18,7 @@

#include <future>
#include <optional>
#include <variant>

#if defined(__unix__) || defined(__unix) || defined(__APPLE__)
#include <signal.h>
Expand Down Expand Up @@ -83,6 +84,7 @@
#include "DolphinQt/HotkeyScheduler.h"
#include "DolphinQt/MainWindow.h"
#include "DolphinQt/MenuBar.h"
#include "DolphinQt/NKitWarningDialog.h"
#include "DolphinQt/NetPlay/NetPlayBrowser.h"
#include "DolphinQt/NetPlay/NetPlayDialog.h"
#include "DolphinQt/NetPlay/NetPlaySetupDialog.h"
Expand Down Expand Up @@ -952,6 +954,15 @@ void MainWindow::StartGame(const std::vector<std::string>& paths,

void MainWindow::StartGame(std::unique_ptr<BootParameters>&& parameters)
{
if (std::holds_alternative<BootParameters::Disc>(parameters->parameters))
{
if (std::get<BootParameters::Disc>(parameters->parameters).volume->IsNKit())
{
if (!NKitWarningDialog::ShowUnlessDisabled())
return;
}
}

// If we're running, only start a new game once we've stopped the last.
if (Core::GetState() != Core::State::Uninitialized)
{
Expand Down
87 changes: 87 additions & 0 deletions Source/Core/DolphinQt/NKitWarningDialog.cpp
@@ -0,0 +1,87 @@
// Copyright 2020 Dolphin Emulator Project
// Licensed under GPLv2+
// Refer to the license.txt file included.

#include "DolphinQt/NKitWarningDialog.h"

#include <QApplication>
#include <QCheckBox>
#include <QHBoxLayout>
#include <QIcon>
#include <QLabel>
#include <QPushButton>
#include <QStyle>
#include <QVBoxLayout>

#include "Common/Config/Config.h"
#include "Core/Config/MainSettings.h"
#include "DolphinQt/Resources.h"

bool NKitWarningDialog::ShowUnlessDisabled(QWidget* parent)
{
if (Config::Get(Config::MAIN_SKIP_NKIT_WARNING))
return true;
else
return NKitWarningDialog(parent).exec() == QDialog::Accepted;
}

NKitWarningDialog::NKitWarningDialog(QWidget* parent) : QDialog(parent)
{
setWindowTitle(tr("NKit Warning"));
setWindowFlags(windowFlags() & ~Qt::WindowContextHelpButtonHint);
setWindowIcon(Resources::GetAppIcon());

QVBoxLayout* main_layout = new QVBoxLayout;

QLabel* warning = new QLabel(
tr("You are about to run an NKit disc image. NKit disc images cause problems that don't "
"happen with normal disc images. These problems include:\n"
"\n"
"• The emulated loading times are longer\n"
"• You can't use NetPlay with people who have normal disc images\n"
"• Input recordings are not compatible between NKit disc images and normal disc images\n"
"• Savestates are not compatible between NKit disc images and normal disc images\n"
"• Some games crash, such as Super Paper Mario\n"
"• Wii games don't work at all in older versions of Dolphin and in many other programs\n"
"\n"
"Are you sure you want to continue anyway?\n"));
warning->setWordWrap(true);
main_layout->addWidget(warning);

QCheckBox* checkbox_accept = new QCheckBox(tr("I am aware of the risks and want to continue"));
main_layout->addWidget(checkbox_accept);

QCheckBox* checkbox_skip = new QCheckBox(tr("Don't show this again"));
main_layout->addWidget(checkbox_skip);

QHBoxLayout* button_layout = new QHBoxLayout;
QPushButton* ok = new QPushButton(tr("OK"));
button_layout->addWidget(ok);
QPushButton* cancel = new QPushButton(tr("Cancel"));
button_layout->addWidget(cancel);
main_layout->addLayout(button_layout);

QHBoxLayout* top_layout = new QHBoxLayout;

QIcon icon = QApplication::style()->standardIcon(QStyle::SP_MessageBoxWarning);
QLabel* icon_label = new QLabel;
icon_label->setPixmap(icon.pixmap(100));
icon_label->setAlignment(Qt::AlignTop);
top_layout->addWidget(icon_label);
top_layout->addSpacing(10);

top_layout->addLayout(main_layout);

setLayout(top_layout);

connect(ok, &QPushButton::clicked, this, &QDialog::accept);
connect(cancel, &QPushButton::clicked, this, &QDialog::reject);

ok->setEnabled(false);
connect(checkbox_accept, &QCheckBox::stateChanged,
[&ok](int state) { ok->setEnabled(state == Qt::Checked); });

connect(this, &QDialog::accepted, [checkbox_skip] {
Config::SetBase(Config::MAIN_SKIP_NKIT_WARNING, checkbox_skip->isChecked());
});
}
19 changes: 19 additions & 0 deletions Source/Core/DolphinQt/NKitWarningDialog.h
@@ -0,0 +1,19 @@
// Copyright 2020 Dolphin Emulator Project
// Licensed under GPLv2+
// Refer to the license.txt file included.

#pragma once

#include <QDialog>
#include <QWidget>

class NKitWarningDialog final : public QDialog
{
Q_OBJECT

public:
static bool ShowUnlessDisabled(QWidget* parent = nullptr);

private:
explicit NKitWarningDialog(QWidget* parent = nullptr);
};

0 comments on commit 9d44df0

Please sign in to comment.