diff options
Diffstat (limited to 'src')
-rw-r--r-- | src/audio_core/codec.cpp | 4 | ||||
-rw-r--r-- | src/audio_core/codec.h | 4 | ||||
-rw-r--r-- | src/audio_core/hle/source.h | 2 | ||||
-rw-r--r-- | src/audio_core/interpolate.cpp | 2 | ||||
-rw-r--r-- | src/audio_core/interpolate.h | 4 | ||||
-rw-r--r-- | src/core/file_sys/archive_selfncch.cpp | 43 | ||||
-rw-r--r-- | src/core/file_sys/archive_selfncch.h | 9 | ||||
-rw-r--r-- | src/core/hle/service/fs/archive.cpp | 18 | ||||
-rw-r--r-- | src/core/hle/service/fs/archive.h | 7 | ||||
-rw-r--r-- | src/core/loader/3dsx.cpp | 3 | ||||
-rw-r--r-- | src/core/loader/ncch.cpp | 3 | ||||
-rw-r--r-- | src/core/memory.cpp | 17 |
12 files changed, 90 insertions, 26 deletions
diff --git a/src/audio_core/codec.cpp b/src/audio_core/codec.cpp index 7a3bd7eb3..6fba9fdae 100644 --- a/src/audio_core/codec.cpp +++ b/src/audio_core/codec.cpp @@ -117,7 +117,9 @@ StereoBuffer16 DecodePCM16(const unsigned num_channels, const u8* const data, ret[i].fill(sample); } } else { - std::memcpy(ret.data(), data, sample_count * 2 * sizeof(u16)); + for (size_t i = 0; i < sample_count; ++i) { + std::memcpy(&ret[i], data + i * sizeof(s16) * 2, 2 * sizeof(s16)); + } } return ret; diff --git a/src/audio_core/codec.h b/src/audio_core/codec.h index 2b0c395e6..877b2202d 100644 --- a/src/audio_core/codec.h +++ b/src/audio_core/codec.h @@ -5,13 +5,13 @@ #pragma once #include <array> -#include <vector> +#include <deque> #include "common/common_types.h" namespace Codec { /// A variable length buffer of signed PCM16 stereo samples. -using StereoBuffer16 = std::vector<std::array<s16, 2>>; +using StereoBuffer16 = std::deque<std::array<s16, 2>>; /// See: Codec::DecodeADPCM struct ADPCMState { diff --git a/src/audio_core/hle/source.h b/src/audio_core/hle/source.h index ccb7f064f..c4d2debc2 100644 --- a/src/audio_core/hle/source.h +++ b/src/audio_core/hle/source.h @@ -108,7 +108,7 @@ private: u32 current_sample_number = 0; u32 next_sample_number = 0; - std::vector<std::array<s16, 2>> current_buffer; + AudioInterp::StereoBuffer16 current_buffer; // buffer_id state diff --git a/src/audio_core/interpolate.cpp b/src/audio_core/interpolate.cpp index 16e68bc5c..83573d772 100644 --- a/src/audio_core/interpolate.cpp +++ b/src/audio_core/interpolate.cpp @@ -47,7 +47,7 @@ static void StepOverSamples(State& state, StereoBuffer16& input, float rate, state.xn1 = input[inputi + 1]; state.fposition = fposition - inputi * scale_factor; - input.erase(input.begin(), input.begin() + inputi + 2); + input.erase(input.begin(), std::next(input.begin(), inputi + 2)); } void None(State& state, StereoBuffer16& input, float rate, DSP::HLE::StereoFrame16& output, diff --git a/src/audio_core/interpolate.h b/src/audio_core/interpolate.h index 59f59bc14..8dff6111a 100644 --- a/src/audio_core/interpolate.h +++ b/src/audio_core/interpolate.h @@ -5,14 +5,14 @@ #pragma once #include <array> -#include <vector> +#include <deque> #include "audio_core/hle/common.h" #include "common/common_types.h" namespace AudioInterp { /// A variable length buffer of signed PCM16 stereo samples. -using StereoBuffer16 = std::vector<std::array<s16, 2>>; +using StereoBuffer16 = std::deque<std::array<s16, 2>>; struct State { /// Two historical samples. diff --git a/src/core/file_sys/archive_selfncch.cpp b/src/core/file_sys/archive_selfncch.cpp index 7dc91a405..a16941c70 100644 --- a/src/core/file_sys/archive_selfncch.cpp +++ b/src/core/file_sys/archive_selfncch.cpp @@ -3,12 +3,14 @@ // Refer to the license.txt file included. #include <array> +#include <cinttypes> #include "common/common_types.h" #include "common/logging/log.h" #include "common/swap.h" #include "core/file_sys/archive_selfncch.h" #include "core/file_sys/errors.h" #include "core/file_sys/ivfc_archive.h" +#include "core/hle/kernel/process.h" //////////////////////////////////////////////////////////////////////////////////////////////////// // FileSys namespace @@ -227,38 +229,57 @@ private: NCCHData ncch_data; }; -ArchiveFactory_SelfNCCH::ArchiveFactory_SelfNCCH(Loader::AppLoader& app_loader) { - std::shared_ptr<FileUtil::IOFile> romfs_file; +void ArchiveFactory_SelfNCCH::Register(Loader::AppLoader& app_loader) { + u64 program_id = 0; + if (app_loader.ReadProgramId(program_id) != Loader::ResultStatus::Success) { + LOG_WARNING( + Service_FS, + "Could not read program id when registering with SelfNCCH, this might be a 3dsx file"); + } + + LOG_DEBUG(Service_FS, "Registering program %016" PRIX64 " with the SelfNCCH archive factory", + program_id); + + if (ncch_data.find(program_id) != ncch_data.end()) { + LOG_WARNING(Service_FS, "Registering program %016" PRIX64 + " with SelfNCCH will override existing mapping", + program_id); + } + + NCCHData& data = ncch_data[program_id]; + + std::shared_ptr<FileUtil::IOFile> romfs_file_; if (Loader::ResultStatus::Success == - app_loader.ReadRomFS(romfs_file, ncch_data.romfs_offset, ncch_data.romfs_size)) { + app_loader.ReadRomFS(romfs_file_, data.romfs_offset, data.romfs_size)) { - ncch_data.romfs_file = std::move(romfs_file); + data.romfs_file = std::move(romfs_file_); } std::shared_ptr<FileUtil::IOFile> update_romfs_file; if (Loader::ResultStatus::Success == - app_loader.ReadUpdateRomFS(update_romfs_file, ncch_data.update_romfs_offset, - ncch_data.update_romfs_size)) { + app_loader.ReadUpdateRomFS(update_romfs_file, data.update_romfs_offset, + data.update_romfs_size)) { - ncch_data.update_romfs_file = std::move(update_romfs_file); + data.update_romfs_file = std::move(update_romfs_file); } std::vector<u8> buffer; if (Loader::ResultStatus::Success == app_loader.ReadIcon(buffer)) - ncch_data.icon = std::make_shared<std::vector<u8>>(std::move(buffer)); + data.icon = std::make_shared<std::vector<u8>>(std::move(buffer)); buffer.clear(); if (Loader::ResultStatus::Success == app_loader.ReadLogo(buffer)) - ncch_data.logo = std::make_shared<std::vector<u8>>(std::move(buffer)); + data.logo = std::make_shared<std::vector<u8>>(std::move(buffer)); buffer.clear(); if (Loader::ResultStatus::Success == app_loader.ReadBanner(buffer)) - ncch_data.banner = std::make_shared<std::vector<u8>>(std::move(buffer)); + data.banner = std::make_shared<std::vector<u8>>(std::move(buffer)); } ResultVal<std::unique_ptr<ArchiveBackend>> ArchiveFactory_SelfNCCH::Open(const Path& path) { - auto archive = std::make_unique<SelfNCCHArchive>(ncch_data); + auto archive = std::make_unique<SelfNCCHArchive>( + ncch_data[Kernel::g_current_process->codeset->program_id]); return MakeResult<std::unique_ptr<ArchiveBackend>>(std::move(archive)); } diff --git a/src/core/file_sys/archive_selfncch.h b/src/core/file_sys/archive_selfncch.h index f1c659948..0d6d6766e 100644 --- a/src/core/file_sys/archive_selfncch.h +++ b/src/core/file_sys/archive_selfncch.h @@ -6,6 +6,7 @@ #include <memory> #include <string> +#include <unordered_map> #include <vector> #include "common/common_types.h" #include "core/file_sys/archive_backend.h" @@ -33,7 +34,10 @@ struct NCCHData { /// File system interface to the SelfNCCH archive class ArchiveFactory_SelfNCCH final : public ArchiveFactory { public: - explicit ArchiveFactory_SelfNCCH(Loader::AppLoader& app_loader); + ArchiveFactory_SelfNCCH() = default; + + /// Registers a loaded application so that we can open its SelfNCCH archive when requested. + void Register(Loader::AppLoader& app_loader); std::string GetName() const override { return "SelfNCCH"; @@ -43,7 +47,8 @@ public: ResultVal<ArchiveFormatInfo> GetFormatInfo(const Path& path) const override; private: - NCCHData ncch_data; + /// Mapping of ProgramId -> NCCHData + std::unordered_map<u64, NCCHData> ncch_data; }; } // namespace FileSys diff --git a/src/core/hle/service/fs/archive.cpp b/src/core/hle/service/fs/archive.cpp index 033fbc9aa..4ccb3cd32 100644 --- a/src/core/hle/service/fs/archive.cpp +++ b/src/core/hle/service/fs/archive.cpp @@ -20,6 +20,7 @@ #include "core/file_sys/archive_savedata.h" #include "core/file_sys/archive_sdmc.h" #include "core/file_sys/archive_sdmcwriteonly.h" +#include "core/file_sys/archive_selfncch.h" #include "core/file_sys/archive_systemsavedata.h" #include "core/file_sys/directory_backend.h" #include "core/file_sys/errors.h" @@ -48,7 +49,7 @@ struct hash<Service::FS::ArchiveIdCode> { return std::hash<Type>()(static_cast<Type>(id_code)); } }; -} +} // namespace std static constexpr Kernel::Handle INVALID_HANDLE{}; @@ -564,6 +565,21 @@ void RegisterArchiveTypes() { auto systemsavedata_factory = std::make_unique<FileSys::ArchiveFactory_SystemSaveData>(nand_directory); RegisterArchiveType(std::move(systemsavedata_factory), ArchiveIdCode::SystemSaveData); + + auto selfncch_factory = std::make_unique<FileSys::ArchiveFactory_SelfNCCH>(); + RegisterArchiveType(std::move(selfncch_factory), ArchiveIdCode::SelfNCCH); +} + +void RegisterSelfNCCH(Loader::AppLoader& app_loader) { + auto itr = id_code_map.find(ArchiveIdCode::SelfNCCH); + if (itr == id_code_map.end()) { + LOG_ERROR(Service_FS, + "Could not register a new NCCH because the SelfNCCH archive hasn't been created"); + return; + } + + auto* factory = static_cast<FileSys::ArchiveFactory_SelfNCCH*>(itr->second.get()); + factory->Register(app_loader); } void UnregisterArchiveTypes() { diff --git a/src/core/hle/service/fs/archive.h b/src/core/hle/service/fs/archive.h index 3a3371c88..e3c8fc2ef 100644 --- a/src/core/hle/service/fs/archive.h +++ b/src/core/hle/service/fs/archive.h @@ -21,6 +21,10 @@ static constexpr char SYSTEM_ID[]{"00000000000000000000000000000000"}; /// The scrambled SD card CID, also known as ID1 static constexpr char SDCARD_ID[]{"00000000000000000000000000000000"}; +namespace Loader { +class AppLoader; +} + namespace Service { namespace FS { @@ -259,6 +263,9 @@ void ArchiveInit(); /// Shutdown archives void ArchiveShutdown(); +/// Registers a new NCCH file with the SelfNCCH archive factory +void RegisterSelfNCCH(Loader::AppLoader& app_loader); + /// Register all archive types void RegisterArchiveTypes(); diff --git a/src/core/loader/3dsx.cpp b/src/core/loader/3dsx.cpp index a03515e6e..5ad5c5287 100644 --- a/src/core/loader/3dsx.cpp +++ b/src/core/loader/3dsx.cpp @@ -278,8 +278,7 @@ ResultStatus AppLoader_THREEDSX::Load() { Kernel::g_current_process->Run(48, Kernel::DEFAULT_STACK_SIZE); - Service::FS::RegisterArchiveType(std::make_unique<FileSys::ArchiveFactory_SelfNCCH>(*this), - Service::FS::ArchiveIdCode::SelfNCCH); + Service::FS::RegisterSelfNCCH(*this); is_loaded = true; return ResultStatus::Success; diff --git a/src/core/loader/ncch.cpp b/src/core/loader/ncch.cpp index c46d7cfc6..5107135f9 100644 --- a/src/core/loader/ncch.cpp +++ b/src/core/loader/ncch.cpp @@ -187,8 +187,7 @@ ResultStatus AppLoader_NCCH::Load() { if (ResultStatus::Success != result) return result; - Service::FS::RegisterArchiveType(std::make_unique<FileSys::ArchiveFactory_SelfNCCH>(*this), - Service::FS::ArchiveIdCode::SelfNCCH); + Service::FS::RegisterSelfNCCH(*this); ParseRegionLockoutInfo(); diff --git a/src/core/memory.cpp b/src/core/memory.cpp index a6b5f6c99..9b394f84b 100644 --- a/src/core/memory.cpp +++ b/src/core/memory.cpp @@ -325,8 +325,15 @@ void RasterizerMarkRegionCached(PAddr start, u32 size, int count_delta) { for (unsigned i = 0; i < num_pages; ++i, paddr += PAGE_SIZE) { boost::optional<VAddr> maybe_vaddr = PhysicalToVirtualAddress(paddr); - if (!maybe_vaddr) + // While the physical <-> virtual mapping is 1:1 for the regions supported by the cache, + // some games (like Pokemon Super Mystery Dungeon) will try to use textures that go beyond + // the end address of VRAM, causing the Virtual->Physical translation to fail when flushing + // parts of the texture. + if (!maybe_vaddr) { + LOG_ERROR(HW_Memory, + "Trying to flush a cached region to an invalid physical address %08X", paddr); continue; + } VAddr vaddr = *maybe_vaddr; u8& res_count = current_page_table->cached_res_count[vaddr >> PAGE_BITS]; @@ -338,6 +345,10 @@ void RasterizerMarkRegionCached(PAddr start, u32 size, int count_delta) { if (res_count == 0) { PageType& page_type = current_page_table->attributes[vaddr >> PAGE_BITS]; switch (page_type) { + case PageType::Unmapped: + // It is not necessary for a process to have this region mapped into its address + // space, for example, a system module need not have a VRAM mapping. + break; case PageType::Memory: page_type = PageType::RasterizerCachedMemory; current_page_table->pointers[vaddr >> PAGE_BITS] = nullptr; @@ -356,6 +367,10 @@ void RasterizerMarkRegionCached(PAddr start, u32 size, int count_delta) { if (res_count == 0) { PageType& page_type = current_page_table->attributes[vaddr >> PAGE_BITS]; switch (page_type) { + case PageType::Unmapped: + // It is not necessary for a process to have this region mapped into its address + // space, for example, a system module need not have a VRAM mapping. + break; case PageType::RasterizerCachedMemory: { u8* pointer = GetPointerFromVMA(vaddr & ~PAGE_MASK); if (pointer == nullptr) { |