summaryrefslogtreecommitdiff
path: root/src
diff options
context:
space:
mode:
Diffstat (limited to 'src')
-rw-r--r--src/audio_core/codec.cpp4
-rw-r--r--src/audio_core/codec.h4
-rw-r--r--src/audio_core/hle/source.h2
-rw-r--r--src/audio_core/interpolate.cpp2
-rw-r--r--src/audio_core/interpolate.h4
-rw-r--r--src/core/file_sys/archive_selfncch.cpp43
-rw-r--r--src/core/file_sys/archive_selfncch.h9
-rw-r--r--src/core/hle/service/fs/archive.cpp18
-rw-r--r--src/core/hle/service/fs/archive.h7
-rw-r--r--src/core/loader/3dsx.cpp3
-rw-r--r--src/core/loader/ncch.cpp3
-rw-r--r--src/core/memory.cpp17
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,
117 ret[i].fill(sample); 117 ret[i].fill(sample);
118 } 118 }
119 } else { 119 } else {
120 std::memcpy(ret.data(), data, sample_count * 2 * sizeof(u16)); 120 for (size_t i = 0; i < sample_count; ++i) {
121 std::memcpy(&ret[i], data + i * sizeof(s16) * 2, 2 * sizeof(s16));
122 }
121 } 123 }
122 124
123 return ret; 125 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 @@
5#pragma once 5#pragma once
6 6
7#include <array> 7#include <array>
8#include <vector> 8#include <deque>
9#include "common/common_types.h" 9#include "common/common_types.h"
10 10
11namespace Codec { 11namespace Codec {
12 12
13/// A variable length buffer of signed PCM16 stereo samples. 13/// A variable length buffer of signed PCM16 stereo samples.
14using StereoBuffer16 = std::vector<std::array<s16, 2>>; 14using StereoBuffer16 = std::deque<std::array<s16, 2>>;
15 15
16/// See: Codec::DecodeADPCM 16/// See: Codec::DecodeADPCM
17struct ADPCMState { 17struct 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:
108 108
109 u32 current_sample_number = 0; 109 u32 current_sample_number = 0;
110 u32 next_sample_number = 0; 110 u32 next_sample_number = 0;
111 std::vector<std::array<s16, 2>> current_buffer; 111 AudioInterp::StereoBuffer16 current_buffer;
112 112
113 // buffer_id state 113 // buffer_id state
114 114
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,
47 state.xn1 = input[inputi + 1]; 47 state.xn1 = input[inputi + 1];
48 state.fposition = fposition - inputi * scale_factor; 48 state.fposition = fposition - inputi * scale_factor;
49 49
50 input.erase(input.begin(), input.begin() + inputi + 2); 50 input.erase(input.begin(), std::next(input.begin(), inputi + 2));
51} 51}
52 52
53void None(State& state, StereoBuffer16& input, float rate, DSP::HLE::StereoFrame16& output, 53void 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 @@
5#pragma once 5#pragma once
6 6
7#include <array> 7#include <array>
8#include <vector> 8#include <deque>
9#include "audio_core/hle/common.h" 9#include "audio_core/hle/common.h"
10#include "common/common_types.h" 10#include "common/common_types.h"
11 11
12namespace AudioInterp { 12namespace AudioInterp {
13 13
14/// A variable length buffer of signed PCM16 stereo samples. 14/// A variable length buffer of signed PCM16 stereo samples.
15using StereoBuffer16 = std::vector<std::array<s16, 2>>; 15using StereoBuffer16 = std::deque<std::array<s16, 2>>;
16 16
17struct State { 17struct State {
18 /// Two historical samples. 18 /// 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 @@
3// Refer to the license.txt file included. 3// Refer to the license.txt file included.
4 4
5#include <array> 5#include <array>
6#include <cinttypes>
6#include "common/common_types.h" 7#include "common/common_types.h"
7#include "common/logging/log.h" 8#include "common/logging/log.h"
8#include "common/swap.h" 9#include "common/swap.h"
9#include "core/file_sys/archive_selfncch.h" 10#include "core/file_sys/archive_selfncch.h"
10#include "core/file_sys/errors.h" 11#include "core/file_sys/errors.h"
11#include "core/file_sys/ivfc_archive.h" 12#include "core/file_sys/ivfc_archive.h"
13#include "core/hle/kernel/process.h"
12 14
13//////////////////////////////////////////////////////////////////////////////////////////////////// 15////////////////////////////////////////////////////////////////////////////////////////////////////
14// FileSys namespace 16// FileSys namespace
@@ -227,38 +229,57 @@ private:
227 NCCHData ncch_data; 229 NCCHData ncch_data;
228}; 230};
229 231
230ArchiveFactory_SelfNCCH::ArchiveFactory_SelfNCCH(Loader::AppLoader& app_loader) { 232void ArchiveFactory_SelfNCCH::Register(Loader::AppLoader& app_loader) {
231 std::shared_ptr<FileUtil::IOFile> romfs_file; 233 u64 program_id = 0;
234 if (app_loader.ReadProgramId(program_id) != Loader::ResultStatus::Success) {
235 LOG_WARNING(
236 Service_FS,
237 "Could not read program id when registering with SelfNCCH, this might be a 3dsx file");
238 }
239
240 LOG_DEBUG(Service_FS, "Registering program %016" PRIX64 " with the SelfNCCH archive factory",
241 program_id);
242
243 if (ncch_data.find(program_id) != ncch_data.end()) {
244 LOG_WARNING(Service_FS, "Registering program %016" PRIX64
245 " with SelfNCCH will override existing mapping",
246 program_id);
247 }
248
249 NCCHData& data = ncch_data[program_id];
250
251 std::shared_ptr<FileUtil::IOFile> romfs_file_;
232 if (Loader::ResultStatus::Success == 252 if (Loader::ResultStatus::Success ==
233 app_loader.ReadRomFS(romfs_file, ncch_data.romfs_offset, ncch_data.romfs_size)) { 253 app_loader.ReadRomFS(romfs_file_, data.romfs_offset, data.romfs_size)) {
234 254
235 ncch_data.romfs_file = std::move(romfs_file); 255 data.romfs_file = std::move(romfs_file_);
236 } 256 }
237 257
238 std::shared_ptr<FileUtil::IOFile> update_romfs_file; 258 std::shared_ptr<FileUtil::IOFile> update_romfs_file;
239 if (Loader::ResultStatus::Success == 259 if (Loader::ResultStatus::Success ==
240 app_loader.ReadUpdateRomFS(update_romfs_file, ncch_data.update_romfs_offset, 260 app_loader.ReadUpdateRomFS(update_romfs_file, data.update_romfs_offset,
241 ncch_data.update_romfs_size)) { 261 data.update_romfs_size)) {
242 262
243 ncch_data.update_romfs_file = std::move(update_romfs_file); 263 data.update_romfs_file = std::move(update_romfs_file);
244 } 264 }
245 265
246 std::vector<u8> buffer; 266 std::vector<u8> buffer;
247 267
248 if (Loader::ResultStatus::Success == app_loader.ReadIcon(buffer)) 268 if (Loader::ResultStatus::Success == app_loader.ReadIcon(buffer))
249 ncch_data.icon = std::make_shared<std::vector<u8>>(std::move(buffer)); 269 data.icon = std::make_shared<std::vector<u8>>(std::move(buffer));
250 270
251 buffer.clear(); 271 buffer.clear();
252 if (Loader::ResultStatus::Success == app_loader.ReadLogo(buffer)) 272 if (Loader::ResultStatus::Success == app_loader.ReadLogo(buffer))
253 ncch_data.logo = std::make_shared<std::vector<u8>>(std::move(buffer)); 273 data.logo = std::make_shared<std::vector<u8>>(std::move(buffer));
254 274
255 buffer.clear(); 275 buffer.clear();
256 if (Loader::ResultStatus::Success == app_loader.ReadBanner(buffer)) 276 if (Loader::ResultStatus::Success == app_loader.ReadBanner(buffer))
257 ncch_data.banner = std::make_shared<std::vector<u8>>(std::move(buffer)); 277 data.banner = std::make_shared<std::vector<u8>>(std::move(buffer));
258} 278}
259 279
260ResultVal<std::unique_ptr<ArchiveBackend>> ArchiveFactory_SelfNCCH::Open(const Path& path) { 280ResultVal<std::unique_ptr<ArchiveBackend>> ArchiveFactory_SelfNCCH::Open(const Path& path) {
261 auto archive = std::make_unique<SelfNCCHArchive>(ncch_data); 281 auto archive = std::make_unique<SelfNCCHArchive>(
282 ncch_data[Kernel::g_current_process->codeset->program_id]);
262 return MakeResult<std::unique_ptr<ArchiveBackend>>(std::move(archive)); 283 return MakeResult<std::unique_ptr<ArchiveBackend>>(std::move(archive));
263} 284}
264 285
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 @@
6 6
7#include <memory> 7#include <memory>
8#include <string> 8#include <string>
9#include <unordered_map>
9#include <vector> 10#include <vector>
10#include "common/common_types.h" 11#include "common/common_types.h"
11#include "core/file_sys/archive_backend.h" 12#include "core/file_sys/archive_backend.h"
@@ -33,7 +34,10 @@ struct NCCHData {
33/// File system interface to the SelfNCCH archive 34/// File system interface to the SelfNCCH archive
34class ArchiveFactory_SelfNCCH final : public ArchiveFactory { 35class ArchiveFactory_SelfNCCH final : public ArchiveFactory {
35public: 36public:
36 explicit ArchiveFactory_SelfNCCH(Loader::AppLoader& app_loader); 37 ArchiveFactory_SelfNCCH() = default;
38
39 /// Registers a loaded application so that we can open its SelfNCCH archive when requested.
40 void Register(Loader::AppLoader& app_loader);
37 41
38 std::string GetName() const override { 42 std::string GetName() const override {
39 return "SelfNCCH"; 43 return "SelfNCCH";
@@ -43,7 +47,8 @@ public:
43 ResultVal<ArchiveFormatInfo> GetFormatInfo(const Path& path) const override; 47 ResultVal<ArchiveFormatInfo> GetFormatInfo(const Path& path) const override;
44 48
45private: 49private:
46 NCCHData ncch_data; 50 /// Mapping of ProgramId -> NCCHData
51 std::unordered_map<u64, NCCHData> ncch_data;
47}; 52};
48 53
49} // namespace FileSys 54} // 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 @@
20#include "core/file_sys/archive_savedata.h" 20#include "core/file_sys/archive_savedata.h"
21#include "core/file_sys/archive_sdmc.h" 21#include "core/file_sys/archive_sdmc.h"
22#include "core/file_sys/archive_sdmcwriteonly.h" 22#include "core/file_sys/archive_sdmcwriteonly.h"
23#include "core/file_sys/archive_selfncch.h"
23#include "core/file_sys/archive_systemsavedata.h" 24#include "core/file_sys/archive_systemsavedata.h"
24#include "core/file_sys/directory_backend.h" 25#include "core/file_sys/directory_backend.h"
25#include "core/file_sys/errors.h" 26#include "core/file_sys/errors.h"
@@ -48,7 +49,7 @@ struct hash<Service::FS::ArchiveIdCode> {
48 return std::hash<Type>()(static_cast<Type>(id_code)); 49 return std::hash<Type>()(static_cast<Type>(id_code));
49 } 50 }
50}; 51};
51} 52} // namespace std
52 53
53static constexpr Kernel::Handle INVALID_HANDLE{}; 54static constexpr Kernel::Handle INVALID_HANDLE{};
54 55
@@ -564,6 +565,21 @@ void RegisterArchiveTypes() {
564 auto systemsavedata_factory = 565 auto systemsavedata_factory =
565 std::make_unique<FileSys::ArchiveFactory_SystemSaveData>(nand_directory); 566 std::make_unique<FileSys::ArchiveFactory_SystemSaveData>(nand_directory);
566 RegisterArchiveType(std::move(systemsavedata_factory), ArchiveIdCode::SystemSaveData); 567 RegisterArchiveType(std::move(systemsavedata_factory), ArchiveIdCode::SystemSaveData);
568
569 auto selfncch_factory = std::make_unique<FileSys::ArchiveFactory_SelfNCCH>();
570 RegisterArchiveType(std::move(selfncch_factory), ArchiveIdCode::SelfNCCH);
571}
572
573void RegisterSelfNCCH(Loader::AppLoader& app_loader) {
574 auto itr = id_code_map.find(ArchiveIdCode::SelfNCCH);
575 if (itr == id_code_map.end()) {
576 LOG_ERROR(Service_FS,
577 "Could not register a new NCCH because the SelfNCCH archive hasn't been created");
578 return;
579 }
580
581 auto* factory = static_cast<FileSys::ArchiveFactory_SelfNCCH*>(itr->second.get());
582 factory->Register(app_loader);
567} 583}
568 584
569void UnregisterArchiveTypes() { 585void 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"};
21/// The scrambled SD card CID, also known as ID1 21/// The scrambled SD card CID, also known as ID1
22static constexpr char SDCARD_ID[]{"00000000000000000000000000000000"}; 22static constexpr char SDCARD_ID[]{"00000000000000000000000000000000"};
23 23
24namespace Loader {
25class AppLoader;
26}
27
24namespace Service { 28namespace Service {
25namespace FS { 29namespace FS {
26 30
@@ -259,6 +263,9 @@ void ArchiveInit();
259/// Shutdown archives 263/// Shutdown archives
260void ArchiveShutdown(); 264void ArchiveShutdown();
261 265
266/// Registers a new NCCH file with the SelfNCCH archive factory
267void RegisterSelfNCCH(Loader::AppLoader& app_loader);
268
262/// Register all archive types 269/// Register all archive types
263void RegisterArchiveTypes(); 270void RegisterArchiveTypes();
264 271
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() {
278 278
279 Kernel::g_current_process->Run(48, Kernel::DEFAULT_STACK_SIZE); 279 Kernel::g_current_process->Run(48, Kernel::DEFAULT_STACK_SIZE);
280 280
281 Service::FS::RegisterArchiveType(std::make_unique<FileSys::ArchiveFactory_SelfNCCH>(*this), 281 Service::FS::RegisterSelfNCCH(*this);
282 Service::FS::ArchiveIdCode::SelfNCCH);
283 282
284 is_loaded = true; 283 is_loaded = true;
285 return ResultStatus::Success; 284 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() {
187 if (ResultStatus::Success != result) 187 if (ResultStatus::Success != result)
188 return result; 188 return result;
189 189
190 Service::FS::RegisterArchiveType(std::make_unique<FileSys::ArchiveFactory_SelfNCCH>(*this), 190 Service::FS::RegisterSelfNCCH(*this);
191 Service::FS::ArchiveIdCode::SelfNCCH);
192 191
193 ParseRegionLockoutInfo(); 192 ParseRegionLockoutInfo();
194 193
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) {
325 325
326 for (unsigned i = 0; i < num_pages; ++i, paddr += PAGE_SIZE) { 326 for (unsigned i = 0; i < num_pages; ++i, paddr += PAGE_SIZE) {
327 boost::optional<VAddr> maybe_vaddr = PhysicalToVirtualAddress(paddr); 327 boost::optional<VAddr> maybe_vaddr = PhysicalToVirtualAddress(paddr);
328 if (!maybe_vaddr) 328 // While the physical <-> virtual mapping is 1:1 for the regions supported by the cache,
329 // some games (like Pokemon Super Mystery Dungeon) will try to use textures that go beyond
330 // the end address of VRAM, causing the Virtual->Physical translation to fail when flushing
331 // parts of the texture.
332 if (!maybe_vaddr) {
333 LOG_ERROR(HW_Memory,
334 "Trying to flush a cached region to an invalid physical address %08X", paddr);
329 continue; 335 continue;
336 }
330 VAddr vaddr = *maybe_vaddr; 337 VAddr vaddr = *maybe_vaddr;
331 338
332 u8& res_count = current_page_table->cached_res_count[vaddr >> PAGE_BITS]; 339 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) {
338 if (res_count == 0) { 345 if (res_count == 0) {
339 PageType& page_type = current_page_table->attributes[vaddr >> PAGE_BITS]; 346 PageType& page_type = current_page_table->attributes[vaddr >> PAGE_BITS];
340 switch (page_type) { 347 switch (page_type) {
348 case PageType::Unmapped:
349 // It is not necessary for a process to have this region mapped into its address
350 // space, for example, a system module need not have a VRAM mapping.
351 break;
341 case PageType::Memory: 352 case PageType::Memory:
342 page_type = PageType::RasterizerCachedMemory; 353 page_type = PageType::RasterizerCachedMemory;
343 current_page_table->pointers[vaddr >> PAGE_BITS] = nullptr; 354 current_page_table->pointers[vaddr >> PAGE_BITS] = nullptr;
@@ -356,6 +367,10 @@ void RasterizerMarkRegionCached(PAddr start, u32 size, int count_delta) {
356 if (res_count == 0) { 367 if (res_count == 0) {
357 PageType& page_type = current_page_table->attributes[vaddr >> PAGE_BITS]; 368 PageType& page_type = current_page_table->attributes[vaddr >> PAGE_BITS];
358 switch (page_type) { 369 switch (page_type) {
370 case PageType::Unmapped:
371 // It is not necessary for a process to have this region mapped into its address
372 // space, for example, a system module need not have a VRAM mapping.
373 break;
359 case PageType::RasterizerCachedMemory: { 374 case PageType::RasterizerCachedMemory: {
360 u8* pointer = GetPointerFromVMA(vaddr & ~PAGE_MASK); 375 u8* pointer = GetPointerFromVMA(vaddr & ~PAGE_MASK);
361 if (pointer == nullptr) { 376 if (pointer == nullptr) {