diff options
26 files changed, 260 insertions, 190 deletions
diff --git a/CMakeLists.txt b/CMakeLists.txt index fa6463b01..604362e57 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -74,7 +74,7 @@ if (NOT MSVC) endif() else() # Silence "deprecation" warnings - add_definitions(/D_CRT_SECURE_NO_WARNINGS /D_CRT_NONSTDC_NO_DEPRECATE) + add_definitions(/D_CRT_SECURE_NO_WARNINGS /D_CRT_NONSTDC_NO_DEPRECATE /D_SCL_SECURE_NO_WARNINGS) # Avoid windows.h junk add_definitions(/DNOMINMAX) diff --git a/appveyor.yml b/appveyor.yml index 6e073ece7..d05cc2213 100644 --- a/appveyor.yml +++ b/appveyor.yml @@ -2,7 +2,6 @@ clone_depth: 5 environment: - QTDIR: C:\Qt\5.4\msvc2013_64_opengl BUILD_PASSWORD: secure: EXGNlWKJsCtbeImEJ5EP9qrxZ+EqUFfNy+CP61nDOMA= @@ -18,7 +17,7 @@ install: before_build: - mkdir build - cd build - - cmake -G "Visual Studio 12 Win64" -DCITRA_USE_BUNDLED_GLFW=1 -DQt5_DIR=%QTDIR%/lib/cmake/Qt5 .. + - cmake -G "Visual Studio 14 Win64" -DCITRA_USE_BUNDLED_GLFW=1 -DCITRA_USE_BUNDLED_QT=1 .. - cd .. after_build: diff --git a/src/citra_qt/bootmanager.cpp b/src/citra_qt/bootmanager.cpp index 7a1360d34..b19b367e1 100644 --- a/src/citra_qt/bootmanager.cpp +++ b/src/citra_qt/bootmanager.cpp @@ -19,8 +19,8 @@ #include "core/settings.h" #include "core/system.h" -#include "video_core/video_core.h" #include "video_core/debug_utils/debug_utils.h" +#include "video_core/video_core.h" #define APP_NAME "citra" #define APP_VERSION "0.1-" VERSION @@ -86,6 +86,9 @@ public: } void paintEvent(QPaintEvent* ev) override { + if (do_painting) { + QPainter painter(this); + } } void resizeEvent(QResizeEvent* ev) override { @@ -93,8 +96,12 @@ public: parent->OnFramebufferSizeChanged(); } + void DisablePainting() { do_painting = false; } + void EnablePainting() { do_painting = true; } + private: GRenderWindow* parent; + bool do_painting; }; GRenderWindow::GRenderWindow(QWidget* parent, EmuThread* emu_thread) : @@ -128,9 +135,6 @@ GRenderWindow::GRenderWindow(QWidget* parent, EmuThread* emu_thread) : BackupGeometry(); -#if QT_VERSION >= QT_VERSION_CHECK(5, 0, 0) - connect(this->windowHandle(), SIGNAL(screenChanged(QScreen*)), this, SLOT(OnFramebufferSizeChanged())); -#endif } void GRenderWindow::moveContext() @@ -273,8 +277,19 @@ void GRenderWindow::OnMinimalClientAreaChangeRequest(const std::pair<unsigned,un void GRenderWindow::OnEmulationStarting(EmuThread* emu_thread) { this->emu_thread = emu_thread; + child->DisablePainting(); } void GRenderWindow::OnEmulationStopping() { emu_thread = nullptr; + child->EnablePainting(); +} + +void GRenderWindow::showEvent(QShowEvent * event) { + QWidget::showEvent(event); + + // windowHandle() is not initialized until the Window is shown, so we connect it here. + #if QT_VERSION >= QT_VERSION_CHECK(5, 0, 0) + connect(this->windowHandle(), SIGNAL(screenChanged(QScreen*)), this, SLOT(OnFramebufferSizeChanged()), Qt::UniqueConnection); + #endif } diff --git a/src/citra_qt/bootmanager.h b/src/citra_qt/bootmanager.h index dc422358e..0a9d263b8 100644 --- a/src/citra_qt/bootmanager.h +++ b/src/citra_qt/bootmanager.h @@ -12,11 +12,12 @@ #include "common/emu_window.h" #include "common/thread.h" -class QScreen; class QKeyEvent; +class QScreen; -class GRenderWindow; +class GGLWidgetInternal; class GMainWindow; +class GRenderWindow; class EmuThread : public QThread { @@ -123,13 +124,12 @@ public: void OnClientAreaResized(unsigned width, unsigned height); - void OnFramebufferSizeChanged(); - public slots: void moveContext(); // overridden void OnEmulationStarting(EmuThread* emu_thread); void OnEmulationStopping(); + void OnFramebufferSizeChanged(); signals: /// Emitted when the window is closed @@ -138,7 +138,7 @@ signals: private: void OnMinimalClientAreaChangeRequest(const std::pair<unsigned,unsigned>& minimal_size) override; - QGLWidget* child; + GGLWidgetInternal* child; QByteArray geometry; @@ -146,4 +146,7 @@ private: int keyboard_id; EmuThread* emu_thread; + +protected: + void showEvent(QShowEvent* event) override; }; diff --git a/src/common/file_util.cpp b/src/common/file_util.cpp index 2fbb0f260..1e0d33313 100644 --- a/src/common/file_util.cpp +++ b/src/common/file_util.cpp @@ -821,8 +821,8 @@ void SplitFilename83(const std::string& filename, std::array<char, 9>& short_nam const std::string forbidden_characters = ".\"/\\[]:;=, "; // On a FAT32 partition, 8.3 names are stored as a 11 bytes array, filled with spaces. - short_name = {' ', ' ', ' ', ' ', ' ', ' ', ' ', ' ', '\0'}; - extension = {' ', ' ', ' ', '\0'}; + short_name = {{' ', ' ', ' ', ' ', ' ', ' ', ' ', ' ', '\0'}}; + extension = {{' ', ' ', ' ', '\0'}}; std::string::size_type point = filename.rfind('.'); if (point == filename.size() - 1) diff --git a/src/common/hash.cpp b/src/common/hash.cpp index 413e9c6f1..c49c2f60e 100644 --- a/src/common/hash.cpp +++ b/src/common/hash.cpp @@ -17,27 +17,11 @@ namespace Common { // Block read - if your platform needs to do endian-swapping or can only handle aligned reads, do // the conversion here - -static FORCE_INLINE u32 getblock32(const u32* p, int i) { - return p[i]; -} - static FORCE_INLINE u64 getblock64(const u64* p, int i) { return p[i]; } // Finalization mix - force all bits of a hash block to avalanche - -static FORCE_INLINE u32 fmix32(u32 h) { - h ^= h >> 16; - h *= 0x85ebca6b; - h ^= h >> 13; - h *= 0xc2b2ae35; - h ^= h >> 16; - - return h; -} - static FORCE_INLINE u64 fmix64(u64 k) { k ^= k >> 33; k *= 0xff51afd7ed558ccdllu; diff --git a/src/common/symbols.cpp b/src/common/symbols.cpp index f23e51c9d..db8340043 100644 --- a/src/common/symbols.cpp +++ b/src/common/symbols.cpp @@ -8,46 +8,43 @@ TSymbolsMap g_symbols; namespace Symbols { - bool HasSymbol(u32 _address) + bool HasSymbol(u32 address) { - return g_symbols.find(_address) != g_symbols.end(); + return g_symbols.find(address) != g_symbols.end(); } - void Add(u32 _address, const std::string& _name, u32 _size, u32 _type) + void Add(u32 address, const std::string& name, u32 size, u32 type) { - if (!HasSymbol(_address)) + if (!HasSymbol(address)) { TSymbol symbol; - symbol.address = _address; - symbol.name = _name; - symbol.size = _size; - symbol.type = _type; + symbol.address = address; + symbol.name = name; + symbol.size = size; + symbol.type = type; - g_symbols.insert(TSymbolsPair(_address, symbol)); + g_symbols.emplace(address, symbol); } } - TSymbol GetSymbol(u32 _address) + TSymbol GetSymbol(u32 address) { - TSymbolsMap::iterator foundSymbolItr; - TSymbol symbol; + const auto iter = g_symbols.find(address); - foundSymbolItr = g_symbols.find(_address); - if (foundSymbolItr != g_symbols.end()) - { - symbol = (*foundSymbolItr).second; - } + if (iter != g_symbols.end()) + return iter->second; - return symbol; + return {}; } - const std::string GetName(u32 _address) + + const std::string GetName(u32 address) { - return GetSymbol(_address).name; + return GetSymbol(address).name; } - void Remove(u32 _address) + void Remove(u32 address) { - g_symbols.erase(_address); + g_symbols.erase(address); } void Clear() diff --git a/src/common/symbols.h b/src/common/symbols.h index 6b62b011e..5ed16009c 100644 --- a/src/common/symbols.h +++ b/src/common/symbols.h @@ -12,15 +12,10 @@ struct TSymbol { - TSymbol() : - address(0), - size(0), - type(0) - {} - u32 address; + u32 address = 0; std::string name; - u32 size; - u32 type; + u32 size = 0; + u32 type = 0; }; typedef std::map<u32, TSymbol> TSymbolsMap; @@ -28,12 +23,12 @@ typedef std::pair<u32, TSymbol> TSymbolsPair; namespace Symbols { - bool HasSymbol(u32 _address); + bool HasSymbol(u32 address); - void Add(u32 _address, const std::string& _name, u32 _size, u32 _type); - TSymbol GetSymbol(u32 _address); - const std::string GetName(u32 _address); - void Remove(u32 _address); + void Add(u32 address, const std::string& name, u32 size, u32 type); + TSymbol GetSymbol(u32 address); + const std::string GetName(u32 address); + void Remove(u32 address); void Clear(); } diff --git a/src/core/arm/skyeye_common/armstate.h b/src/core/arm/skyeye_common/armstate.h index b364e2621..ceb159d14 100644 --- a/src/core/arm/skyeye_common/armstate.h +++ b/src/core/arm/skyeye_common/armstate.h @@ -247,6 +247,5 @@ private: static const u32 RESERVATION_GRANULE_MASK = 0xFFFFFFF8; u32 exclusive_tag; // The address for which the local monitor is in exclusive access mode - u32 exclusive_result; bool exclusive_state; }; diff --git a/src/core/core_timing.cpp b/src/core/core_timing.cpp index 56615502c..aba22cdd1 100644 --- a/src/core/core_timing.cpp +++ b/src/core/core_timing.cpp @@ -3,6 +3,7 @@ // Refer to the license.txt file included. #include <atomic> +#include <cinttypes> #include <mutex> #include <vector> @@ -530,7 +531,7 @@ void Idle(int max_idle) { } } - LOG_TRACE(Core_Timing, "Idle for %i cycles! (%f ms)", cycles_down, cycles_down / (float)(g_clock_rate_arm11 * 0.001f)); + LOG_TRACE(Core_Timing, "Idle for %" PRId64 " cycles! (%f ms)", cycles_down, cycles_down / (float)(g_clock_rate_arm11 * 0.001f)); idled_cycles += cycles_down; Core::g_app_core->down_count -= cycles_down; diff --git a/src/core/file_sys/ivfc_archive.cpp b/src/core/file_sys/ivfc_archive.cpp index e16aa1491..441ca9b53 100644 --- a/src/core/file_sys/ivfc_archive.cpp +++ b/src/core/file_sys/ivfc_archive.cpp @@ -62,7 +62,7 @@ std::unique_ptr<DirectoryBackend> IVFCArchive::OpenDirectory(const Path& path) c //////////////////////////////////////////////////////////////////////////////////////////////////// size_t IVFCFile::Read(const u64 offset, const size_t length, u8* buffer) const { - LOG_TRACE(Service_FS, "called offset=%llu, length=%d", offset, length); + LOG_TRACE(Service_FS, "called offset=%llu, length=%zu", offset, length); romfs_file->Seek(data_offset + offset, SEEK_SET); size_t read_length = (size_t)std::min((u64)length, data_size - offset); diff --git a/src/core/hle/kernel/timer.cpp b/src/core/hle/kernel/timer.cpp index 8aa4110a6..08b3ea8c0 100644 --- a/src/core/hle/kernel/timer.cpp +++ b/src/core/hle/kernel/timer.cpp @@ -2,6 +2,8 @@ // Licensed under GPLv2 or any later version // Refer to the license.txt file included. +#include <cinttypes> + #include "common/assert.h" #include "common/logging/log.h" @@ -71,11 +73,11 @@ static void TimerCallback(u64 timer_handle, int cycles_late) { SharedPtr<Timer> timer = timer_callback_handle_table.Get<Timer>(static_cast<Handle>(timer_handle)); if (timer == nullptr) { - LOG_CRITICAL(Kernel, "Callback fired for invalid timer %08lX", timer_handle); + LOG_CRITICAL(Kernel, "Callback fired for invalid timer %08" PRIx64, timer_handle); return; } - LOG_TRACE(Kernel, "Timer %u fired", timer_handle); + LOG_TRACE(Kernel, "Timer %08" PRIx64 " fired", timer_handle); timer->signaled = true; diff --git a/src/core/hle/service/cfg/cfg.cpp b/src/core/hle/service/cfg/cfg.cpp index 62ad90fdc..56986a49e 100644 --- a/src/core/hle/service/cfg/cfg.cpp +++ b/src/core/hle/service/cfg/cfg.cpp @@ -21,28 +21,67 @@ namespace Service { namespace CFG { -const u64 CFG_SAVE_ID = 0x00010017; -const u64 CONSOLE_UNIQUE_ID = 0xDEADC0DE; -const ConsoleModelInfo CONSOLE_MODEL = { NINTENDO_3DS_XL, { 0, 0, 0 } }; -const u8 CONSOLE_LANGUAGE = LANGUAGE_EN; -const char CONSOLE_USERNAME[0x14] = "CITRA"; +/// The maximum number of block entries that can exist in the config file +static const u32 CONFIG_FILE_MAX_BLOCK_ENTRIES = 1479; + +namespace { + +/** + * The header of the config savedata file, + * contains information about the blocks in the file + */ +struct SaveFileConfig { + u16 total_entries; ///< The total number of set entries in the config file + u16 data_entries_offset; ///< The offset where the data for the blocks start, this is hardcoded to 0x455C as per hardware + SaveConfigBlockEntry block_entries[CONFIG_FILE_MAX_BLOCK_ENTRIES]; ///< The block headers, the maximum possible value is 1479 as per hardware + u32 unknown; ///< This field is unknown, possibly padding, 0 has been observed in hardware +}; +static_assert(sizeof(SaveFileConfig) == 0x455C, "SaveFileConfig header must be exactly 0x455C bytes"); + +struct UsernameBlock { + char16_t username[10]; ///< Exactly 20 bytes long, padded with zeros at the end if necessary + u32 zero; + u32 ng_word; +}; +static_assert(sizeof(UsernameBlock) == 0x1C, "UsernameBlock must be exactly 0x1C bytes"); + +struct ConsoleModelInfo { + u8 model; ///< The console model (3DS, 2DS, etc) + u8 unknown[3]; ///< Unknown data +}; +static_assert(sizeof(ConsoleModelInfo) == 4, "ConsoleModelInfo must be exactly 4 bytes"); + +struct ConsoleCountryInfo { + u8 unknown[3]; ///< Unknown data + u8 country_code; ///< The country code of the console +}; +static_assert(sizeof(ConsoleCountryInfo) == 4, "ConsoleCountryInfo must be exactly 4 bytes"); + +} + +static const u64 CFG_SAVE_ID = 0x00010017; +static const u64 CONSOLE_UNIQUE_ID = 0xDEADC0DE; +static const ConsoleModelInfo CONSOLE_MODEL = { NINTENDO_3DS_XL, { 0, 0, 0 } }; +static const u8 CONSOLE_LANGUAGE = LANGUAGE_EN; +static const char CONSOLE_USERNAME[0x14] = "CITRA"; /// This will be initialized in Init, and will be used when creating the block -UsernameBlock CONSOLE_USERNAME_BLOCK; +static UsernameBlock CONSOLE_USERNAME_BLOCK; /// TODO(Subv): Find out what this actually is -const u8 SOUND_OUTPUT_MODE = 2; -const u8 UNITED_STATES_COUNTRY_ID = 49; +static const u8 SOUND_OUTPUT_MODE = 2; +static const u8 UNITED_STATES_COUNTRY_ID = 49; /// TODO(Subv): Find what the other bytes are -const ConsoleCountryInfo COUNTRY_INFO = { { 0, 0, 0 }, UNITED_STATES_COUNTRY_ID }; +static const ConsoleCountryInfo COUNTRY_INFO = { { 0, 0, 0 }, UNITED_STATES_COUNTRY_ID }; /** * TODO(Subv): Find out what this actually is, these values fix some NaN uniforms in some games, * for example Nintendo Zone * Thanks Normmatt for providing this information */ -const std::array<float, 8> STEREO_CAMERA_SETTINGS = { +static const std::array<float, 8> STEREO_CAMERA_SETTINGS = {{ 62.0f, 289.0f, 76.80000305175781f, 46.08000183105469f, 10.0f, 5.0f, 55.58000183105469f, 21.56999969482422f -}; +}}; +static_assert(sizeof(STEREO_CAMERA_SETTINGS) == 0x20, "STEREO_CAMERA_SETTINGS must be exactly 0x20 bytes"); static const u32 CONFIG_SAVEFILE_SIZE = 0x8000; static std::array<u8, CONFIG_SAVEFILE_SIZE> cfg_config_file_buffer; @@ -212,7 +251,7 @@ ResultCode GetConfigInfoBlock(u32 block_id, u32 size, u32 flag, u8* output) { return RESULT_SUCCESS; } -ResultCode CreateConfigInfoBlk(u32 block_id, u16 size, u16 flags, const u8* data) { +ResultCode CreateConfigInfoBlk(u32 block_id, u16 size, u16 flags, const void* data) { SaveFileConfig* config = reinterpret_cast<SaveFileConfig*>(cfg_config_file_buffer.data()); if (config->total_entries >= CONFIG_FILE_MAX_BLOCK_ENTRIES) return ResultCode(-1); // TODO(Subv): Find the right error code @@ -277,33 +316,63 @@ ResultCode FormatConfig() { SaveFileConfig* config = reinterpret_cast<SaveFileConfig*>(cfg_config_file_buffer.data()); // This value is hardcoded, taken from 3dbrew, verified by hardware, it's always the same value config->data_entries_offset = 0x455C; + // Insert the default blocks - res = CreateConfigInfoBlk(0x00050005, sizeof(STEREO_CAMERA_SETTINGS), 0xE, - reinterpret_cast<const u8*>(STEREO_CAMERA_SETTINGS.data())); - if (!res.IsSuccess()) - return res; - res = CreateConfigInfoBlk(0x00090001, sizeof(CONSOLE_UNIQUE_ID), 0xE, - reinterpret_cast<const u8*>(&CONSOLE_UNIQUE_ID)); - if (!res.IsSuccess()) - return res; - res = CreateConfigInfoBlk(0x000F0004, sizeof(CONSOLE_MODEL), 0x8, - reinterpret_cast<const u8*>(&CONSOLE_MODEL)); - if (!res.IsSuccess()) - return res; - res = CreateConfigInfoBlk(0x000A0002, sizeof(CONSOLE_LANGUAGE), 0xA, &CONSOLE_LANGUAGE); - if (!res.IsSuccess()) - return res; + u8 zero_buffer[0xC0] = {}; + + // 0x00030001 - Unknown + res = CreateConfigInfoBlk(0x00030001, 0x8, 0xE, zero_buffer); + if (!res.IsSuccess()) return res; + + res = CreateConfigInfoBlk(0x00050005, sizeof(STEREO_CAMERA_SETTINGS), 0xE, STEREO_CAMERA_SETTINGS.data()); + if (!res.IsSuccess()) return res; res = CreateConfigInfoBlk(0x00070001, sizeof(SOUND_OUTPUT_MODE), 0xE, &SOUND_OUTPUT_MODE); - if (!res.IsSuccess()) - return res; - res = CreateConfigInfoBlk(0x000B0000, sizeof(COUNTRY_INFO), 0xE, - reinterpret_cast<const u8*>(&COUNTRY_INFO)); - if (!res.IsSuccess()) - return res; - res = CreateConfigInfoBlk(0x000A0000, sizeof(CONSOLE_USERNAME_BLOCK), 0xE, - reinterpret_cast<const u8*>(&CONSOLE_USERNAME_BLOCK)); - if (!res.IsSuccess()) - return res; + if (!res.IsSuccess()) return res; + res = CreateConfigInfoBlk(0x00090001, sizeof(CONSOLE_UNIQUE_ID), 0xE, &CONSOLE_UNIQUE_ID); + if (!res.IsSuccess()) return res; + res = CreateConfigInfoBlk(0x000A0000, sizeof(CONSOLE_USERNAME_BLOCK), 0xE, &CONSOLE_USERNAME_BLOCK); + if (!res.IsSuccess()) return res; + + // 0x000A0001 - Profile birthday + const u8 profile_birthday[2] = {3, 25}; // March 25th, 2014 + res = CreateConfigInfoBlk(0x000A0001, sizeof(profile_birthday), 0xE, profile_birthday); + if (!res.IsSuccess()) return res; + + res = CreateConfigInfoBlk(0x000A0002, sizeof(CONSOLE_LANGUAGE), 0xE, &CONSOLE_LANGUAGE); + if (!res.IsSuccess()) return res; + res = CreateConfigInfoBlk(0x000B0000, sizeof(COUNTRY_INFO), 0xE, &COUNTRY_INFO); + if (!res.IsSuccess()) return res; + + char16_t country_name_buffer[16][0x40] = {}; + for (size_t i = 0; i < 16; ++i) { + Common::UTF8ToUTF16("Gensokyo").copy(country_name_buffer[i], 0x40); + } + // 0x000B0001 - Localized names for the profile Country + res = CreateConfigInfoBlk(0x000B0001, sizeof(country_name_buffer), 0xE, country_name_buffer); + if (!res.IsSuccess()) return res; + // 0x000B0002 - Localized names for the profile State/Province + res = CreateConfigInfoBlk(0x000B0002, sizeof(country_name_buffer), 0xE, country_name_buffer); + if (!res.IsSuccess()) return res; + + // 0x000B0003 - Unknown, related to country/address (zip code?) + res = CreateConfigInfoBlk(0x000B0003, 0x4, 0xE, zero_buffer); + if (!res.IsSuccess()) return res; + + // 0x000C0000 - Unknown + res = CreateConfigInfoBlk(0x000C0000, 0xC0, 0xE, zero_buffer); + if (!res.IsSuccess()) return res; + + // 0x000C0001 - Unknown + res = CreateConfigInfoBlk(0x000C0001, 0x14, 0xE, zero_buffer); + if (!res.IsSuccess()) return res; + + // 0x000D0000 - Accepted EULA version + res = CreateConfigInfoBlk(0x000D0000, 0x4, 0xE, zero_buffer); + if (!res.IsSuccess()) return res; + + res = CreateConfigInfoBlk(0x000F0004, sizeof(CONSOLE_MODEL), 0xC, &CONSOLE_MODEL); + if (!res.IsSuccess()) return res; + // Save the buffer to the file res = UpdateConfigNANDSavegame(); if (!res.IsSuccess()) diff --git a/src/core/hle/service/cfg/cfg.h b/src/core/hle/service/cfg/cfg.h index ff76dc9dc..fc2a16a04 100644 --- a/src/core/hle/service/cfg/cfg.h +++ b/src/core/hle/service/cfg/cfg.h @@ -41,10 +41,11 @@ struct SaveConfigBlockEntry { u16 flags; ///< The flags of the block, possibly used for access control }; -// TODO(Link Mauve): use a constexpr once MSVC starts supporting it. -#define C(code) ((code)[0] | ((code)[1] << 8)) +static constexpr u16 C(const char code[2]) { + return code[0] | (code[1] << 8); +} -static const std::array<u16, 187> country_codes = { +static const std::array<u16, 187> country_codes = {{ 0, C("JP"), 0, 0, 0, 0, 0, 0, // 0-7 C("AI"), C("AG"), C("AR"), C("AW"), C("BS"), C("BB"), C("BZ"), C("BO"), // 8-15 C("BR"), C("VG"), C("CA"), C("KY"), C("CL"), C("CO"), C("CR"), C("DM"), // 16-23 @@ -69,9 +70,7 @@ static const std::array<u16, 187> country_codes = { C("AE"), C("IN"), C("EG"), C("OM"), C("QA"), C("KW"), C("SA"), C("SY"), // 168-175 C("BH"), C("JO"), 0, 0, 0, 0, 0, 0, // 176-183 C("SM"), C("VA"), C("BM") // 184-186 -}; - -#undef C +}}; /** * CFG::GetCountryCodeString service function @@ -204,59 +203,6 @@ void UpdateConfigNANDSavegame(Service::Interface* self); */ void FormatConfig(Service::Interface* self); -/// The maximum number of block entries that can exist in the config file -static const u32 CONFIG_FILE_MAX_BLOCK_ENTRIES = 1479; - -/** -* The header of the config savedata file, -* contains information about the blocks in the file -*/ -struct SaveFileConfig { - u16 total_entries; ///< The total number of set entries in the config file - u16 data_entries_offset; ///< The offset where the data for the blocks start, this is hardcoded to 0x455C as per hardware - SaveConfigBlockEntry block_entries[CONFIG_FILE_MAX_BLOCK_ENTRIES]; ///< The block headers, the maximum possible value is 1479 as per hardware - u32 unknown; ///< This field is unknown, possibly padding, 0 has been observed in hardware -}; -static_assert(sizeof(SaveFileConfig) == 0x455C, "The SaveFileConfig header must be exactly 0x455C bytes"); - -struct UsernameBlock { - char16_t username[10]; ///< Exactly 20 bytes long, padded with zeros at the end if necessary - u32 zero; - u32 ng_word; -}; -static_assert(sizeof(UsernameBlock) == 0x1C, "Size of UsernameBlock must be 0x1C"); - -struct ConsoleModelInfo { - u8 model; ///< The console model (3DS, 2DS, etc) - u8 unknown[3]; ///< Unknown data -}; -static_assert(sizeof(ConsoleModelInfo) == 4, "ConsoleModelInfo must be exactly 4 bytes"); - -struct ConsoleCountryInfo { - u8 unknown[3]; ///< Unknown data - u8 country_code; ///< The country code of the console -}; -static_assert(sizeof(ConsoleCountryInfo) == 4, "ConsoleCountryInfo must be exactly 4 bytes"); - -extern const u64 CFG_SAVE_ID; -extern const u64 CONSOLE_UNIQUE_ID; -extern const ConsoleModelInfo CONSOLE_MODEL; -extern const u8 CONSOLE_LANGUAGE; -extern const char CONSOLE_USERNAME[0x14]; -/// This will be initialized in the Interface constructor, and will be used when creating the block -extern UsernameBlock CONSOLE_USERNAME_BLOCK; -/// TODO(Subv): Find out what this actually is -extern const u8 SOUND_OUTPUT_MODE; -extern const u8 UNITED_STATES_COUNTRY_ID; -/// TODO(Subv): Find what the other bytes are -extern const ConsoleCountryInfo COUNTRY_INFO; -extern const std::array<float, 8> STEREO_CAMERA_SETTINGS; - -static_assert(sizeof(STEREO_CAMERA_SETTINGS) == 0x20, "STEREO_CAMERA_SETTINGS must be exactly 0x20 bytes"); -static_assert(sizeof(CONSOLE_UNIQUE_ID) == 8, "CONSOLE_UNIQUE_ID must be exactly 8 bytes"); -static_assert(sizeof(CONSOLE_LANGUAGE) == 1, "CONSOLE_LANGUAGE must be exactly 1 byte"); -static_assert(sizeof(SOUND_OUTPUT_MODE) == 1, "SOUND_OUTPUT_MODE must be exactly 1 byte"); - /** * Reads a block with the specified id and flag from the Config savegame buffer * and writes the output to output. @@ -278,7 +224,7 @@ ResultCode GetConfigInfoBlock(u32 block_id, u32 size, u32 flag, u8* output); * @param data A pointer containing the data we will write to the new block * @returns ResultCode indicating the result of the operation, 0 on success */ -ResultCode CreateConfigInfoBlk(u32 block_id, u16 size, u16 flags, const u8* data); +ResultCode CreateConfigInfoBlk(u32 block_id, u16 size, u16 flags, const void* data); /** * Deletes the config savegame file from the filesystem, the buffer in memory is not affected diff --git a/src/core/hle/service/dsp_dsp.cpp b/src/core/hle/service/dsp_dsp.cpp index a8cb15d60..ce5619069 100644 --- a/src/core/hle/service/dsp_dsp.cpp +++ b/src/core/hle/service/dsp_dsp.cpp @@ -212,10 +212,10 @@ static void ReadPipeIfPossible(Service::Interface* self) { // Canned DSP responses that games expect. These were taken from HW by 3dmoo team. // TODO: Remove this hack :) - static const std::array<u16, 16> canned_read_pipe = { + static const std::array<u16, 16> canned_read_pipe = {{ 0x000F, 0xBFFF, 0x9E8E, 0x8680, 0xA78E, 0x9430, 0x8400, 0x8540, 0x948E, 0x8710, 0x8410, 0xA90E, 0xAA0E, 0xAACE, 0xAC4E, 0xAC58 - }; + }}; u32 initial_size = read_pipe_count; diff --git a/src/core/hle/service/hid/hid.cpp b/src/core/hle/service/hid/hid.cpp index c35b13b25..2e1e5c3e9 100644 --- a/src/core/hle/service/hid/hid.cpp +++ b/src/core/hle/service/hid/hid.cpp @@ -35,14 +35,14 @@ static Kernel::SharedPtr<Kernel::Event> event_debug_pad; static u32 next_pad_index; static u32 next_touch_index; -const std::array<Service::HID::PadState, Settings::NativeInput::NUM_INPUTS> pad_mapping = { +const std::array<Service::HID::PadState, Settings::NativeInput::NUM_INPUTS> pad_mapping = {{ Service::HID::PAD_A, Service::HID::PAD_B, Service::HID::PAD_X, Service::HID::PAD_Y, Service::HID::PAD_L, Service::HID::PAD_R, Service::HID::PAD_ZL, Service::HID::PAD_ZR, Service::HID::PAD_START, Service::HID::PAD_SELECT, Service::HID::PAD_NONE, Service::HID::PAD_UP, Service::HID::PAD_DOWN, Service::HID::PAD_LEFT, Service::HID::PAD_RIGHT, Service::HID::PAD_CIRCLE_UP, Service::HID::PAD_CIRCLE_DOWN, Service::HID::PAD_CIRCLE_LEFT, Service::HID::PAD_CIRCLE_RIGHT, Service::HID::PAD_C_UP, Service::HID::PAD_C_DOWN, Service::HID::PAD_C_LEFT, Service::HID::PAD_C_RIGHT -}; +}}; // TODO(peachum): diff --git a/src/core/loader/3dsx.cpp b/src/core/loader/3dsx.cpp index 530837d08..111b6a409 100644 --- a/src/core/loader/3dsx.cpp +++ b/src/core/loader/3dsx.cpp @@ -62,6 +62,10 @@ struct THREEDSX_Header // Sizes of the code, rodata and data segments + // size of the BSS section (uninitialized latter half of the data segment) u32 code_seg_size, rodata_seg_size, data_seg_size, bss_size; + // offset and size of smdh + u32 smdh_offset, smdh_size; + // offset to filesystem + u32 fs_offset; }; // Relocation header: all fields (even extra unknown fields) are guaranteed to be relocation counts. @@ -267,4 +271,40 @@ ResultStatus AppLoader_THREEDSX::Load() { return ResultStatus::Success; } +ResultStatus AppLoader_THREEDSX::ReadRomFS(std::shared_ptr<FileUtil::IOFile>& romfs_file, u64& offset, u64& size) { + if (!file.IsOpen()) + return ResultStatus::Error; + + // Reset read pointer in case this file has been read before. + file.Seek(0, SEEK_SET); + + THREEDSX_Header hdr; + if (file.ReadBytes(&hdr, sizeof(THREEDSX_Header)) != sizeof(THREEDSX_Header)) + return ResultStatus::Error; + + if (hdr.header_size != sizeof(THREEDSX_Header)) + return ResultStatus::Error; + + // Check if the 3DSX has a RomFS... + if (hdr.fs_offset != 0) { + u32 romfs_offset = hdr.fs_offset; + u32 romfs_size = file.GetSize() - hdr.fs_offset; + + LOG_DEBUG(Loader, "RomFS offset: 0x%08X", romfs_offset); + LOG_DEBUG(Loader, "RomFS size: 0x%08X", romfs_size); + + // We reopen the file, to allow its position to be independent from file's + romfs_file = std::make_shared<FileUtil::IOFile>(filepath, "rb"); + if (!romfs_file->IsOpen()) + return ResultStatus::Error; + + offset = romfs_offset; + size = romfs_size; + + return ResultStatus::Success; + } + LOG_DEBUG(Loader, "3DSX has no RomFS"); + return ResultStatus::ErrorNotUsed; +} + } // namespace Loader diff --git a/src/core/loader/3dsx.h b/src/core/loader/3dsx.h index a0aa0c533..365ddb7a5 100644 --- a/src/core/loader/3dsx.h +++ b/src/core/loader/3dsx.h @@ -17,8 +17,8 @@ namespace Loader { /// Loads an 3DSX file class AppLoader_THREEDSX final : public AppLoader { public: - AppLoader_THREEDSX(FileUtil::IOFile&& file, std::string filename) - : AppLoader(std::move(file)), filename(std::move(filename)) {} + AppLoader_THREEDSX(FileUtil::IOFile&& file, std::string filename, const std::string& filepath) + : AppLoader(std::move(file)), filename(std::move(filename)), filepath(filepath) {} /** * Returns the type of the file @@ -33,8 +33,18 @@ public: */ ResultStatus Load() override; + /** + * Get the RomFS of the application + * @param romfs_file Reference to buffer to store data + * @param offset Offset in the file to the RomFS + * @param size Size of the RomFS in bytes + * @return ResultStatus result of function + */ + ResultStatus ReadRomFS(std::shared_ptr<FileUtil::IOFile>& romfs_file, u64& offset, u64& size) override; + private: std::string filename; + std::string filepath; }; } // namespace Loader diff --git a/src/core/loader/loader.cpp b/src/core/loader/loader.cpp index b1902dcca..6b88169e1 100644 --- a/src/core/loader/loader.cpp +++ b/src/core/loader/loader.cpp @@ -116,7 +116,15 @@ ResultStatus LoadFile(const std::string& filename) { //3DSX file format... case FileType::THREEDSX: - return AppLoader_THREEDSX(std::move(file), filename_filename).Load(); + { + AppLoader_THREEDSX app_loader(std::move(file), filename_filename, filename); + // Load application and RomFS + if (ResultStatus::Success == app_loader.Load()) { + Service::FS::RegisterArchiveType(Common::make_unique<FileSys::ArchiveFactory_RomFS>(app_loader), Service::FS::ArchiveIdCode::RomFS); + return ResultStatus::Success; + } + break; + } // Standard ELF file format... case FileType::ELF: diff --git a/src/core/settings.h b/src/core/settings.h index 6ca0e1afc..0b05e5bee 100644 --- a/src/core/settings.h +++ b/src/core/settings.h @@ -19,22 +19,22 @@ enum Values { CUP, CDOWN, CLEFT, CRIGHT, NUM_INPUTS }; -static const std::array<const char*, NUM_INPUTS> Mapping = { +static const std::array<const char*, NUM_INPUTS> Mapping = {{ "pad_a", "pad_b", "pad_x", "pad_y", "pad_l", "pad_r", "pad_zl", "pad_zr", "pad_start", "pad_select", "pad_home", "pad_dup", "pad_ddown", "pad_dleft", "pad_dright", "pad_sup", "pad_sdown", "pad_sleft", "pad_sright", "pad_cup", "pad_cdown", "pad_cleft", "pad_cright" -}; -static const std::array<Values, NUM_INPUTS> All = { +}}; +static const std::array<Values, NUM_INPUTS> All = {{ A, B, X, Y, L, R, ZL, ZR, START, SELECT, HOME, DUP, DDOWN, DLEFT, DRIGHT, SUP, SDOWN, SLEFT, SRIGHT, CUP, CDOWN, CLEFT, CRIGHT -}; +}}; } diff --git a/src/core/tracer/recorder.cpp b/src/core/tracer/recorder.cpp index 656706c0c..c6dc35c83 100644 --- a/src/core/tracer/recorder.cpp +++ b/src/core/tracer/recorder.cpp @@ -143,11 +143,11 @@ void Recorder::Finish(const std::string& filename) { } void Recorder::FrameFinished() { - stream.push_back( { FrameMarker } ); + stream.push_back( { { FrameMarker } } ); } void Recorder::MemoryAccessed(const u8* data, u32 size, u32 physical_address) { - StreamElement element = { MemoryLoad }; + StreamElement element = { { MemoryLoad } }; element.data.memory_load.size = size; element.data.memory_load.physical_address = physical_address; @@ -168,7 +168,7 @@ void Recorder::MemoryAccessed(const u8* data, u32 size, u32 physical_address) { template<typename T> void Recorder::RegisterWritten(u32 physical_address, T value) { - StreamElement element = { RegisterWrite }; + StreamElement element = { { RegisterWrite } }; element.data.register_write.size = (sizeof(T) == 1) ? CTRegisterWrite::SIZE_8 : (sizeof(T) == 2) ? CTRegisterWrite::SIZE_16 : (sizeof(T) == 4) ? CTRegisterWrite::SIZE_32 diff --git a/src/video_core/debug_utils/debug_utils.cpp b/src/video_core/debug_utils/debug_utils.cpp index 77a4fe272..aa1f1484c 100644 --- a/src/video_core/debug_utils/debug_utils.cpp +++ b/src/video_core/debug_utils/debug_utils.cpp @@ -92,7 +92,7 @@ void GeometryDumper::AddTriangle(Vertex& v0, Vertex& v1, Vertex& v2) { vertices.push_back(v2); int num_vertices = (int)vertices.size(); - faces.push_back({ num_vertices-3, num_vertices-2, num_vertices-1 }); + faces.push_back({{ num_vertices-3, num_vertices-2, num_vertices-1 }}); } void GeometryDumper::Dump() { @@ -576,8 +576,8 @@ const Math::Vec4<u8> LookupTexture(const u8* source, int x, int y, const Texture unsigned table_index = static_cast<int>((x < 2) ? table_index_1.Value() : table_index_2.Value()); static const std::array<std::array<u8, 2>, 8> etc1_modifier_table = {{ - { 2, 8 }, { 5, 17 }, { 9, 29 }, { 13, 42 }, - { 18, 60 }, { 24, 80 }, { 33, 106 }, { 47, 183 } + {{ 2, 8 }}, {{ 5, 17 }}, {{ 9, 29 }}, {{ 13, 42 }}, + {{ 18, 60 }}, {{ 24, 80 }}, {{ 33, 106 }}, {{ 47, 183 }} }}; int modifier = etc1_modifier_table.at(table_index).at(GetTableSubIndex(texel)); diff --git a/src/video_core/gpu_debugger.h b/src/video_core/gpu_debugger.h index fae5de7d1..a3aab216c 100644 --- a/src/video_core/gpu_debugger.h +++ b/src/video_core/gpu_debugger.h @@ -45,7 +45,6 @@ public: private: GraphicsDebugger* observed; - bool in_destruction; friend class GraphicsDebugger; }; diff --git a/src/video_core/rasterizer.cpp b/src/video_core/rasterizer.cpp index a90ff5fef..7abf60292 100644 --- a/src/video_core/rasterizer.cpp +++ b/src/video_core/rasterizer.cpp @@ -735,11 +735,11 @@ static void ProcessTriangleInternal(const Shader::OutputVertex& v0, auto color_output = ColorCombine(tev_stage.color_op, color_result); // alpha combiner - std::array<u8,3> alpha_result = { + std::array<u8,3> alpha_result = {{ GetAlphaModifier(tev_stage.alpha_modifier1, GetSource(tev_stage.alpha_source1)), GetAlphaModifier(tev_stage.alpha_modifier2, GetSource(tev_stage.alpha_source2)), GetAlphaModifier(tev_stage.alpha_modifier3, GetSource(tev_stage.alpha_source3)) - }; + }}; auto alpha_output = AlphaCombine(tev_stage.alpha_op, alpha_result); combiner_output[0] = std::min((unsigned)255, color_output.r() * tev_stage.GetColorMultiplier()); @@ -967,6 +967,8 @@ static void ProcessTriangleInternal(const Shader::OutputVertex& v0, UNIMPLEMENTED(); break; } + + return {}; }; auto LookupFactorA = [&](Regs::BlendFactor factor) -> u8 { @@ -1000,6 +1002,8 @@ static void ProcessTriangleInternal(const Shader::OutputVertex& v0, UNIMPLEMENTED(); break; } + + return {}; }; static auto EvaluateBlendEquation = [](const Math::Vec4<u8>& src, const Math::Vec4<u8>& srcfactor, diff --git a/src/video_core/renderer_opengl/renderer_opengl.cpp b/src/video_core/renderer_opengl/renderer_opengl.cpp index 22f261c68..f1313b54f 100644 --- a/src/video_core/renderer_opengl/renderer_opengl.cpp +++ b/src/video_core/renderer_opengl/renderer_opengl.cpp @@ -314,12 +314,12 @@ void RendererOpenGL::ConfigureFramebufferTexture(TextureInfo& texture, * Draws a single texture to the emulator window, rotating the texture to correct for the 3DS's LCD rotation. */ void RendererOpenGL::DrawSingleScreenRotated(const TextureInfo& texture, float x, float y, float w, float h) { - std::array<ScreenRectVertex, 4> vertices = { + std::array<ScreenRectVertex, 4> vertices = {{ ScreenRectVertex(x, y, 1.f, 0.f), ScreenRectVertex(x+w, y, 1.f, 1.f), ScreenRectVertex(x, y+h, 0.f, 0.f), ScreenRectVertex(x+w, y+h, 0.f, 1.f), - }; + }}; state.texture_units[0].texture_2d = texture.handle; state.Apply(); diff --git a/src/video_core/renderer_opengl/renderer_opengl.h b/src/video_core/renderer_opengl/renderer_opengl.h index 5677e538b..b42df7654 100644 --- a/src/video_core/renderer_opengl/renderer_opengl.h +++ b/src/video_core/renderer_opengl/renderer_opengl.h @@ -62,7 +62,6 @@ private: const TextureInfo& texture); EmuWindow* render_window; ///< Handle to render window - u32 last_mode; ///< Last render mode int resolution_width; ///< Current resolution width int resolution_height; ///< Current resolution height |