diff --git a/CMakeLists.txt b/CMakeLists.txt index bd3198e..603f542 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -1,8 +1,20 @@ # CMake 3.8 required for 17 to be a valid value for CXX_STANDARD cmake_minimum_required(VERSION 3.8) +list(APPEND CMAKE_MODULE_PATH "${CMAKE_CURRENT_SOURCE_DIR}/CMakeModules") +include(DownloadExternals) +include(CMakeDependentOption) + +if (POLICY CMP0076) + # TODO: set this to NEW + cmake_policy(SET CMP0076 OLD) +endif() project(threeSD) +option(WARNINGS_AS_ERRORS "Treat warnings as errors" ON) +CMAKE_DEPENDENT_OPTION(USE_BUNDLED_QT "Download bundled Qt binaries" ON "MSVC" OFF) +CMAKE_DEPENDENT_OPTION(COMPILE_WITH_DWARF "Add DWARF debugging information" ON "MINGW" OFF) + # Sanity check : Check that all submodules are present # ======================================================================= function(check_submodules_present) @@ -26,6 +38,55 @@ set(CMAKE_CXX_STANDARD_REQUIRED ON) # set up output paths for executable binaries set(CMAKE_RUNTIME_OUTPUT_DIRECTORY ${PROJECT_BINARY_DIR}/bin) +# System imported libraries +# ====================== + +# TODO: Is this necessary? + +# Prefer the -pthread flag on Linux. +set(THREADS_PREFER_PTHREAD_FLAG ON) +find_package(Threads REQUIRED) + +if (USE_BUNDLED_QT) + if ((MSVC_VERSION GREATER_EQUAL 1910 AND MSVC_VERSION LESS 1930) AND ARCHITECTURE_x86_64) + set(QT_VER qt-5.10.0-msvc2017_64) + else() + message(FATAL_ERROR "No bundled Qt binaries for your toolchain. Disable CITRA_USE_BUNDLED_QT and provide your own.") + endif() + + if (DEFINED QT_VER) + download_bundled_external("qt/" ${QT_VER} QT_PREFIX) + endif() + + set(QT_PREFIX_HINT HINTS "${QT_PREFIX}") +else() + # Passing an empty HINTS seems to cause default system paths to get ignored in CMake 2.8 so + # make sure to not pass anything if we don't have one. + set(QT_PREFIX_HINT) +endif() + +find_package(Qt5 REQUIRED COMPONENTS Widgets ${QT_PREFIX_HINT}) + +# Platform-specific library requirements +# ====================================== +# TODO: Check the necessity of these + +if (APPLE) + # Umbrella framework for everything GUI-related + find_library(COCOA_LIBRARY Cocoa) + set(PLATFORM_LIBRARIES ${COCOA_LIBRARY} ${IOKIT_LIBRARY} ${COREVIDEO_LIBRARY}) +elseif (WIN32) + # WSAPoll and SHGetKnownFolderPath (AppData/Roaming) didn't exist before WinNT 6.x (Vista) + add_definitions(-D_WIN32_WINNT=0x0600 -DWINVER=0x0600) + set(PLATFORM_LIBRARIES winmm ws2_32) + if (MINGW) + # PSAPI is the Process Status API + set(PLATFORM_LIBRARIES ${PLATFORM_LIBRARIES} psapi imm32 version) + endif() +elseif (CMAKE_SYSTEM_NAME MATCHES "^(Linux|kFreeBSD|GNU|SunOS)$") + set(PLATFORM_LIBRARIES rt) +endif() + # Include source code # =================== add_subdirectory(externals) diff --git a/CMakeModules/CopyQt5Deps.cmake b/CMakeModules/CopyQt5Deps.cmake new file mode 100644 index 0000000..0d5c25c --- /dev/null +++ b/CMakeModules/CopyQt5Deps.cmake @@ -0,0 +1,32 @@ +function(copy_Qt5_deps target_dir) + include(WindowsCopyFiles) + set(DLL_DEST "${CMAKE_BINARY_DIR}/bin/$/") + set(Qt5_DLL_DIR "${Qt5_DIR}/../../../bin") + set(Qt5_PLATFORMS_DIR "${Qt5_DIR}/../../../plugins/platforms/") + set(Qt5_STYLES_DIR "${Qt5_DIR}/../../../plugins/styles/") + # set(Qt5_IMAGEFORMATS_DIR "${Qt5_DIR}/../../../plugins/imageformats/") + set(PLATFORMS ${DLL_DEST}platforms/) + set(STYLES ${DLL_DEST}styles/) + # set(IMAGEFORMATS ${DLL_DEST}imageformats/) + windows_copy_files(${target_dir} ${Qt5_DLL_DIR} ${DLL_DEST} + icudt*.dll + icuin*.dll + icuuc*.dll + Qt5Core$<$:d>.* + Qt5Gui$<$:d>.* + Qt5Widgets$<$:d>.* + ) + windows_copy_files(citra-qt ${Qt5_PLATFORMS_DIR} ${PLATFORMS} qwindows$<$:d>.*) + windows_copy_files(citra-qt ${Qt5_STYLES_DIR} ${STYLES} qwindowsvistastyle$<$:d>.*) + # windows_copy_files(${target_dir} ${Qt5_IMAGEFORMATS_DIR} ${IMAGEFORMATS} + # qgif$<$:d>.dll + # qicns$<$:d>.dll + # qico$<$:d>.dll + # qjpeg$<$:d>.dll + # qsvg$<$:d>.dll + # qtga$<$:d>.dll + # qtiff$<$:d>.dll + # qwbmp$<$:d>.dll + # qwebp$<$:d>.dll + # ) +endfunction(copy_citra_Qt5_deps) diff --git a/CMakeModules/DownloadExternals.cmake b/CMakeModules/DownloadExternals.cmake new file mode 100644 index 0000000..138a15d --- /dev/null +++ b/CMakeModules/DownloadExternals.cmake @@ -0,0 +1,18 @@ + +# This function downloads a binary library package from our external repo. +# Params: +# remote_path: path to the file to download, relative to the remote repository root +# prefix_var: name of a variable which will be set with the path to the extracted contents +function(download_bundled_external remote_path lib_name prefix_var) +set(prefix "${CMAKE_BINARY_DIR}/externals/${lib_name}") +if (NOT EXISTS "${prefix}") + message(STATUS "Downloading binaries for ${lib_name}...") + file(DOWNLOAD + https://github.com/citra-emu/ext-windows-bin/raw/master/${remote_path}${lib_name}.7z + "${CMAKE_BINARY_DIR}/externals/${lib_name}.7z" SHOW_PROGRESS) + execute_process(COMMAND ${CMAKE_COMMAND} -E tar xf "${CMAKE_BINARY_DIR}/externals/${lib_name}.7z" + WORKING_DIRECTORY "${CMAKE_BINARY_DIR}/externals") +endif() +message(STATUS "Using bundled binaries at ${prefix}") +set(${prefix_var} "${prefix}" PARENT_SCOPE) +endfunction() \ No newline at end of file diff --git a/CMakeModules/WindowsCopyFiles.cmake b/CMakeModules/WindowsCopyFiles.cmake new file mode 100644 index 0000000..cd0c2ce --- /dev/null +++ b/CMakeModules/WindowsCopyFiles.cmake @@ -0,0 +1,28 @@ +# Copyright 2016 Citra Emulator Project +# Licensed under GPLv2 or any later version +# Refer to the license.txt file included. + +# This file provides the function windows_copy_files. +# This is only valid on Windows. + +# Include guard +if(__windows_copy_files) + return() +endif() +set(__windows_copy_files YES) + +# Any number of files to copy from SOURCE_DIR to DEST_DIR can be specified after DEST_DIR. +# This copying happens post-build. +function(windows_copy_files TARGET SOURCE_DIR DEST_DIR) + # windows commandline expects the / to be \ so switch them + string(REPLACE "/" "\\\\" SOURCE_DIR ${SOURCE_DIR}) + string(REPLACE "/" "\\\\" DEST_DIR ${DEST_DIR}) + + # /NJH /NJS /NDL /NFL /NC /NS /NP - Silence any output + # cmake adds an extra check for command success which doesn't work too well with robocopy + # so trick it into thinking the command was successful with the || cmd /c "exit /b 0" + add_custom_command(TARGET ${TARGET} POST_BUILD + COMMAND if not exist ${DEST_DIR} mkdir ${DEST_DIR} 2> nul + COMMAND robocopy ${SOURCE_DIR} ${DEST_DIR} ${ARGN} /NJH /NJS /NDL /NFL /NC /NS /NP || cmd /c "exit /b 0" + ) +endfunction() \ No newline at end of file diff --git a/README.md b/README.md new file mode 100644 index 0000000..ed366e2 --- /dev/null +++ b/README.md @@ -0,0 +1,34 @@ +threeSD +======== + +threeSD is a tool to help prepare your system for the Nintendo 3DS emulator [Citra](https://citra-emu.org). + +## Instructions + +First of all, of course, you should download a [release](https://github.com/zhaowenlan1779/threeSD/releases) of threeSD and extract the archive somewhere. + +### What you'll need + +* Nintendo 3DS with access to CFW and [GodMode9](https://github.com/d0k3/GodMode9) + * If your 3DS is not yet hacked, you can do so by following the instructions [here](https://3ds.hacks.guide). + * You can install GodMode9 by downloading it and copying the `firm` file to `luma/payloads` on your 3DS. You can rename it to begin with `[BUTTON]_` (e.g. `X_GodMode9.firm`) to set a convenicence button to hold during boot to enter GodMode9. +* PC compatible with Citra + * You will need a graphics card compatible with OpenGL 3.3 and install the latest graphics drivers from your vendor's website. + * Operating system requirements: **64-bit** Windows (7+), Linux (flatpak) or macOS (10.13+). Note that Citra on macOS 10.13 is currently broken. It is recommended to update to 10.14. +* SD / microSD card reader + +### On Your 3DS + +You will need to run a GodMode9 script. If you are unsure about the script's safety (which is good!), check the source code yourself [here](https://github.com/zhaowenlan1779/threeSD/blob/master/dist/threeSDumper.gm9). + +1. Copy the gm9 script (`threeSDumper.gm9`) in `dist` to the `gm9/scripts` folder on your SD card. +1. Power up your 3DS to launch GodMode9 (you will need to hold a button corresponding to your `firm` file's name, or hold `START` to enter the chainloader). Press the `Home` button to bring up GodMode9's `HOME Menu`. Use the d-pad and the `A` button to select `Scripts...`. +1. Use the d-pad and the `A` button to select `threeSDumper`. You will be prompted with a question "Execute threeSD Dumper?". Press `A` to confirm. +1. After a moment or two you will see the message "Successfully dumped necessary files for threeSD." Your 3DS SD card is now prepared for use with threeSD and Citra. Press `A` to exit the script. +1. Power off your 3DS with `R+START`. Remove the SD card from your 3DS and insert it into your PC (with a card reader). + +### On your PC + +Make sure the SD card is properly recognized and shows up as a disk. + +1. diff --git a/src/CMakeLists.txt b/src/CMakeLists.txt index fbb37c0..859566c 100644 --- a/src/CMakeLists.txt +++ b/src/CMakeLists.txt @@ -1,9 +1,95 @@ +# Enable modules to include each other's files include_directories(.) -add_executable(threeSD) +# CMake seems to only define _DEBUG on Windows +set_property(DIRECTORY APPEND PROPERTY + COMPILE_DEFINITIONS $<$:_DEBUG> $<$>:NDEBUG>) + +# Set compilation flags +if (MSVC) + set(CMAKE_CONFIGURATION_TYPES Debug Release CACHE STRING "" FORCE) + + # Silence "deprecation" warnings + add_definitions(-D_CRT_SECURE_NO_WARNINGS -D_CRT_NONSTDC_NO_DEPRECATE -D_SCL_SECURE_NO_WARNINGS) + + # Avoid windows.h junk + add_definitions(-DNOMINMAX) + + # Avoid windows.h from including some usually unused libs like winsocks.h, since this might cause some redefinition errors. + add_definitions(-DWIN32_LEAN_AND_MEAN) + + # Ensure that projects build with Unicode support. + add_definitions(-DUNICODE -D_UNICODE) + + # /W3 - Level 3 warnings + # /MP - Multi-threaded compilation + # /Zi - Output debugging information + # /Zo - Enhanced debug info for optimized builds + # /permissive- - Enables stricter C++ standards conformance checks + # /EHsc - C++-only exception handling semantics + # /volatile:iso - Use strict standards-compliant volatile semantics. + # /Zc:externConstexpr - Allow extern constexpr variables to have external linkage, like the standard mandates + # /Zc:inline - Let codegen omit inline functions in object files + # /Zc:throwingNew - Let codegen assume `operator new` (without std::nothrow) will never return null + add_compile_options( + /W3 + /MP + /Zi + /Zo + /permissive- + /EHsc + /std:c++latest + /volatile:iso + /Zc:externConstexpr + /Zc:inline + /Zc:throwingNew + ) + + # /GS- - No stack buffer overflow checks + add_compile_options("$<$:/GS->") + + if (WARNINGS_AS_ERRORS) + add_compile_options(/WX) + endif() + + set(CMAKE_EXE_LINKER_FLAGS_DEBUG "/DEBUG /MANIFEST:NO" CACHE STRING "" FORCE) + set(CMAKE_EXE_LINKER_FLAGS_RELEASE "/DEBUG /MANIFEST:NO /INCREMENTAL:NO /OPT:REF,ICF" CACHE STRING "" FORCE) +else() + add_compile_options( + -Wall + -Wno-attributes + ) + + if (WARNINGS_AS_ERRORS) + add_compile_options(-Werror -Wfatal-errors) + endif() + + if (APPLE AND CMAKE_CXX_COMPILER_ID STREQUAL Clang) + add_compile_options("-stdlib=libc++") + endif() + + # Set file offset size to 64 bits. + # + # On modern Unixes, this is typically already the case. The lone exception is + # glibc, which may default to 32 bits. glibc allows this to be configured + # by setting _FILE_OFFSET_BITS. + if(CMAKE_SYSTEM_NAME STREQUAL "Linux" OR MINGW) + add_definitions(-D_FILE_OFFSET_BITS=64) + endif() + + if (MINGW) + add_definitions(-DMINGW_HAS_SECURE_API) + if (COMPILE_WITH_DWARF) + add_compile_options("-gdwarf") + endif() + + if (MINGW_STATIC_BUILD) + add_definitions(-DQT_STATICPLUGIN) + add_compile_options("-static") + endif() + endif() +endif() add_subdirectory(common) add_subdirectory(core) add_subdirectory(frontend) - -target_link_libraries(threeSD PRIVATE cryptopp fmt) diff --git a/src/common/CMakeLists.txt b/src/common/CMakeLists.txt index aabc5b8..f8b32f7 100644 --- a/src/common/CMakeLists.txt +++ b/src/common/CMakeLists.txt @@ -1,14 +1,16 @@ -target_sources(threeSD PRIVATE - common/assert.h - common/bit_field.h - common/common_funcs.h - common/common_paths.h - common/common_types.h - common/file_util.cpp - common/file_util.h - common/logging/log.h - common/misc.cpp - common/string_util.cpp - common/string_util.h - common/swap.h +add_library(common STATIC + assert.h + bit_field.h + common_funcs.h + common_paths.h + common_types.h + file_util.cpp + file_util.h + logging/log.h + misc.cpp + string_util.cpp + string_util.h + swap.h ) + +target_link_libraries(common PUBLIC fmt) diff --git a/src/core/CMakeLists.txt b/src/core/CMakeLists.txt index 7f35085..37463f4 100644 --- a/src/core/CMakeLists.txt +++ b/src/core/CMakeLists.txt @@ -1,14 +1,16 @@ -target_sources(threeSD PRIVATE - core/data_container.cpp - core/data_container.h - core/decryptor.cpp - core/decryptor.h - core/importer.cpp - core/importer.h - core/inner_fat.cpp - core/inner_fat.h - core/key/arithmetic128.cpp - core/key/arithmetic128.h - core/key/key.cpp - core/key/key.h +add_library(core STATIC + data_container.cpp + data_container.h + decryptor.cpp + decryptor.h + importer.cpp + importer.h + inner_fat.cpp + inner_fat.h + key/arithmetic128.cpp + key/arithmetic128.h + key/key.cpp + key/key.h ) + +target_link_libraries(core PRIVATE common cryptopp) diff --git a/src/core/importer.cpp b/src/core/importer.cpp index 6a39bee..1a0bf5d 100644 --- a/src/core/importer.cpp +++ b/src/core/importer.cpp @@ -2,6 +2,7 @@ // Licensed under GPLv2 or any later version // Refer to the license.txt file included. +#include #include "common/assert.h" #include "common/common_paths.h" #include "common/file_util.h" @@ -17,7 +18,7 @@ SDMCImporter::SDMCImporter(const Config& config_) : config(config_) { SDMCImporter::~SDMCImporter() = default; bool SDMCImporter::Init() { - ASSERT_MSG(config.is_good && !config.sdmc_path.empty() && !config.user_path.empty() && + ASSERT_MSG(!config.sdmc_path.empty() && !config.user_path.empty() && !config.bootrom_path.empty() && !config.movable_sed_path.empty(), "Config is not good"); @@ -245,3 +246,75 @@ void SDMCImporter::ListSysdata(std::vector& out) const { #undef CHECK_CONTENT } + +std::vector LoadPresetConfig(std::string mount_point) { + if (mount_point.back() != '/' && mount_point.back() != '\\') { + mount_point += '/'; + } + + // Not a Nintendo 3DS sd card at all + if (!FileUtil::Exists(mount_point + "Nintendo 3DS/")) { + return {}; + } + + Config config_template{}; + config_template.user_path = FileUtil::GetUserPath(FileUtil::UserPath::UserDir); + + // Load dumped data paths if using our dumper + if (FileUtil::Exists(mount_point + "threeSD/")) { +#define LOAD_DATA(var, path) \ + if (FileUtil::Exists(mount_point + "threeSD/" + path)) { \ + config_template.var = mount_point + "threeSD/" + path; \ + } + + LOAD_DATA(movable_sed_path, MOVABLE_SED); + LOAD_DATA(bootrom_path, BOOTROM9); + LOAD_DATA(safe_mode_firm_path, "firm/"); + LOAD_DATA(seed_db_path, SEED_DB); + LOAD_DATA(secret_sector_path, SECRET_SECTOR); +#undef LOAD_DATA + } + + // Regex for 3DS ID0 and ID1 + const std::regex id_regex{"[0-9a-f]{32}"}; + + // Load SDMC dir + std::vector out; + const auto ProcessDirectory = [&id_regex, &config_template, &out](const std::string& path) { + return FileUtil::ForeachDirectoryEntry( + nullptr, path, + [&id_regex, &config_template, &out](u64* /*num_entries_out*/, + const std::string& directory, + const std::string& virtual_name) { + if (!FileUtil::IsDirectory(directory + virtual_name)) { + return true; + } + + if (!std::regex_match(virtual_name, id_regex)) { + return true; + } + + Config config = config_template; + config.sdmc_path = directory + virtual_name + "/"; + out.push_back(config); + return true; + }); + }; + + FileUtil::ForeachDirectoryEntry( + nullptr, mount_point + "Nintendo 3DS/", + [&id_regex, &ProcessDirectory](u64* /*num_entries_out*/, const std::string& directory, + const std::string& virtual_name) { + if (!FileUtil::IsDirectory(directory + virtual_name)) { + return true; + } + + if (!std::regex_match(virtual_name, id_regex)) { + return true; + } + + return ProcessDirectory(directory + virtual_name); + }); + + return out; +} diff --git a/src/core/importer.h b/src/core/importer.h index 77c86ea..9707654 100644 --- a/src/core/importer.h +++ b/src/core/importer.h @@ -51,9 +51,6 @@ struct Config { std::string safe_mode_firm_path; ///< Path to safe mode firm (A folder) (Sysdata 1) std::string seed_db_path; ///< Path to seeddb.bin (Sysdata 2) std::string secret_sector_path; ///< Path to secret sector (New3DS only) (Sysdata 3) - - // Whether this config has all necessary information - bool is_good; }; class SDMCImporter { @@ -96,3 +93,9 @@ private: Config config; std::unique_ptr decryptor; }; + +/** + * Look for and load preset config for a SD card mounted at mount_point. + * @return a list of preset config available. can be empty + */ +std::vector LoadPresetConfig(std::string mount_point); diff --git a/src/core/key/key.cpp b/src/core/key/key.cpp index 38c7483..eb44b4c 100644 --- a/src/core/key/key.cpp +++ b/src/core/key/key.cpp @@ -31,7 +31,8 @@ struct KeyDesc { bool same_as_before; }; -AESKey HexToKey(const std::string& hex) { +// TODO: Use this to support manual input of keys +[[maybe_unused]] AESKey HexToKey(const std::string& hex) { if (hex.size() < 32) { throw std::invalid_argument("hex string is too short"); } diff --git a/src/frontend/CMakeLists.txt b/src/frontend/CMakeLists.txt index b6ed1d3..43cf8ca 100644 --- a/src/frontend/CMakeLists.txt +++ b/src/frontend/CMakeLists.txt @@ -1,3 +1,54 @@ -target_sources(threeSD PRIVATE - frontend/main.cpp +set(CMAKE_AUTOMOC ON) +set(CMAKE_AUTORCC ON) +set(CMAKE_AUTOUIC ON) +set(CMAKE_INCLUDE_CURRENT_DIR ON) +if (POLICY CMP0071) + cmake_policy(SET CMP0071 NEW) +endif() + +add_executable(threeSD + main.cpp + main.h + main.ui ) + +target_link_libraries(threeSD PRIVATE common core) +target_link_libraries(threeSD PRIVATE Qt5::Widgets) +target_link_libraries(threeSD PRIVATE ${PLATFORM_LIBRARIES} Threads::Threads) + +if (APPLE) + # TODO: support macOS + # set(MACOSX_ICON "../../dist/citra.icns") + # set_source_files_properties(${MACOSX_ICON} PROPERTIES MACOSX_PACKAGE_LOCATION Resources) + # target_sources(threeSD PRIVATE ${MACOSX_ICON}) + # set_target_properties(threeSD PROPERTIES MACOSX_BUNDLE TRUE) + # set_target_properties(threeSD PROPERTIES MACOSX_BUNDLE_INFO_PLIST ${CMAKE_CURRENT_SOURCE_DIR}/Info.plist) +elseif(WIN32) + # compile as a win32 gui application instead of a console application + target_link_libraries(threeSD PRIVATE Qt5::WinMain) + if(MSVC) + set_target_properties(threeSD PROPERTIES LINK_FLAGS_RELEASE "/SUBSYSTEM:WINDOWS") + elseif(MINGW) + set_target_properties(threeSD PROPERTIES LINK_FLAGS_RELEASE "-mwindows") + endif() +endif() + +target_compile_definitions(threeSD PRIVATE + # Use QStringBuilder for string concatenation to reduce + # the overall number of temporary strings created. + -DQT_USE_QSTRINGBUILDER + + # Disable implicit type narrowing in signal/slot connect() calls. + -DQT_NO_NARROWING_CONVERSIONS_IN_CONNECT + + # Disable unsafe overloads of QProcess' start() function. + -DQT_NO_PROCESS_COMBINED_ARGUMENT_START + + # Disable implicit QString->QUrl conversions to enforce use of proper resolving functions. + -DQT_NO_URL_CAST_FROM_STRING +) + +if (MSVC) + include(CopyQt5Deps) + copy_Qt5_deps(threeSD) +endif() diff --git a/src/frontend/main.cpp b/src/frontend/main.cpp index 4745cc8..f900b39 100644 --- a/src/frontend/main.cpp +++ b/src/frontend/main.cpp @@ -1,14 +1,38 @@ -// Dummy +// Copyright 2014 Citra Emulator Project / 2019 threeSD Project +// Licensed under GPLv2 or any later version +// Refer to the license.txt file included. -#include -#include "common/logging/log.h" +#include +#include "frontend/main.h" +#include "ui_main.h" -int main() { +#ifdef __APPLE__ +#include +#include +#include "common/common_paths.h" +#include "common/file_util.h" +#endif - LOG_ERROR(Frontend, "test"); - _sleep(1000); - LOG_WARNING(Frontend, "test2"); - system("pause"); +MainDialog::MainDialog(QWidget* parent) : QDialog(parent), ui(std::make_unique()) { + ui->setupUi(this); +} - return 0; -} \ No newline at end of file +MainDialog::~MainDialog() = default; + +int main(int argc, char* argv[]) { + // Init settings params + QCoreApplication::setOrganizationName("zhaowenlan1779"); + QCoreApplication::setApplicationName("threeSD"); + +#ifdef __APPLE__ + std::string bin_path = FileUtil::GetBundleDirectory() + DIR_SEP + ".."; + chdir(bin_path.c_str()); +#endif + + QApplication app(argc, argv); + + MainDialog main_dialog; + main_dialog.show(); + + return app.exec(); +} diff --git a/src/frontend/main.h b/src/frontend/main.h new file mode 100644 index 0000000..4c1d80f --- /dev/null +++ b/src/frontend/main.h @@ -0,0 +1,23 @@ +// Copyright 2019 threeSD Project +// Licensed under GPLv2 or any later version +// Refer to the license.txt file included. + +#pragma once + +#include +#include + +namespace Ui { +class MainDialog; +} + +class MainDialog : public QDialog { + Q_OBJECT; + +public: + explicit MainDialog(QWidget* parent = nullptr); + ~MainDialog() override; + +private: + std::unique_ptr ui; +}; diff --git a/src/frontend/main.ui b/src/frontend/main.ui new file mode 100644 index 0000000..e7f4aef --- /dev/null +++ b/src/frontend/main.ui @@ -0,0 +1,239 @@ + + + MainDialog + + + + 0 + 0 + 800 + 450 + + + + threeSD + + + + + + + + Auto-detected Configuration: + + + + + + + + 0 + 0 + + + + + + + + + + + + Advanced... + + + + + + + Qt::Horizontal + + + + + + + + + Custom + + + false + + + + + + + + SDMC: + + + + + + + + + + ... + + + + + + + + + + + User Directory: + + + + + + + + + + ... + + + + + + + + + + + movable.sed: + + + + + + + + + + ... + + + + + + + + + + + boot9.bin: + + + + + + + + + + ... + + + + + + + + + + + Safe mode firm Path: + + + + + + + + + + ... + + + + + + + + + + + seeddb.bin: + + + + + + + + + + ... + + + + + + + + + + + sector0x96.bin: + + + + + + + + + + ... + + + + + + + + + + + + QDialogButtonBox::Ok|QDialogButtonBox::Reset + + + + + + + Qt::Vertical + + + + 0 + 0 + + + + + + + + +