diff options
32 files changed, 533 insertions, 216 deletions
diff --git a/src/audio_core/audio_renderer.cpp b/src/audio_core/audio_renderer.cpp index 521b19ff7..6f0ff953a 100644 --- a/src/audio_core/audio_renderer.cpp +++ b/src/audio_core/audio_renderer.cpp | |||
| @@ -79,7 +79,7 @@ u32 AudioRenderer::GetMixBufferCount() const { | |||
| 79 | return worker_params.mix_buffer_count; | 79 | return worker_params.mix_buffer_count; |
| 80 | } | 80 | } |
| 81 | 81 | ||
| 82 | u32 AudioRenderer::GetState() const { | 82 | Stream::State AudioRenderer::GetStreamState() const { |
| 83 | return stream->GetState(); | 83 | return stream->GetState(); |
| 84 | } | 84 | } |
| 85 | 85 | ||
diff --git a/src/audio_core/audio_renderer.h b/src/audio_core/audio_renderer.h index be923ee65..dfef89e1d 100644 --- a/src/audio_core/audio_renderer.h +++ b/src/audio_core/audio_renderer.h | |||
| @@ -170,7 +170,7 @@ public: | |||
| 170 | u32 GetSampleRate() const; | 170 | u32 GetSampleRate() const; |
| 171 | u32 GetSampleCount() const; | 171 | u32 GetSampleCount() const; |
| 172 | u32 GetMixBufferCount() const; | 172 | u32 GetMixBufferCount() const; |
| 173 | u32 GetState() const; | 173 | Stream::State GetStreamState() const; |
| 174 | 174 | ||
| 175 | private: | 175 | private: |
| 176 | class VoiceState; | 176 | class VoiceState; |
diff --git a/src/audio_core/stream.cpp b/src/audio_core/stream.cpp index ee4aa98af..742a5e0a0 100644 --- a/src/audio_core/stream.cpp +++ b/src/audio_core/stream.cpp | |||
| @@ -53,8 +53,8 @@ void Stream::Stop() { | |||
| 53 | ASSERT_MSG(false, "Unimplemented"); | 53 | ASSERT_MSG(false, "Unimplemented"); |
| 54 | } | 54 | } |
| 55 | 55 | ||
| 56 | u32 Stream::GetState() const { | 56 | Stream::State Stream::GetState() const { |
| 57 | return static_cast<u32>(state); | 57 | return state; |
| 58 | } | 58 | } |
| 59 | 59 | ||
| 60 | s64 Stream::GetBufferReleaseCycles(const Buffer& buffer) const { | 60 | s64 Stream::GetBufferReleaseCycles(const Buffer& buffer) const { |
diff --git a/src/audio_core/stream.h b/src/audio_core/stream.h index 43eca74e1..aebfeb51d 100644 --- a/src/audio_core/stream.h +++ b/src/audio_core/stream.h | |||
| @@ -33,6 +33,12 @@ public: | |||
| 33 | Multi51Channel16, | 33 | Multi51Channel16, |
| 34 | }; | 34 | }; |
| 35 | 35 | ||
| 36 | /// Current state of the stream | ||
| 37 | enum class State { | ||
| 38 | Stopped, | ||
| 39 | Playing, | ||
| 40 | }; | ||
| 41 | |||
| 36 | /// Callback function type, used to change guest state on a buffer being released | 42 | /// Callback function type, used to change guest state on a buffer being released |
| 37 | using ReleaseCallback = std::function<void()>; | 43 | using ReleaseCallback = std::function<void()>; |
| 38 | 44 | ||
| @@ -73,15 +79,9 @@ public: | |||
| 73 | u32 GetNumChannels() const; | 79 | u32 GetNumChannels() const; |
| 74 | 80 | ||
| 75 | /// Get the state | 81 | /// Get the state |
| 76 | u32 GetState() const; | 82 | State GetState() const; |
| 77 | 83 | ||
| 78 | private: | 84 | private: |
| 79 | /// Current state of the stream | ||
| 80 | enum class State { | ||
| 81 | Stopped, | ||
| 82 | Playing, | ||
| 83 | }; | ||
| 84 | |||
| 85 | /// Plays the next queued buffer in the audio stream, starting playback if necessary | 85 | /// Plays the next queued buffer in the audio stream, starting playback if necessary |
| 86 | void PlayNextBuffer(); | 86 | void PlayNextBuffer(); |
| 87 | 87 | ||
diff --git a/src/core/arm/dynarmic/arm_dynarmic.cpp b/src/core/arm/dynarmic/arm_dynarmic.cpp index 8760d17a8..8cad070b4 100644 --- a/src/core/arm/dynarmic/arm_dynarmic.cpp +++ b/src/core/arm/dynarmic/arm_dynarmic.cpp | |||
| @@ -129,7 +129,8 @@ public: | |||
| 129 | }; | 129 | }; |
| 130 | 130 | ||
| 131 | std::unique_ptr<Dynarmic::A64::Jit> ARM_Dynarmic::MakeJit() const { | 131 | std::unique_ptr<Dynarmic::A64::Jit> ARM_Dynarmic::MakeJit() const { |
| 132 | auto** const page_table = Core::CurrentProcess()->vm_manager.page_table.pointers.data(); | 132 | auto& current_process = Core::CurrentProcess(); |
| 133 | auto** const page_table = current_process->vm_manager.page_table.pointers.data(); | ||
| 133 | 134 | ||
| 134 | Dynarmic::A64::UserConfig config; | 135 | Dynarmic::A64::UserConfig config; |
| 135 | 136 | ||
| @@ -138,7 +139,7 @@ std::unique_ptr<Dynarmic::A64::Jit> ARM_Dynarmic::MakeJit() const { | |||
| 138 | 139 | ||
| 139 | // Memory | 140 | // Memory |
| 140 | config.page_table = reinterpret_cast<void**>(page_table); | 141 | config.page_table = reinterpret_cast<void**>(page_table); |
| 141 | config.page_table_address_space_bits = Memory::ADDRESS_SPACE_BITS; | 142 | config.page_table_address_space_bits = current_process->vm_manager.GetAddressSpaceWidth(); |
| 142 | config.silently_mirror_page_table = false; | 143 | config.silently_mirror_page_table = false; |
| 143 | 144 | ||
| 144 | // Multi-process state | 145 | // Multi-process state |
diff --git a/src/core/file_sys/program_metadata.cpp b/src/core/file_sys/program_metadata.cpp index 02319ce0f..8903ed1d3 100644 --- a/src/core/file_sys/program_metadata.cpp +++ b/src/core/file_sys/program_metadata.cpp | |||
| @@ -83,10 +83,12 @@ void ProgramMetadata::Print() const { | |||
| 83 | 83 | ||
| 84 | auto address_space = "Unknown"; | 84 | auto address_space = "Unknown"; |
| 85 | switch (npdm_header.address_space_type) { | 85 | switch (npdm_header.address_space_type) { |
| 86 | case ProgramAddressSpaceType::Is64Bit: | 86 | case ProgramAddressSpaceType::Is36Bit: |
| 87 | case ProgramAddressSpaceType::Is39Bit: | ||
| 87 | address_space = "64-bit"; | 88 | address_space = "64-bit"; |
| 88 | break; | 89 | break; |
| 89 | case ProgramAddressSpaceType::Is32Bit: | 90 | case ProgramAddressSpaceType::Is32Bit: |
| 91 | case ProgramAddressSpaceType::Is32BitNoMap: | ||
| 90 | address_space = "32-bit"; | 92 | address_space = "32-bit"; |
| 91 | break; | 93 | break; |
| 92 | } | 94 | } |
diff --git a/src/core/file_sys/program_metadata.h b/src/core/file_sys/program_metadata.h index 1143e36c4..e4470d6f0 100644 --- a/src/core/file_sys/program_metadata.h +++ b/src/core/file_sys/program_metadata.h | |||
| @@ -17,8 +17,10 @@ enum class ResultStatus : u16; | |||
| 17 | namespace FileSys { | 17 | namespace FileSys { |
| 18 | 18 | ||
| 19 | enum class ProgramAddressSpaceType : u8 { | 19 | enum class ProgramAddressSpaceType : u8 { |
| 20 | Is64Bit = 1, | 20 | Is32Bit = 0, |
| 21 | Is32Bit = 2, | 21 | Is36Bit = 1, |
| 22 | Is32BitNoMap = 2, | ||
| 23 | Is39Bit = 3, | ||
| 22 | }; | 24 | }; |
| 23 | 25 | ||
| 24 | enum class ProgramFilePermission : u64 { | 26 | enum class ProgramFilePermission : u64 { |
diff --git a/src/core/gdbstub/gdbstub.cpp b/src/core/gdbstub/gdbstub.cpp index 0ecdd9f82..d8c7b3492 100644 --- a/src/core/gdbstub/gdbstub.cpp +++ b/src/core/gdbstub/gdbstub.cpp | |||
| @@ -37,7 +37,9 @@ | |||
| 37 | #include "core/core.h" | 37 | #include "core/core.h" |
| 38 | #include "core/core_cpu.h" | 38 | #include "core/core_cpu.h" |
| 39 | #include "core/gdbstub/gdbstub.h" | 39 | #include "core/gdbstub/gdbstub.h" |
| 40 | #include "core/hle/kernel/process.h" | ||
| 40 | #include "core/hle/kernel/scheduler.h" | 41 | #include "core/hle/kernel/scheduler.h" |
| 42 | #include "core/hle/kernel/vm_manager.h" | ||
| 41 | #include "core/loader/loader.h" | 43 | #include "core/loader/loader.h" |
| 42 | #include "core/memory.h" | 44 | #include "core/memory.h" |
| 43 | 45 | ||
| @@ -585,7 +587,8 @@ static void HandleQuery() { | |||
| 585 | strlen("Xfer:features:read:target.xml:")) == 0) { | 587 | strlen("Xfer:features:read:target.xml:")) == 0) { |
| 586 | SendReply(target_xml); | 588 | SendReply(target_xml); |
| 587 | } else if (strncmp(query, "Offsets", strlen("Offsets")) == 0) { | 589 | } else if (strncmp(query, "Offsets", strlen("Offsets")) == 0) { |
| 588 | std::string buffer = fmt::format("TextSeg={:0x}", Memory::PROCESS_IMAGE_VADDR); | 590 | const VAddr base_address = Core::CurrentProcess()->vm_manager.GetCodeRegionBaseAddress(); |
| 591 | std::string buffer = fmt::format("TextSeg={:0x}", base_address); | ||
| 589 | SendReply(buffer.c_str()); | 592 | SendReply(buffer.c_str()); |
| 590 | } else if (strncmp(query, "fThreadInfo", strlen("fThreadInfo")) == 0) { | 593 | } else if (strncmp(query, "fThreadInfo", strlen("fThreadInfo")) == 0) { |
| 591 | std::string val = "m"; | 594 | std::string val = "m"; |
| @@ -893,11 +896,11 @@ static void ReadMemory() { | |||
| 893 | static u8 reply[GDB_BUFFER_SIZE - 4]; | 896 | static u8 reply[GDB_BUFFER_SIZE - 4]; |
| 894 | 897 | ||
| 895 | auto start_offset = command_buffer + 1; | 898 | auto start_offset = command_buffer + 1; |
| 896 | auto addr_pos = std::find(start_offset, command_buffer + command_length, ','); | 899 | const auto addr_pos = std::find(start_offset, command_buffer + command_length, ','); |
| 897 | VAddr addr = HexToLong(start_offset, static_cast<u64>(addr_pos - start_offset)); | 900 | const VAddr addr = HexToLong(start_offset, static_cast<u64>(addr_pos - start_offset)); |
| 898 | 901 | ||
| 899 | start_offset = addr_pos + 1; | 902 | start_offset = addr_pos + 1; |
| 900 | u64 len = | 903 | const u64 len = |
| 901 | HexToLong(start_offset, static_cast<u64>((command_buffer + command_length) - start_offset)); | 904 | HexToLong(start_offset, static_cast<u64>((command_buffer + command_length) - start_offset)); |
| 902 | 905 | ||
| 903 | LOG_DEBUG(Debug_GDBStub, "gdb: addr: {:016X} len: {:016X}", addr, len); | 906 | LOG_DEBUG(Debug_GDBStub, "gdb: addr: {:016X} len: {:016X}", addr, len); |
| @@ -906,7 +909,9 @@ static void ReadMemory() { | |||
| 906 | SendReply("E01"); | 909 | SendReply("E01"); |
| 907 | } | 910 | } |
| 908 | 911 | ||
| 909 | if (addr < Memory::PROCESS_IMAGE_VADDR || addr >= Memory::MAP_REGION_VADDR_END) { | 912 | const auto& vm_manager = Core::CurrentProcess()->vm_manager; |
| 913 | if (addr < vm_manager.GetCodeRegionBaseAddress() || | ||
| 914 | addr >= vm_manager.GetMapRegionEndAddress()) { | ||
| 910 | return SendReply("E00"); | 915 | return SendReply("E00"); |
| 911 | } | 916 | } |
| 912 | 917 | ||
diff --git a/src/core/hle/kernel/process.cpp b/src/core/hle/kernel/process.cpp index 121f741fd..a8e3098ca 100644 --- a/src/core/hle/kernel/process.cpp +++ b/src/core/hle/kernel/process.cpp | |||
| @@ -8,6 +8,7 @@ | |||
| 8 | #include "common/common_funcs.h" | 8 | #include "common/common_funcs.h" |
| 9 | #include "common/logging/log.h" | 9 | #include "common/logging/log.h" |
| 10 | #include "core/core.h" | 10 | #include "core/core.h" |
| 11 | #include "core/file_sys/program_metadata.h" | ||
| 11 | #include "core/hle/kernel/errors.h" | 12 | #include "core/hle/kernel/errors.h" |
| 12 | #include "core/hle/kernel/kernel.h" | 13 | #include "core/hle/kernel/kernel.h" |
| 13 | #include "core/hle/kernel/process.h" | 14 | #include "core/hle/kernel/process.h" |
| @@ -34,14 +35,21 @@ SharedPtr<Process> Process::Create(KernelCore& kernel, std::string&& name) { | |||
| 34 | process->name = std::move(name); | 35 | process->name = std::move(name); |
| 35 | process->flags.raw = 0; | 36 | process->flags.raw = 0; |
| 36 | process->flags.memory_region.Assign(MemoryRegion::APPLICATION); | 37 | process->flags.memory_region.Assign(MemoryRegion::APPLICATION); |
| 38 | process->resource_limit = kernel.ResourceLimitForCategory(ResourceLimitCategory::APPLICATION); | ||
| 37 | process->status = ProcessStatus::Created; | 39 | process->status = ProcessStatus::Created; |
| 38 | process->program_id = 0; | 40 | process->program_id = 0; |
| 39 | process->process_id = kernel.CreateNewProcessID(); | 41 | process->process_id = kernel.CreateNewProcessID(); |
| 42 | process->svc_access_mask.set(); | ||
| 40 | 43 | ||
| 41 | kernel.AppendNewProcess(process); | 44 | kernel.AppendNewProcess(process); |
| 42 | return process; | 45 | return process; |
| 43 | } | 46 | } |
| 44 | 47 | ||
| 48 | void Process::LoadFromMetadata(const FileSys::ProgramMetadata& metadata) { | ||
| 49 | program_id = metadata.GetTitleID(); | ||
| 50 | vm_manager.Reset(metadata.GetAddressSpaceType()); | ||
| 51 | } | ||
| 52 | |||
| 45 | void Process::ParseKernelCaps(const u32* kernel_caps, std::size_t len) { | 53 | void Process::ParseKernelCaps(const u32* kernel_caps, std::size_t len) { |
| 46 | for (std::size_t i = 0; i < len; ++i) { | 54 | for (std::size_t i = 0; i < len; ++i) { |
| 47 | u32 descriptor = kernel_caps[i]; | 55 | u32 descriptor = kernel_caps[i]; |
| @@ -119,7 +127,7 @@ void Process::Run(VAddr entry_point, s32 main_thread_priority, u32 stack_size) { | |||
| 119 | // TODO(bunnei): This is heap area that should be allocated by the kernel and not mapped as part | 127 | // TODO(bunnei): This is heap area that should be allocated by the kernel and not mapped as part |
| 120 | // of the user address space. | 128 | // of the user address space. |
| 121 | vm_manager | 129 | vm_manager |
| 122 | .MapMemoryBlock(Memory::STACK_AREA_VADDR_END - stack_size, | 130 | .MapMemoryBlock(vm_manager.GetTLSIORegionEndAddress() - stack_size, |
| 123 | std::make_shared<std::vector<u8>>(stack_size, 0), 0, stack_size, | 131 | std::make_shared<std::vector<u8>>(stack_size, 0), 0, stack_size, |
| 124 | MemoryState::Mapped) | 132 | MemoryState::Mapped) |
| 125 | .Unwrap(); | 133 | .Unwrap(); |
| @@ -185,6 +193,7 @@ static std::tuple<std::size_t, std::size_t, bool> FindFreeThreadLocalSlot( | |||
| 185 | 193 | ||
| 186 | VAddr Process::MarkNextAvailableTLSSlotAsUsed(Thread& thread) { | 194 | VAddr Process::MarkNextAvailableTLSSlotAsUsed(Thread& thread) { |
| 187 | auto [available_page, available_slot, needs_allocation] = FindFreeThreadLocalSlot(tls_slots); | 195 | auto [available_page, available_slot, needs_allocation] = FindFreeThreadLocalSlot(tls_slots); |
| 196 | const VAddr tls_begin = vm_manager.GetTLSIORegionBaseAddress(); | ||
| 188 | 197 | ||
| 189 | if (needs_allocation) { | 198 | if (needs_allocation) { |
| 190 | tls_slots.emplace_back(0); // The page is completely available at the start | 199 | tls_slots.emplace_back(0); // The page is completely available at the start |
| @@ -197,18 +206,17 @@ VAddr Process::MarkNextAvailableTLSSlotAsUsed(Thread& thread) { | |||
| 197 | 206 | ||
| 198 | vm_manager.RefreshMemoryBlockMappings(tls_memory.get()); | 207 | vm_manager.RefreshMemoryBlockMappings(tls_memory.get()); |
| 199 | 208 | ||
| 200 | vm_manager.MapMemoryBlock(Memory::TLS_AREA_VADDR + available_page * Memory::PAGE_SIZE, | 209 | vm_manager.MapMemoryBlock(tls_begin + available_page * Memory::PAGE_SIZE, tls_memory, 0, |
| 201 | tls_memory, 0, Memory::PAGE_SIZE, MemoryState::ThreadLocal); | 210 | Memory::PAGE_SIZE, MemoryState::ThreadLocal); |
| 202 | } | 211 | } |
| 203 | 212 | ||
| 204 | tls_slots[available_page].set(available_slot); | 213 | tls_slots[available_page].set(available_slot); |
| 205 | 214 | ||
| 206 | return Memory::TLS_AREA_VADDR + available_page * Memory::PAGE_SIZE + | 215 | return tls_begin + available_page * Memory::PAGE_SIZE + available_slot * Memory::TLS_ENTRY_SIZE; |
| 207 | available_slot * Memory::TLS_ENTRY_SIZE; | ||
| 208 | } | 216 | } |
| 209 | 217 | ||
| 210 | void Process::FreeTLSSlot(VAddr tls_address) { | 218 | void Process::FreeTLSSlot(VAddr tls_address) { |
| 211 | const VAddr tls_base = tls_address - Memory::TLS_AREA_VADDR; | 219 | const VAddr tls_base = tls_address - vm_manager.GetTLSIORegionBaseAddress(); |
| 212 | const VAddr tls_page = tls_base / Memory::PAGE_SIZE; | 220 | const VAddr tls_page = tls_base / Memory::PAGE_SIZE; |
| 213 | const VAddr tls_slot = (tls_base % Memory::PAGE_SIZE) / Memory::TLS_ENTRY_SIZE; | 221 | const VAddr tls_slot = (tls_base % Memory::PAGE_SIZE) / Memory::TLS_ENTRY_SIZE; |
| 214 | 222 | ||
| @@ -232,8 +240,8 @@ void Process::LoadModule(SharedPtr<CodeSet> module_, VAddr base_addr) { | |||
| 232 | } | 240 | } |
| 233 | 241 | ||
| 234 | ResultVal<VAddr> Process::HeapAllocate(VAddr target, u64 size, VMAPermission perms) { | 242 | ResultVal<VAddr> Process::HeapAllocate(VAddr target, u64 size, VMAPermission perms) { |
| 235 | if (target < Memory::HEAP_VADDR || target + size > Memory::HEAP_VADDR_END || | 243 | if (target < vm_manager.GetHeapRegionBaseAddress() || |
| 236 | target + size < target) { | 244 | target + size > vm_manager.GetHeapRegionEndAddress() || target + size < target) { |
| 237 | return ERR_INVALID_ADDRESS; | 245 | return ERR_INVALID_ADDRESS; |
| 238 | } | 246 | } |
| 239 | 247 | ||
| @@ -268,8 +276,8 @@ ResultVal<VAddr> Process::HeapAllocate(VAddr target, u64 size, VMAPermission per | |||
| 268 | } | 276 | } |
| 269 | 277 | ||
| 270 | ResultCode Process::HeapFree(VAddr target, u32 size) { | 278 | ResultCode Process::HeapFree(VAddr target, u32 size) { |
| 271 | if (target < Memory::HEAP_VADDR || target + size > Memory::HEAP_VADDR_END || | 279 | if (target < vm_manager.GetHeapRegionBaseAddress() || |
| 272 | target + size < target) { | 280 | target + size > vm_manager.GetHeapRegionEndAddress() || target + size < target) { |
| 273 | return ERR_INVALID_ADDRESS; | 281 | return ERR_INVALID_ADDRESS; |
| 274 | } | 282 | } |
| 275 | 283 | ||
diff --git a/src/core/hle/kernel/process.h b/src/core/hle/kernel/process.h index 04d74e572..adb03c228 100644 --- a/src/core/hle/kernel/process.h +++ b/src/core/hle/kernel/process.h | |||
| @@ -17,6 +17,10 @@ | |||
| 17 | #include "core/hle/kernel/thread.h" | 17 | #include "core/hle/kernel/thread.h" |
| 18 | #include "core/hle/kernel/vm_manager.h" | 18 | #include "core/hle/kernel/vm_manager.h" |
| 19 | 19 | ||
| 20 | namespace FileSys { | ||
| 21 | class ProgramMetadata; | ||
| 22 | } | ||
| 23 | |||
| 20 | namespace Kernel { | 24 | namespace Kernel { |
| 21 | 25 | ||
| 22 | class KernelCore; | 26 | class KernelCore; |
| @@ -141,6 +145,14 @@ public: | |||
| 141 | return process_id; | 145 | return process_id; |
| 142 | } | 146 | } |
| 143 | 147 | ||
| 148 | /** | ||
| 149 | * Loads process-specifics configuration info with metadata provided | ||
| 150 | * by an executable. | ||
| 151 | * | ||
| 152 | * @param metadata The provided metadata to load process specific info. | ||
| 153 | */ | ||
| 154 | void LoadFromMetadata(const FileSys::ProgramMetadata& metadata); | ||
| 155 | |||
| 144 | /// Title ID corresponding to the process | 156 | /// Title ID corresponding to the process |
| 145 | u64 program_id; | 157 | u64 program_id; |
| 146 | 158 | ||
diff --git a/src/core/hle/kernel/shared_memory.cpp b/src/core/hle/kernel/shared_memory.cpp index abb1d09cd..9b78c8cb5 100644 --- a/src/core/hle/kernel/shared_memory.cpp +++ b/src/core/hle/kernel/shared_memory.cpp | |||
| @@ -8,6 +8,7 @@ | |||
| 8 | #include "common/logging/log.h" | 8 | #include "common/logging/log.h" |
| 9 | #include "core/core.h" | 9 | #include "core/core.h" |
| 10 | #include "core/hle/kernel/errors.h" | 10 | #include "core/hle/kernel/errors.h" |
| 11 | #include "core/hle/kernel/kernel.h" | ||
| 11 | #include "core/hle/kernel/shared_memory.h" | 12 | #include "core/hle/kernel/shared_memory.h" |
| 12 | #include "core/memory.h" | 13 | #include "core/memory.h" |
| 13 | 14 | ||
| @@ -71,7 +72,8 @@ SharedPtr<SharedMemory> SharedMemory::CreateForApplet( | |||
| 71 | shared_memory->other_permissions = other_permissions; | 72 | shared_memory->other_permissions = other_permissions; |
| 72 | shared_memory->backing_block = std::move(heap_block); | 73 | shared_memory->backing_block = std::move(heap_block); |
| 73 | shared_memory->backing_block_offset = offset; | 74 | shared_memory->backing_block_offset = offset; |
| 74 | shared_memory->base_address = Memory::HEAP_VADDR + offset; | 75 | shared_memory->base_address = |
| 76 | kernel.CurrentProcess()->vm_manager.GetHeapRegionBaseAddress() + offset; | ||
| 75 | 77 | ||
| 76 | return shared_memory; | 78 | return shared_memory; |
| 77 | } | 79 | } |
diff --git a/src/core/hle/kernel/svc.cpp b/src/core/hle/kernel/svc.cpp index c9d212a4c..44bbaf0c8 100644 --- a/src/core/hle/kernel/svc.cpp +++ b/src/core/hle/kernel/svc.cpp | |||
| @@ -51,8 +51,9 @@ static ResultCode SetHeapSize(VAddr* heap_addr, u64 heap_size) { | |||
| 51 | } | 51 | } |
| 52 | 52 | ||
| 53 | auto& process = *Core::CurrentProcess(); | 53 | auto& process = *Core::CurrentProcess(); |
| 54 | const VAddr heap_base = process.vm_manager.GetHeapRegionBaseAddress(); | ||
| 54 | CASCADE_RESULT(*heap_addr, | 55 | CASCADE_RESULT(*heap_addr, |
| 55 | process.HeapAllocate(Memory::HEAP_VADDR, heap_size, VMAPermission::ReadWrite)); | 56 | process.HeapAllocate(heap_base, heap_size, VMAPermission::ReadWrite)); |
| 56 | return RESULT_SUCCESS; | 57 | return RESULT_SUCCESS; |
| 57 | } | 58 | } |
| 58 | 59 | ||
| @@ -325,26 +326,27 @@ static ResultCode GetInfo(u64* result, u64 info_id, u64 handle, u64 info_sub_id) | |||
| 325 | LOG_TRACE(Kernel_SVC, "called info_id=0x{:X}, info_sub_id=0x{:X}, handle=0x{:08X}", info_id, | 326 | LOG_TRACE(Kernel_SVC, "called info_id=0x{:X}, info_sub_id=0x{:X}, handle=0x{:08X}", info_id, |
| 326 | info_sub_id, handle); | 327 | info_sub_id, handle); |
| 327 | 328 | ||
| 328 | const auto& vm_manager = Core::CurrentProcess()->vm_manager; | 329 | const auto& current_process = Core::CurrentProcess(); |
| 330 | const auto& vm_manager = current_process->vm_manager; | ||
| 329 | 331 | ||
| 330 | switch (static_cast<GetInfoType>(info_id)) { | 332 | switch (static_cast<GetInfoType>(info_id)) { |
| 331 | case GetInfoType::AllowedCpuIdBitmask: | 333 | case GetInfoType::AllowedCpuIdBitmask: |
| 332 | *result = Core::CurrentProcess()->allowed_processor_mask; | 334 | *result = current_process->allowed_processor_mask; |
| 333 | break; | 335 | break; |
| 334 | case GetInfoType::AllowedThreadPrioBitmask: | 336 | case GetInfoType::AllowedThreadPrioBitmask: |
| 335 | *result = Core::CurrentProcess()->allowed_thread_priority_mask; | 337 | *result = current_process->allowed_thread_priority_mask; |
| 336 | break; | 338 | break; |
| 337 | case GetInfoType::MapRegionBaseAddr: | 339 | case GetInfoType::MapRegionBaseAddr: |
| 338 | *result = Memory::MAP_REGION_VADDR; | 340 | *result = vm_manager.GetMapRegionBaseAddress(); |
| 339 | break; | 341 | break; |
| 340 | case GetInfoType::MapRegionSize: | 342 | case GetInfoType::MapRegionSize: |
| 341 | *result = Memory::MAP_REGION_SIZE; | 343 | *result = vm_manager.GetMapRegionSize(); |
| 342 | break; | 344 | break; |
| 343 | case GetInfoType::HeapRegionBaseAddr: | 345 | case GetInfoType::HeapRegionBaseAddr: |
| 344 | *result = Memory::HEAP_VADDR; | 346 | *result = vm_manager.GetHeapRegionBaseAddress(); |
| 345 | break; | 347 | break; |
| 346 | case GetInfoType::HeapRegionSize: | 348 | case GetInfoType::HeapRegionSize: |
| 347 | *result = Memory::HEAP_SIZE; | 349 | *result = vm_manager.GetHeapRegionSize(); |
| 348 | break; | 350 | break; |
| 349 | case GetInfoType::TotalMemoryUsage: | 351 | case GetInfoType::TotalMemoryUsage: |
| 350 | *result = vm_manager.GetTotalMemoryUsage(); | 352 | *result = vm_manager.GetTotalMemoryUsage(); |
| @@ -359,22 +361,35 @@ static ResultCode GetInfo(u64* result, u64 info_id, u64 handle, u64 info_sub_id) | |||
| 359 | *result = 0; | 361 | *result = 0; |
| 360 | break; | 362 | break; |
| 361 | case GetInfoType::AddressSpaceBaseAddr: | 363 | case GetInfoType::AddressSpaceBaseAddr: |
| 362 | *result = vm_manager.GetAddressSpaceBaseAddr(); | 364 | *result = vm_manager.GetCodeRegionBaseAddress(); |
| 363 | break; | 365 | break; |
| 364 | case GetInfoType::AddressSpaceSize: | 366 | case GetInfoType::AddressSpaceSize: { |
| 365 | *result = vm_manager.GetAddressSpaceSize(); | 367 | const u64 width = vm_manager.GetAddressSpaceWidth(); |
| 368 | |||
| 369 | switch (width) { | ||
| 370 | case 32: | ||
| 371 | *result = 0xFFE00000; | ||
| 372 | break; | ||
| 373 | case 36: | ||
| 374 | *result = 0xFF8000000; | ||
| 375 | break; | ||
| 376 | case 39: | ||
| 377 | *result = 0x7FF8000000; | ||
| 378 | break; | ||
| 379 | } | ||
| 366 | break; | 380 | break; |
| 381 | } | ||
| 367 | case GetInfoType::NewMapRegionBaseAddr: | 382 | case GetInfoType::NewMapRegionBaseAddr: |
| 368 | *result = Memory::NEW_MAP_REGION_VADDR; | 383 | *result = vm_manager.GetNewMapRegionBaseAddress(); |
| 369 | break; | 384 | break; |
| 370 | case GetInfoType::NewMapRegionSize: | 385 | case GetInfoType::NewMapRegionSize: |
| 371 | *result = Memory::NEW_MAP_REGION_SIZE; | 386 | *result = vm_manager.GetNewMapRegionSize(); |
| 372 | break; | 387 | break; |
| 373 | case GetInfoType::IsVirtualAddressMemoryEnabled: | 388 | case GetInfoType::IsVirtualAddressMemoryEnabled: |
| 374 | *result = Core::CurrentProcess()->is_virtual_address_memory_enabled; | 389 | *result = current_process->is_virtual_address_memory_enabled; |
| 375 | break; | 390 | break; |
| 376 | case GetInfoType::TitleId: | 391 | case GetInfoType::TitleId: |
| 377 | *result = Core::CurrentProcess()->program_id; | 392 | *result = current_process->program_id; |
| 378 | break; | 393 | break; |
| 379 | case GetInfoType::PrivilegedProcessId: | 394 | case GetInfoType::PrivilegedProcessId: |
| 380 | LOG_WARNING(Kernel_SVC, | 395 | LOG_WARNING(Kernel_SVC, |
diff --git a/src/core/hle/kernel/thread.cpp b/src/core/hle/kernel/thread.cpp index 315f65338..064ed908d 100644 --- a/src/core/hle/kernel/thread.cpp +++ b/src/core/hle/kernel/thread.cpp | |||
| @@ -262,8 +262,9 @@ SharedPtr<Thread> SetupMainThread(KernelCore& kernel, VAddr entry_point, u32 pri | |||
| 262 | SetCurrentPageTable(&owner_process.vm_manager.page_table); | 262 | SetCurrentPageTable(&owner_process.vm_manager.page_table); |
| 263 | 263 | ||
| 264 | // Initialize new "main" thread | 264 | // Initialize new "main" thread |
| 265 | const VAddr stack_top = owner_process.vm_manager.GetTLSIORegionEndAddress(); | ||
| 265 | auto thread_res = Thread::Create(kernel, "main", entry_point, priority, 0, THREADPROCESSORID_0, | 266 | auto thread_res = Thread::Create(kernel, "main", entry_point, priority, 0, THREADPROCESSORID_0, |
| 266 | Memory::STACK_AREA_VADDR_END, &owner_process); | 267 | stack_top, &owner_process); |
| 267 | 268 | ||
| 268 | SharedPtr<Thread> thread = std::move(thread_res).Unwrap(); | 269 | SharedPtr<Thread> thread = std::move(thread_res).Unwrap(); |
| 269 | 270 | ||
diff --git a/src/core/hle/kernel/vm_manager.cpp b/src/core/hle/kernel/vm_manager.cpp index 608cbd57b..e412309fd 100644 --- a/src/core/hle/kernel/vm_manager.cpp +++ b/src/core/hle/kernel/vm_manager.cpp | |||
| @@ -9,6 +9,7 @@ | |||
| 9 | #include "common/logging/log.h" | 9 | #include "common/logging/log.h" |
| 10 | #include "core/arm/arm_interface.h" | 10 | #include "core/arm/arm_interface.h" |
| 11 | #include "core/core.h" | 11 | #include "core/core.h" |
| 12 | #include "core/file_sys/program_metadata.h" | ||
| 12 | #include "core/hle/kernel/errors.h" | 13 | #include "core/hle/kernel/errors.h" |
| 13 | #include "core/hle/kernel/vm_manager.h" | 14 | #include "core/hle/kernel/vm_manager.h" |
| 14 | #include "core/memory.h" | 15 | #include "core/memory.h" |
| @@ -54,30 +55,32 @@ bool VirtualMemoryArea::CanBeMergedWith(const VirtualMemoryArea& next) const { | |||
| 54 | } | 55 | } |
| 55 | 56 | ||
| 56 | VMManager::VMManager() { | 57 | VMManager::VMManager() { |
| 57 | Reset(); | 58 | // Default to assuming a 39-bit address space. This way we have a sane |
| 59 | // starting point with executables that don't provide metadata. | ||
| 60 | Reset(FileSys::ProgramAddressSpaceType::Is39Bit); | ||
| 58 | } | 61 | } |
| 59 | 62 | ||
| 60 | VMManager::~VMManager() { | 63 | VMManager::~VMManager() { |
| 61 | Reset(); | 64 | Reset(FileSys::ProgramAddressSpaceType::Is39Bit); |
| 62 | } | 65 | } |
| 63 | 66 | ||
| 64 | void VMManager::Reset() { | 67 | void VMManager::Reset(FileSys::ProgramAddressSpaceType type) { |
| 65 | vma_map.clear(); | 68 | Clear(); |
| 69 | |||
| 70 | InitializeMemoryRegionRanges(type); | ||
| 71 | |||
| 72 | page_table.Resize(address_space_width); | ||
| 66 | 73 | ||
| 67 | // Initialize the map with a single free region covering the entire managed space. | 74 | // Initialize the map with a single free region covering the entire managed space. |
| 68 | VirtualMemoryArea initial_vma; | 75 | VirtualMemoryArea initial_vma; |
| 69 | initial_vma.size = MAX_ADDRESS; | 76 | initial_vma.size = address_space_end; |
| 70 | vma_map.emplace(initial_vma.base, initial_vma); | 77 | vma_map.emplace(initial_vma.base, initial_vma); |
| 71 | 78 | ||
| 72 | page_table.pointers.fill(nullptr); | ||
| 73 | page_table.special_regions.clear(); | ||
| 74 | page_table.attributes.fill(Memory::PageType::Unmapped); | ||
| 75 | |||
| 76 | UpdatePageTableForVMA(initial_vma); | 79 | UpdatePageTableForVMA(initial_vma); |
| 77 | } | 80 | } |
| 78 | 81 | ||
| 79 | VMManager::VMAHandle VMManager::FindVMA(VAddr target) const { | 82 | VMManager::VMAHandle VMManager::FindVMA(VAddr target) const { |
| 80 | if (target >= MAX_ADDRESS) { | 83 | if (target >= address_space_end) { |
| 81 | return vma_map.end(); | 84 | return vma_map.end(); |
| 82 | } else { | 85 | } else { |
| 83 | return std::prev(vma_map.upper_bound(target)); | 86 | return std::prev(vma_map.upper_bound(target)); |
| @@ -291,7 +294,7 @@ ResultVal<VMManager::VMAIter> VMManager::CarveVMARange(VAddr target, u64 size) { | |||
| 291 | 294 | ||
| 292 | const VAddr target_end = target + size; | 295 | const VAddr target_end = target + size; |
| 293 | ASSERT(target_end >= target); | 296 | ASSERT(target_end >= target); |
| 294 | ASSERT(target_end <= MAX_ADDRESS); | 297 | ASSERT(target_end <= address_space_end); |
| 295 | ASSERT(size > 0); | 298 | ASSERT(size > 0); |
| 296 | 299 | ||
| 297 | VMAIter begin_vma = StripIterConstness(FindVMA(target)); | 300 | VMAIter begin_vma = StripIterConstness(FindVMA(target)); |
| @@ -382,6 +385,85 @@ void VMManager::UpdatePageTableForVMA(const VirtualMemoryArea& vma) { | |||
| 382 | } | 385 | } |
| 383 | } | 386 | } |
| 384 | 387 | ||
| 388 | void VMManager::InitializeMemoryRegionRanges(FileSys::ProgramAddressSpaceType type) { | ||
| 389 | u64 map_region_size = 0; | ||
| 390 | u64 heap_region_size = 0; | ||
| 391 | u64 new_map_region_size = 0; | ||
| 392 | u64 tls_io_region_size = 0; | ||
| 393 | |||
| 394 | switch (type) { | ||
| 395 | case FileSys::ProgramAddressSpaceType::Is32Bit: | ||
| 396 | address_space_width = 32; | ||
| 397 | code_region_base = 0x200000; | ||
| 398 | code_region_end = code_region_base + 0x3FE00000; | ||
| 399 | map_region_size = 0x40000000; | ||
| 400 | heap_region_size = 0x40000000; | ||
| 401 | break; | ||
| 402 | case FileSys::ProgramAddressSpaceType::Is36Bit: | ||
| 403 | address_space_width = 36; | ||
| 404 | code_region_base = 0x8000000; | ||
| 405 | code_region_end = code_region_base + 0x78000000; | ||
| 406 | map_region_size = 0x180000000; | ||
| 407 | heap_region_size = 0x180000000; | ||
| 408 | break; | ||
| 409 | case FileSys::ProgramAddressSpaceType::Is32BitNoMap: | ||
| 410 | address_space_width = 32; | ||
| 411 | code_region_base = 0x200000; | ||
| 412 | code_region_end = code_region_base + 0x3FE00000; | ||
| 413 | map_region_size = 0; | ||
| 414 | heap_region_size = 0x80000000; | ||
| 415 | break; | ||
| 416 | case FileSys::ProgramAddressSpaceType::Is39Bit: | ||
| 417 | address_space_width = 39; | ||
| 418 | code_region_base = 0x8000000; | ||
| 419 | code_region_end = code_region_base + 0x80000000; | ||
| 420 | map_region_size = 0x1000000000; | ||
| 421 | heap_region_size = 0x180000000; | ||
| 422 | new_map_region_size = 0x80000000; | ||
| 423 | tls_io_region_size = 0x1000000000; | ||
| 424 | break; | ||
| 425 | default: | ||
| 426 | UNREACHABLE_MSG("Invalid address space type specified: {}", static_cast<u32>(type)); | ||
| 427 | return; | ||
| 428 | } | ||
| 429 | |||
| 430 | address_space_base = 0; | ||
| 431 | address_space_end = 1ULL << address_space_width; | ||
| 432 | |||
| 433 | map_region_base = code_region_end; | ||
| 434 | map_region_end = map_region_base + map_region_size; | ||
| 435 | |||
| 436 | heap_region_base = map_region_end; | ||
| 437 | heap_region_end = heap_region_base + heap_region_size; | ||
| 438 | |||
| 439 | new_map_region_base = heap_region_end; | ||
| 440 | new_map_region_end = new_map_region_base + new_map_region_size; | ||
| 441 | |||
| 442 | tls_io_region_base = new_map_region_end; | ||
| 443 | tls_io_region_end = tls_io_region_base + tls_io_region_size; | ||
| 444 | |||
| 445 | if (new_map_region_size == 0) { | ||
| 446 | new_map_region_base = address_space_base; | ||
| 447 | new_map_region_end = address_space_end; | ||
| 448 | } | ||
| 449 | } | ||
| 450 | |||
| 451 | void VMManager::Clear() { | ||
| 452 | ClearVMAMap(); | ||
| 453 | ClearPageTable(); | ||
| 454 | } | ||
| 455 | |||
| 456 | void VMManager::ClearVMAMap() { | ||
| 457 | vma_map.clear(); | ||
| 458 | } | ||
| 459 | |||
| 460 | void VMManager::ClearPageTable() { | ||
| 461 | std::fill(page_table.pointers.begin(), page_table.pointers.end(), nullptr); | ||
| 462 | page_table.special_regions.clear(); | ||
| 463 | std::fill(page_table.attributes.begin(), page_table.attributes.end(), | ||
| 464 | Memory::PageType::Unmapped); | ||
| 465 | } | ||
| 466 | |||
| 385 | u64 VMManager::GetTotalMemoryUsage() const { | 467 | u64 VMManager::GetTotalMemoryUsage() const { |
| 386 | LOG_WARNING(Kernel, "(STUBBED) called"); | 468 | LOG_WARNING(Kernel, "(STUBBED) called"); |
| 387 | return 0xF8000000; | 469 | return 0xF8000000; |
| @@ -392,14 +474,80 @@ u64 VMManager::GetTotalHeapUsage() const { | |||
| 392 | return 0x0; | 474 | return 0x0; |
| 393 | } | 475 | } |
| 394 | 476 | ||
| 395 | VAddr VMManager::GetAddressSpaceBaseAddr() const { | 477 | VAddr VMManager::GetAddressSpaceBaseAddress() const { |
| 396 | LOG_WARNING(Kernel, "(STUBBED) called"); | 478 | return address_space_base; |
| 397 | return 0x8000000; | 479 | } |
| 480 | |||
| 481 | VAddr VMManager::GetAddressSpaceEndAddress() const { | ||
| 482 | return address_space_end; | ||
| 398 | } | 483 | } |
| 399 | 484 | ||
| 400 | u64 VMManager::GetAddressSpaceSize() const { | 485 | u64 VMManager::GetAddressSpaceSize() const { |
| 401 | LOG_WARNING(Kernel, "(STUBBED) called"); | 486 | return address_space_end - address_space_base; |
| 402 | return MAX_ADDRESS; | 487 | } |
| 488 | |||
| 489 | u64 VMManager::GetAddressSpaceWidth() const { | ||
| 490 | return address_space_width; | ||
| 491 | } | ||
| 492 | |||
| 493 | VAddr VMManager::GetCodeRegionBaseAddress() const { | ||
| 494 | return code_region_base; | ||
| 495 | } | ||
| 496 | |||
| 497 | VAddr VMManager::GetCodeRegionEndAddress() const { | ||
| 498 | return code_region_end; | ||
| 499 | } | ||
| 500 | |||
| 501 | u64 VMManager::GetCodeRegionSize() const { | ||
| 502 | return code_region_end - code_region_base; | ||
| 503 | } | ||
| 504 | |||
| 505 | VAddr VMManager::GetHeapRegionBaseAddress() const { | ||
| 506 | return heap_region_base; | ||
| 507 | } | ||
| 508 | |||
| 509 | VAddr VMManager::GetHeapRegionEndAddress() const { | ||
| 510 | return heap_region_end; | ||
| 511 | } | ||
| 512 | |||
| 513 | u64 VMManager::GetHeapRegionSize() const { | ||
| 514 | return heap_region_end - heap_region_base; | ||
| 515 | } | ||
| 516 | |||
| 517 | VAddr VMManager::GetMapRegionBaseAddress() const { | ||
| 518 | return map_region_base; | ||
| 519 | } | ||
| 520 | |||
| 521 | VAddr VMManager::GetMapRegionEndAddress() const { | ||
| 522 | return map_region_end; | ||
| 523 | } | ||
| 524 | |||
| 525 | u64 VMManager::GetMapRegionSize() const { | ||
| 526 | return map_region_end - map_region_base; | ||
| 527 | } | ||
| 528 | |||
| 529 | VAddr VMManager::GetNewMapRegionBaseAddress() const { | ||
| 530 | return new_map_region_base; | ||
| 531 | } | ||
| 532 | |||
| 533 | VAddr VMManager::GetNewMapRegionEndAddress() const { | ||
| 534 | return new_map_region_end; | ||
| 535 | } | ||
| 536 | |||
| 537 | u64 VMManager::GetNewMapRegionSize() const { | ||
| 538 | return new_map_region_end - new_map_region_base; | ||
| 539 | } | ||
| 540 | |||
| 541 | VAddr VMManager::GetTLSIORegionBaseAddress() const { | ||
| 542 | return tls_io_region_base; | ||
| 543 | } | ||
| 544 | |||
| 545 | VAddr VMManager::GetTLSIORegionEndAddress() const { | ||
| 546 | return tls_io_region_end; | ||
| 547 | } | ||
| 548 | |||
| 549 | u64 VMManager::GetTLSIORegionSize() const { | ||
| 550 | return tls_io_region_end - tls_io_region_base; | ||
| 403 | } | 551 | } |
| 404 | 552 | ||
| 405 | } // namespace Kernel | 553 | } // namespace Kernel |
diff --git a/src/core/hle/kernel/vm_manager.h b/src/core/hle/kernel/vm_manager.h index de75036c0..015559a64 100644 --- a/src/core/hle/kernel/vm_manager.h +++ b/src/core/hle/kernel/vm_manager.h | |||
| @@ -12,6 +12,10 @@ | |||
| 12 | #include "core/memory.h" | 12 | #include "core/memory.h" |
| 13 | #include "core/memory_hook.h" | 13 | #include "core/memory_hook.h" |
| 14 | 14 | ||
| 15 | namespace FileSys { | ||
| 16 | enum class ProgramAddressSpaceType : u8; | ||
| 17 | } | ||
| 18 | |||
| 15 | namespace Kernel { | 19 | namespace Kernel { |
| 16 | 20 | ||
| 17 | enum class VMAType : u8 { | 21 | enum class VMAType : u8 { |
| @@ -111,12 +115,6 @@ struct VirtualMemoryArea { | |||
| 111 | class VMManager final { | 115 | class VMManager final { |
| 112 | public: | 116 | public: |
| 113 | /** | 117 | /** |
| 114 | * The maximum amount of address space managed by the kernel. | ||
| 115 | * @todo This was selected arbitrarily, and should be verified for Switch OS. | ||
| 116 | */ | ||
| 117 | static constexpr VAddr MAX_ADDRESS{0x1000000000ULL}; | ||
| 118 | |||
| 119 | /** | ||
| 120 | * A map covering the entirety of the managed address space, keyed by the `base` field of each | 118 | * A map covering the entirety of the managed address space, keyed by the `base` field of each |
| 121 | * VMA. It must always be modified by splitting or merging VMAs, so that the invariant | 119 | * VMA. It must always be modified by splitting or merging VMAs, so that the invariant |
| 122 | * `elem.base + elem.size == next.base` is preserved, and mergeable regions must always be | 120 | * `elem.base + elem.size == next.base` is preserved, and mergeable regions must always be |
| @@ -130,7 +128,7 @@ public: | |||
| 130 | ~VMManager(); | 128 | ~VMManager(); |
| 131 | 129 | ||
| 132 | /// Clears the address space map, re-initializing with a single free area. | 130 | /// Clears the address space map, re-initializing with a single free area. |
| 133 | void Reset(); | 131 | void Reset(FileSys::ProgramAddressSpaceType type); |
| 134 | 132 | ||
| 135 | /// Finds the VMA in which the given address is included in, or `vma_map.end()`. | 133 | /// Finds the VMA in which the given address is included in, or `vma_map.end()`. |
| 136 | VMAHandle FindVMA(VAddr target) const; | 134 | VMAHandle FindVMA(VAddr target) const; |
| @@ -195,12 +193,63 @@ public: | |||
| 195 | /// Gets the total heap usage, used by svcGetInfo | 193 | /// Gets the total heap usage, used by svcGetInfo |
| 196 | u64 GetTotalHeapUsage() const; | 194 | u64 GetTotalHeapUsage() const; |
| 197 | 195 | ||
| 198 | /// Gets the total address space base address, used by svcGetInfo | 196 | /// Gets the address space base address |
| 199 | VAddr GetAddressSpaceBaseAddr() const; | 197 | VAddr GetAddressSpaceBaseAddress() const; |
| 200 | 198 | ||
| 201 | /// Gets the total address space address size, used by svcGetInfo | 199 | /// Gets the address space end address |
| 200 | VAddr GetAddressSpaceEndAddress() const; | ||
| 201 | |||
| 202 | /// Gets the total address space address size in bytes | ||
| 202 | u64 GetAddressSpaceSize() const; | 203 | u64 GetAddressSpaceSize() const; |
| 203 | 204 | ||
| 205 | /// Gets the address space width in bits. | ||
| 206 | u64 GetAddressSpaceWidth() const; | ||
| 207 | |||
| 208 | /// Gets the base address of the code region. | ||
| 209 | VAddr GetCodeRegionBaseAddress() const; | ||
| 210 | |||
| 211 | /// Gets the end address of the code region. | ||
| 212 | VAddr GetCodeRegionEndAddress() const; | ||
| 213 | |||
| 214 | /// Gets the total size of the code region in bytes. | ||
| 215 | u64 GetCodeRegionSize() const; | ||
| 216 | |||
| 217 | /// Gets the base address of the heap region. | ||
| 218 | VAddr GetHeapRegionBaseAddress() const; | ||
| 219 | |||
| 220 | /// Gets the end address of the heap region; | ||
| 221 | VAddr GetHeapRegionEndAddress() const; | ||
| 222 | |||
| 223 | /// Gets the total size of the heap region in bytes. | ||
| 224 | u64 GetHeapRegionSize() const; | ||
| 225 | |||
| 226 | /// Gets the base address of the map region. | ||
| 227 | VAddr GetMapRegionBaseAddress() const; | ||
| 228 | |||
| 229 | /// Gets the end address of the map region. | ||
| 230 | VAddr GetMapRegionEndAddress() const; | ||
| 231 | |||
| 232 | /// Gets the total size of the map region in bytes. | ||
| 233 | u64 GetMapRegionSize() const; | ||
| 234 | |||
| 235 | /// Gets the base address of the new map region. | ||
| 236 | VAddr GetNewMapRegionBaseAddress() const; | ||
| 237 | |||
| 238 | /// Gets the end address of the new map region. | ||
| 239 | VAddr GetNewMapRegionEndAddress() const; | ||
| 240 | |||
| 241 | /// Gets the total size of the new map region in bytes. | ||
| 242 | u64 GetNewMapRegionSize() const; | ||
| 243 | |||
| 244 | /// Gets the base address of the TLS IO region. | ||
| 245 | VAddr GetTLSIORegionBaseAddress() const; | ||
| 246 | |||
| 247 | /// Gets the end address of the TLS IO region. | ||
| 248 | VAddr GetTLSIORegionEndAddress() const; | ||
| 249 | |||
| 250 | /// Gets the total size of the TLS IO region in bytes. | ||
| 251 | u64 GetTLSIORegionSize() const; | ||
| 252 | |||
| 204 | /// Each VMManager has its own page table, which is set as the main one when the owning process | 253 | /// Each VMManager has its own page table, which is set as the main one when the owning process |
| 205 | /// is scheduled. | 254 | /// is scheduled. |
| 206 | Memory::PageTable page_table; | 255 | Memory::PageTable page_table; |
| @@ -240,5 +289,36 @@ private: | |||
| 240 | 289 | ||
| 241 | /// Updates the pages corresponding to this VMA so they match the VMA's attributes. | 290 | /// Updates the pages corresponding to this VMA so they match the VMA's attributes. |
| 242 | void UpdatePageTableForVMA(const VirtualMemoryArea& vma); | 291 | void UpdatePageTableForVMA(const VirtualMemoryArea& vma); |
| 292 | |||
| 293 | /// Initializes memory region ranges to adhere to a given address space type. | ||
| 294 | void InitializeMemoryRegionRanges(FileSys::ProgramAddressSpaceType type); | ||
| 295 | |||
| 296 | /// Clears the underlying map and page table. | ||
| 297 | void Clear(); | ||
| 298 | |||
| 299 | /// Clears out the VMA map, unmapping any previously mapped ranges. | ||
| 300 | void ClearVMAMap(); | ||
| 301 | |||
| 302 | /// Clears out the page table | ||
| 303 | void ClearPageTable(); | ||
| 304 | |||
| 305 | u32 address_space_width = 0; | ||
| 306 | VAddr address_space_base = 0; | ||
| 307 | VAddr address_space_end = 0; | ||
| 308 | |||
| 309 | VAddr code_region_base = 0; | ||
| 310 | VAddr code_region_end = 0; | ||
| 311 | |||
| 312 | VAddr heap_region_base = 0; | ||
| 313 | VAddr heap_region_end = 0; | ||
| 314 | |||
| 315 | VAddr map_region_base = 0; | ||
| 316 | VAddr map_region_end = 0; | ||
| 317 | |||
| 318 | VAddr new_map_region_base = 0; | ||
| 319 | VAddr new_map_region_end = 0; | ||
| 320 | |||
| 321 | VAddr tls_io_region_base = 0; | ||
| 322 | VAddr tls_io_region_end = 0; | ||
| 243 | }; | 323 | }; |
| 244 | } // namespace Kernel | 324 | } // namespace Kernel |
diff --git a/src/core/hle/service/audio/audren_u.cpp b/src/core/hle/service/audio/audren_u.cpp index fa15712cf..6073f4ecd 100644 --- a/src/core/hle/service/audio/audren_u.cpp +++ b/src/core/hle/service/audio/audren_u.cpp | |||
| @@ -66,7 +66,7 @@ private: | |||
| 66 | void GetAudioRendererState(Kernel::HLERequestContext& ctx) { | 66 | void GetAudioRendererState(Kernel::HLERequestContext& ctx) { |
| 67 | IPC::ResponseBuilder rb{ctx, 3}; | 67 | IPC::ResponseBuilder rb{ctx, 3}; |
| 68 | rb.Push(RESULT_SUCCESS); | 68 | rb.Push(RESULT_SUCCESS); |
| 69 | rb.Push<u32>(renderer->GetState()); | 69 | rb.Push<u32>(static_cast<u32>(renderer->GetStreamState())); |
| 70 | LOG_DEBUG(Service_Audio, "called"); | 70 | LOG_DEBUG(Service_Audio, "called"); |
| 71 | } | 71 | } |
| 72 | 72 | ||
diff --git a/src/core/loader/deconstructed_rom_directory.cpp b/src/core/loader/deconstructed_rom_directory.cpp index 2b8f78136..7e8035d0f 100644 --- a/src/core/loader/deconstructed_rom_directory.cpp +++ b/src/core/loader/deconstructed_rom_directory.cpp | |||
| @@ -14,11 +14,9 @@ | |||
| 14 | #include "core/gdbstub/gdbstub.h" | 14 | #include "core/gdbstub/gdbstub.h" |
| 15 | #include "core/hle/kernel/kernel.h" | 15 | #include "core/hle/kernel/kernel.h" |
| 16 | #include "core/hle/kernel/process.h" | 16 | #include "core/hle/kernel/process.h" |
| 17 | #include "core/hle/kernel/resource_limit.h" | ||
| 18 | #include "core/hle/service/filesystem/filesystem.h" | 17 | #include "core/hle/service/filesystem/filesystem.h" |
| 19 | #include "core/loader/deconstructed_rom_directory.h" | 18 | #include "core/loader/deconstructed_rom_directory.h" |
| 20 | #include "core/loader/nso.h" | 19 | #include "core/loader/nso.h" |
| 21 | #include "core/memory.h" | ||
| 22 | 20 | ||
| 23 | namespace Loader { | 21 | namespace Loader { |
| 24 | 22 | ||
| @@ -127,12 +125,16 @@ ResultStatus AppLoader_DeconstructedRomDirectory::Load( | |||
| 127 | metadata.Print(); | 125 | metadata.Print(); |
| 128 | 126 | ||
| 129 | const FileSys::ProgramAddressSpaceType arch_bits{metadata.GetAddressSpaceType()}; | 127 | const FileSys::ProgramAddressSpaceType arch_bits{metadata.GetAddressSpaceType()}; |
| 130 | if (arch_bits == FileSys::ProgramAddressSpaceType::Is32Bit) { | 128 | if (arch_bits == FileSys::ProgramAddressSpaceType::Is32Bit || |
| 129 | arch_bits == FileSys::ProgramAddressSpaceType::Is32BitNoMap) { | ||
| 131 | return ResultStatus::Error32BitISA; | 130 | return ResultStatus::Error32BitISA; |
| 132 | } | 131 | } |
| 133 | 132 | ||
| 133 | process->LoadFromMetadata(metadata); | ||
| 134 | |||
| 134 | // Load NSO modules | 135 | // Load NSO modules |
| 135 | VAddr next_load_addr{Memory::PROCESS_IMAGE_VADDR}; | 136 | const VAddr base_address = process->vm_manager.GetCodeRegionBaseAddress(); |
| 137 | VAddr next_load_addr = base_address; | ||
| 136 | for (const auto& module : {"rtld", "main", "subsdk0", "subsdk1", "subsdk2", "subsdk3", | 138 | for (const auto& module : {"rtld", "main", "subsdk0", "subsdk1", "subsdk2", "subsdk3", |
| 137 | "subsdk4", "subsdk5", "subsdk6", "subsdk7", "sdk"}) { | 139 | "subsdk4", "subsdk5", "subsdk6", "subsdk7", "sdk"}) { |
| 138 | const FileSys::VirtualFile module_file = dir->GetFile(module); | 140 | const FileSys::VirtualFile module_file = dir->GetFile(module); |
| @@ -145,13 +147,7 @@ ResultStatus AppLoader_DeconstructedRomDirectory::Load( | |||
| 145 | } | 147 | } |
| 146 | } | 148 | } |
| 147 | 149 | ||
| 148 | auto& kernel = Core::System::GetInstance().Kernel(); | 150 | process->Run(base_address, metadata.GetMainThreadPriority(), metadata.GetMainThreadStackSize()); |
| 149 | process->program_id = metadata.GetTitleID(); | ||
| 150 | process->svc_access_mask.set(); | ||
| 151 | process->resource_limit = | ||
| 152 | kernel.ResourceLimitForCategory(Kernel::ResourceLimitCategory::APPLICATION); | ||
| 153 | process->Run(Memory::PROCESS_IMAGE_VADDR, metadata.GetMainThreadPriority(), | ||
| 154 | metadata.GetMainThreadStackSize()); | ||
| 155 | 151 | ||
| 156 | // Find the RomFS by searching for a ".romfs" file in this directory | 152 | // Find the RomFS by searching for a ".romfs" file in this directory |
| 157 | const auto& files = dir->GetFiles(); | 153 | const auto& files = dir->GetFiles(); |
diff --git a/src/core/loader/elf.cpp b/src/core/loader/elf.cpp index 0e2af20b4..ff1221574 100644 --- a/src/core/loader/elf.cpp +++ b/src/core/loader/elf.cpp | |||
| @@ -12,7 +12,7 @@ | |||
| 12 | #include "core/core.h" | 12 | #include "core/core.h" |
| 13 | #include "core/hle/kernel/kernel.h" | 13 | #include "core/hle/kernel/kernel.h" |
| 14 | #include "core/hle/kernel/process.h" | 14 | #include "core/hle/kernel/process.h" |
| 15 | #include "core/hle/kernel/resource_limit.h" | 15 | #include "core/hle/kernel/vm_manager.h" |
| 16 | #include "core/loader/elf.h" | 16 | #include "core/loader/elf.h" |
| 17 | #include "core/memory.h" | 17 | #include "core/memory.h" |
| 18 | 18 | ||
| @@ -189,7 +189,7 @@ private: | |||
| 189 | 189 | ||
| 190 | u32* sectionAddrs; | 190 | u32* sectionAddrs; |
| 191 | bool relocate; | 191 | bool relocate; |
| 192 | u32 entryPoint; | 192 | VAddr entryPoint; |
| 193 | 193 | ||
| 194 | public: | 194 | public: |
| 195 | explicit ElfReader(void* ptr); | 195 | explicit ElfReader(void* ptr); |
| @@ -205,13 +205,13 @@ public: | |||
| 205 | ElfMachine GetMachine() const { | 205 | ElfMachine GetMachine() const { |
| 206 | return (ElfMachine)(header->e_machine); | 206 | return (ElfMachine)(header->e_machine); |
| 207 | } | 207 | } |
| 208 | u32 GetEntryPoint() const { | 208 | VAddr GetEntryPoint() const { |
| 209 | return entryPoint; | 209 | return entryPoint; |
| 210 | } | 210 | } |
| 211 | u32 GetFlags() const { | 211 | u32 GetFlags() const { |
| 212 | return (u32)(header->e_flags); | 212 | return (u32)(header->e_flags); |
| 213 | } | 213 | } |
| 214 | SharedPtr<CodeSet> LoadInto(u32 vaddr); | 214 | SharedPtr<CodeSet> LoadInto(VAddr vaddr); |
| 215 | 215 | ||
| 216 | int GetNumSegments() const { | 216 | int GetNumSegments() const { |
| 217 | return (int)(header->e_phnum); | 217 | return (int)(header->e_phnum); |
| @@ -274,7 +274,7 @@ const char* ElfReader::GetSectionName(int section) const { | |||
| 274 | return nullptr; | 274 | return nullptr; |
| 275 | } | 275 | } |
| 276 | 276 | ||
| 277 | SharedPtr<CodeSet> ElfReader::LoadInto(u32 vaddr) { | 277 | SharedPtr<CodeSet> ElfReader::LoadInto(VAddr vaddr) { |
| 278 | LOG_DEBUG(Loader, "String section: {}", header->e_shstrndx); | 278 | LOG_DEBUG(Loader, "String section: {}", header->e_shstrndx); |
| 279 | 279 | ||
| 280 | // Should we relocate? | 280 | // Should we relocate? |
| @@ -289,11 +289,11 @@ SharedPtr<CodeSet> ElfReader::LoadInto(u32 vaddr) { | |||
| 289 | LOG_DEBUG(Loader, "{} segments:", header->e_phnum); | 289 | LOG_DEBUG(Loader, "{} segments:", header->e_phnum); |
| 290 | 290 | ||
| 291 | // First pass : Get the bits into RAM | 291 | // First pass : Get the bits into RAM |
| 292 | u32 base_addr = relocate ? vaddr : 0; | 292 | const VAddr base_addr = relocate ? vaddr : 0; |
| 293 | 293 | ||
| 294 | u32 total_image_size = 0; | 294 | u64 total_image_size = 0; |
| 295 | for (unsigned int i = 0; i < header->e_phnum; ++i) { | 295 | for (unsigned int i = 0; i < header->e_phnum; ++i) { |
| 296 | Elf32_Phdr* p = &segments[i]; | 296 | const Elf32_Phdr* p = &segments[i]; |
| 297 | if (p->p_type == PT_LOAD) { | 297 | if (p->p_type == PT_LOAD) { |
| 298 | total_image_size += (p->p_memsz + 0xFFF) & ~0xFFF; | 298 | total_image_size += (p->p_memsz + 0xFFF) & ~0xFFF; |
| 299 | } | 299 | } |
| @@ -306,7 +306,7 @@ SharedPtr<CodeSet> ElfReader::LoadInto(u32 vaddr) { | |||
| 306 | SharedPtr<CodeSet> codeset = CodeSet::Create(kernel, ""); | 306 | SharedPtr<CodeSet> codeset = CodeSet::Create(kernel, ""); |
| 307 | 307 | ||
| 308 | for (unsigned int i = 0; i < header->e_phnum; ++i) { | 308 | for (unsigned int i = 0; i < header->e_phnum; ++i) { |
| 309 | Elf32_Phdr* p = &segments[i]; | 309 | const Elf32_Phdr* p = &segments[i]; |
| 310 | LOG_DEBUG(Loader, "Type: {} Vaddr: {:08X} Filesz: {:08X} Memsz: {:08X} ", p->p_type, | 310 | LOG_DEBUG(Loader, "Type: {} Vaddr: {:08X} Filesz: {:08X} Memsz: {:08X} ", p->p_type, |
| 311 | p->p_vaddr, p->p_filesz, p->p_memsz); | 311 | p->p_vaddr, p->p_filesz, p->p_memsz); |
| 312 | 312 | ||
| @@ -333,8 +333,8 @@ SharedPtr<CodeSet> ElfReader::LoadInto(u32 vaddr) { | |||
| 333 | continue; | 333 | continue; |
| 334 | } | 334 | } |
| 335 | 335 | ||
| 336 | u32 segment_addr = base_addr + p->p_vaddr; | 336 | const VAddr segment_addr = base_addr + p->p_vaddr; |
| 337 | u32 aligned_size = (p->p_memsz + 0xFFF) & ~0xFFF; | 337 | const u32 aligned_size = (p->p_memsz + 0xFFF) & ~0xFFF; |
| 338 | 338 | ||
| 339 | codeset_segment->offset = current_image_position; | 339 | codeset_segment->offset = current_image_position; |
| 340 | codeset_segment->addr = segment_addr; | 340 | codeset_segment->addr = segment_addr; |
| @@ -395,18 +395,12 @@ ResultStatus AppLoader_ELF::Load(Kernel::SharedPtr<Kernel::Process>& process) { | |||
| 395 | if (buffer.size() != file->GetSize()) | 395 | if (buffer.size() != file->GetSize()) |
| 396 | return ResultStatus::ErrorIncorrectELFFileSize; | 396 | return ResultStatus::ErrorIncorrectELFFileSize; |
| 397 | 397 | ||
| 398 | const VAddr base_address = process->vm_manager.GetCodeRegionBaseAddress(); | ||
| 398 | ElfReader elf_reader(&buffer[0]); | 399 | ElfReader elf_reader(&buffer[0]); |
| 399 | SharedPtr<CodeSet> codeset = elf_reader.LoadInto(Memory::PROCESS_IMAGE_VADDR); | 400 | SharedPtr<CodeSet> codeset = elf_reader.LoadInto(base_address); |
| 400 | codeset->name = file->GetName(); | 401 | codeset->name = file->GetName(); |
| 401 | 402 | ||
| 402 | process->LoadModule(codeset, codeset->entrypoint); | 403 | process->LoadModule(codeset, codeset->entrypoint); |
| 403 | process->svc_access_mask.set(); | ||
| 404 | |||
| 405 | // Attach the default resource limit (APPLICATION) to the process | ||
| 406 | auto& kernel = Core::System::GetInstance().Kernel(); | ||
| 407 | process->resource_limit = | ||
| 408 | kernel.ResourceLimitForCategory(Kernel::ResourceLimitCategory::APPLICATION); | ||
| 409 | |||
| 410 | process->Run(codeset->entrypoint, 48, Memory::DEFAULT_STACK_SIZE); | 404 | process->Run(codeset->entrypoint, 48, Memory::DEFAULT_STACK_SIZE); |
| 411 | 405 | ||
| 412 | is_loaded = true; | 406 | is_loaded = true; |
diff --git a/src/core/loader/nro.cpp b/src/core/loader/nro.cpp index c49ec34ab..b72871efa 100644 --- a/src/core/loader/nro.cpp +++ b/src/core/loader/nro.cpp | |||
| @@ -16,7 +16,7 @@ | |||
| 16 | #include "core/gdbstub/gdbstub.h" | 16 | #include "core/gdbstub/gdbstub.h" |
| 17 | #include "core/hle/kernel/kernel.h" | 17 | #include "core/hle/kernel/kernel.h" |
| 18 | #include "core/hle/kernel/process.h" | 18 | #include "core/hle/kernel/process.h" |
| 19 | #include "core/hle/kernel/resource_limit.h" | 19 | #include "core/hle/kernel/vm_manager.h" |
| 20 | #include "core/loader/nro.h" | 20 | #include "core/loader/nro.h" |
| 21 | #include "core/memory.h" | 21 | #include "core/memory.h" |
| 22 | 22 | ||
| @@ -181,17 +181,13 @@ ResultStatus AppLoader_NRO::Load(Kernel::SharedPtr<Kernel::Process>& process) { | |||
| 181 | } | 181 | } |
| 182 | 182 | ||
| 183 | // Load NRO | 183 | // Load NRO |
| 184 | static constexpr VAddr base_addr{Memory::PROCESS_IMAGE_VADDR}; | 184 | const VAddr base_address = process->vm_manager.GetCodeRegionBaseAddress(); |
| 185 | 185 | ||
| 186 | if (!LoadNro(file, base_addr)) { | 186 | if (!LoadNro(file, base_address)) { |
| 187 | return ResultStatus::ErrorLoadingNRO; | 187 | return ResultStatus::ErrorLoadingNRO; |
| 188 | } | 188 | } |
| 189 | 189 | ||
| 190 | auto& kernel = Core::System::GetInstance().Kernel(); | 190 | process->Run(base_address, Kernel::THREADPRIO_DEFAULT, Memory::DEFAULT_STACK_SIZE); |
| 191 | process->svc_access_mask.set(); | ||
| 192 | process->resource_limit = | ||
| 193 | kernel.ResourceLimitForCategory(Kernel::ResourceLimitCategory::APPLICATION); | ||
| 194 | process->Run(base_addr, Kernel::THREADPRIO_DEFAULT, Memory::DEFAULT_STACK_SIZE); | ||
| 195 | 191 | ||
| 196 | is_loaded = true; | 192 | is_loaded = true; |
| 197 | return ResultStatus::Success; | 193 | return ResultStatus::Success; |
diff --git a/src/core/loader/nso.cpp b/src/core/loader/nso.cpp index 78a4438c4..1a6876a22 100644 --- a/src/core/loader/nso.cpp +++ b/src/core/loader/nso.cpp | |||
| @@ -13,7 +13,7 @@ | |||
| 13 | #include "core/gdbstub/gdbstub.h" | 13 | #include "core/gdbstub/gdbstub.h" |
| 14 | #include "core/hle/kernel/kernel.h" | 14 | #include "core/hle/kernel/kernel.h" |
| 15 | #include "core/hle/kernel/process.h" | 15 | #include "core/hle/kernel/process.h" |
| 16 | #include "core/hle/kernel/resource_limit.h" | 16 | #include "core/hle/kernel/vm_manager.h" |
| 17 | #include "core/loader/nso.h" | 17 | #include "core/loader/nso.h" |
| 18 | #include "core/memory.h" | 18 | #include "core/memory.h" |
| 19 | 19 | ||
| @@ -159,15 +159,11 @@ ResultStatus AppLoader_NSO::Load(Kernel::SharedPtr<Kernel::Process>& process) { | |||
| 159 | } | 159 | } |
| 160 | 160 | ||
| 161 | // Load module | 161 | // Load module |
| 162 | LoadModule(file, Memory::PROCESS_IMAGE_VADDR); | 162 | const VAddr base_address = process->vm_manager.GetCodeRegionBaseAddress(); |
| 163 | LOG_DEBUG(Loader, "loaded module {} @ 0x{:X}", file->GetName(), Memory::PROCESS_IMAGE_VADDR); | 163 | LoadModule(file, base_address); |
| 164 | LOG_DEBUG(Loader, "loaded module {} @ 0x{:X}", file->GetName(), base_address); | ||
| 164 | 165 | ||
| 165 | auto& kernel = Core::System::GetInstance().Kernel(); | 166 | process->Run(base_address, Kernel::THREADPRIO_DEFAULT, Memory::DEFAULT_STACK_SIZE); |
| 166 | process->svc_access_mask.set(); | ||
| 167 | process->resource_limit = | ||
| 168 | kernel.ResourceLimitForCategory(Kernel::ResourceLimitCategory::APPLICATION); | ||
| 169 | process->Run(Memory::PROCESS_IMAGE_VADDR, Kernel::THREADPRIO_DEFAULT, | ||
| 170 | Memory::DEFAULT_STACK_SIZE); | ||
| 171 | 167 | ||
| 172 | is_loaded = true; | 168 | is_loaded = true; |
| 173 | return ResultStatus::Success; | 169 | return ResultStatus::Success; |
diff --git a/src/core/memory.cpp b/src/core/memory.cpp index 316b46820..6430daad4 100644 --- a/src/core/memory.cpp +++ b/src/core/memory.cpp | |||
| @@ -3,7 +3,6 @@ | |||
| 3 | // Refer to the license.txt file included. | 3 | // Refer to the license.txt file included. |
| 4 | 4 | ||
| 5 | #include <algorithm> | 5 | #include <algorithm> |
| 6 | #include <array> | ||
| 7 | #include <cstring> | 6 | #include <cstring> |
| 8 | #include <utility> | 7 | #include <utility> |
| 9 | 8 | ||
| @@ -15,11 +14,11 @@ | |||
| 15 | #include "core/arm/arm_interface.h" | 14 | #include "core/arm/arm_interface.h" |
| 16 | #include "core/core.h" | 15 | #include "core/core.h" |
| 17 | #include "core/hle/kernel/process.h" | 16 | #include "core/hle/kernel/process.h" |
| 17 | #include "core/hle/kernel/vm_manager.h" | ||
| 18 | #include "core/hle/lock.h" | 18 | #include "core/hle/lock.h" |
| 19 | #include "core/memory.h" | 19 | #include "core/memory.h" |
| 20 | #include "core/memory_setup.h" | 20 | #include "core/memory_setup.h" |
| 21 | #include "video_core/renderer_base.h" | 21 | #include "video_core/renderer_base.h" |
| 22 | #include "video_core/video_core.h" | ||
| 23 | 22 | ||
| 24 | namespace Memory { | 23 | namespace Memory { |
| 25 | 24 | ||
| @@ -41,6 +40,21 @@ PageTable* GetCurrentPageTable() { | |||
| 41 | return current_page_table; | 40 | return current_page_table; |
| 42 | } | 41 | } |
| 43 | 42 | ||
| 43 | PageTable::PageTable() = default; | ||
| 44 | |||
| 45 | PageTable::PageTable(std::size_t address_space_width_in_bits) { | ||
| 46 | Resize(address_space_width_in_bits); | ||
| 47 | } | ||
| 48 | |||
| 49 | PageTable::~PageTable() = default; | ||
| 50 | |||
| 51 | void PageTable::Resize(std::size_t address_space_width_in_bits) { | ||
| 52 | const std::size_t num_page_table_entries = 1ULL << (address_space_width_in_bits - PAGE_BITS); | ||
| 53 | |||
| 54 | pointers.resize(num_page_table_entries); | ||
| 55 | attributes.resize(num_page_table_entries); | ||
| 56 | } | ||
| 57 | |||
| 44 | static void MapPages(PageTable& page_table, VAddr base, u64 size, u8* memory, PageType type) { | 58 | static void MapPages(PageTable& page_table, VAddr base, u64 size, u8* memory, PageType type) { |
| 45 | LOG_DEBUG(HW_Memory, "Mapping {} onto {:016X}-{:016X}", fmt::ptr(memory), base * PAGE_SIZE, | 59 | LOG_DEBUG(HW_Memory, "Mapping {} onto {:016X}-{:016X}", fmt::ptr(memory), base * PAGE_SIZE, |
| 46 | (base + size) * PAGE_SIZE); | 60 | (base + size) * PAGE_SIZE); |
| @@ -50,7 +64,7 @@ static void MapPages(PageTable& page_table, VAddr base, u64 size, u8* memory, Pa | |||
| 50 | 64 | ||
| 51 | VAddr end = base + size; | 65 | VAddr end = base + size; |
| 52 | while (base != end) { | 66 | while (base != end) { |
| 53 | ASSERT_MSG(base < PAGE_TABLE_NUM_ENTRIES, "out of range mapping at {:016X}", base); | 67 | ASSERT_MSG(base < page_table.pointers.size(), "out of range mapping at {:016X}", base); |
| 54 | 68 | ||
| 55 | page_table.attributes[base] = type; | 69 | page_table.attributes[base] = type; |
| 56 | page_table.pointers[base] = memory; | 70 | page_table.pointers[base] = memory; |
| @@ -323,7 +337,7 @@ void RasterizerFlushVirtualRegion(VAddr start, u64 size, FlushMode mode) { | |||
| 323 | return; | 337 | return; |
| 324 | } | 338 | } |
| 325 | 339 | ||
| 326 | VAddr end = start + size; | 340 | const VAddr end = start + size; |
| 327 | 341 | ||
| 328 | const auto CheckRegion = [&](VAddr region_start, VAddr region_end) { | 342 | const auto CheckRegion = [&](VAddr region_start, VAddr region_end) { |
| 329 | if (start >= region_end || end <= region_start) { | 343 | if (start >= region_end || end <= region_start) { |
| @@ -333,7 +347,7 @@ void RasterizerFlushVirtualRegion(VAddr start, u64 size, FlushMode mode) { | |||
| 333 | 347 | ||
| 334 | const VAddr overlap_start = std::max(start, region_start); | 348 | const VAddr overlap_start = std::max(start, region_start); |
| 335 | const VAddr overlap_end = std::min(end, region_end); | 349 | const VAddr overlap_end = std::min(end, region_end); |
| 336 | const u64 overlap_size = overlap_end - overlap_start; | 350 | const VAddr overlap_size = overlap_end - overlap_start; |
| 337 | 351 | ||
| 338 | auto& rasterizer = system_instance.Renderer().Rasterizer(); | 352 | auto& rasterizer = system_instance.Renderer().Rasterizer(); |
| 339 | switch (mode) { | 353 | switch (mode) { |
| @@ -349,8 +363,10 @@ void RasterizerFlushVirtualRegion(VAddr start, u64 size, FlushMode mode) { | |||
| 349 | } | 363 | } |
| 350 | }; | 364 | }; |
| 351 | 365 | ||
| 352 | CheckRegion(PROCESS_IMAGE_VADDR, PROCESS_IMAGE_VADDR_END); | 366 | const auto& vm_manager = Core::CurrentProcess()->vm_manager; |
| 353 | CheckRegion(HEAP_VADDR, HEAP_VADDR_END); | 367 | |
| 368 | CheckRegion(vm_manager.GetCodeRegionBaseAddress(), vm_manager.GetCodeRegionEndAddress()); | ||
| 369 | CheckRegion(vm_manager.GetHeapRegionBaseAddress(), vm_manager.GetHeapRegionEndAddress()); | ||
| 354 | } | 370 | } |
| 355 | 371 | ||
| 356 | u8 Read8(const VAddr addr) { | 372 | u8 Read8(const VAddr addr) { |
diff --git a/src/core/memory.h b/src/core/memory.h index 2a27c0251..1acf5ce8c 100644 --- a/src/core/memory.h +++ b/src/core/memory.h | |||
| @@ -4,10 +4,10 @@ | |||
| 4 | 4 | ||
| 5 | #pragma once | 5 | #pragma once |
| 6 | 6 | ||
| 7 | #include <array> | ||
| 8 | #include <cstddef> | 7 | #include <cstddef> |
| 9 | #include <string> | 8 | #include <string> |
| 10 | #include <tuple> | 9 | #include <tuple> |
| 10 | #include <vector> | ||
| 11 | #include <boost/icl/interval_map.hpp> | 11 | #include <boost/icl/interval_map.hpp> |
| 12 | #include "common/common_types.h" | 12 | #include "common/common_types.h" |
| 13 | #include "core/memory_hook.h" | 13 | #include "core/memory_hook.h" |
| @@ -23,10 +23,8 @@ namespace Memory { | |||
| 23 | * be mapped. | 23 | * be mapped. |
| 24 | */ | 24 | */ |
| 25 | constexpr std::size_t PAGE_BITS = 12; | 25 | constexpr std::size_t PAGE_BITS = 12; |
| 26 | constexpr u64 PAGE_SIZE = 1 << PAGE_BITS; | 26 | constexpr u64 PAGE_SIZE = 1ULL << PAGE_BITS; |
| 27 | constexpr u64 PAGE_MASK = PAGE_SIZE - 1; | 27 | constexpr u64 PAGE_MASK = PAGE_SIZE - 1; |
| 28 | constexpr std::size_t ADDRESS_SPACE_BITS = 36; | ||
| 29 | constexpr std::size_t PAGE_TABLE_NUM_ENTRIES = 1ULL << (ADDRESS_SPACE_BITS - PAGE_BITS); | ||
| 30 | 28 | ||
| 31 | enum class PageType : u8 { | 29 | enum class PageType : u8 { |
| 32 | /// Page is unmapped and should cause an access error. | 30 | /// Page is unmapped and should cause an access error. |
| @@ -62,32 +60,39 @@ struct SpecialRegion { | |||
| 62 | * mimics the way a real CPU page table works. | 60 | * mimics the way a real CPU page table works. |
| 63 | */ | 61 | */ |
| 64 | struct PageTable { | 62 | struct PageTable { |
| 63 | explicit PageTable(); | ||
| 64 | explicit PageTable(std::size_t address_space_width_in_bits); | ||
| 65 | ~PageTable(); | ||
| 66 | |||
| 67 | /** | ||
| 68 | * Resizes the page table to be able to accomodate enough pages within | ||
| 69 | * a given address space. | ||
| 70 | * | ||
| 71 | * @param address_space_width_in_bits The address size width in bits. | ||
| 72 | */ | ||
| 73 | void Resize(std::size_t address_space_width_in_bits); | ||
| 74 | |||
| 65 | /** | 75 | /** |
| 66 | * Array of memory pointers backing each page. An entry can only be non-null if the | 76 | * Vector of memory pointers backing each page. An entry can only be non-null if the |
| 67 | * corresponding entry in the `attributes` array is of type `Memory`. | 77 | * corresponding entry in the `attributes` vector is of type `Memory`. |
| 68 | */ | 78 | */ |
| 69 | std::array<u8*, PAGE_TABLE_NUM_ENTRIES> pointers; | 79 | std::vector<u8*> pointers; |
| 70 | 80 | ||
| 71 | /** | 81 | /** |
| 72 | * Contains MMIO handlers that back memory regions whose entries in the `attribute` array is of | 82 | * Contains MMIO handlers that back memory regions whose entries in the `attribute` vector is |
| 73 | * type `Special`. | 83 | * of type `Special`. |
| 74 | */ | 84 | */ |
| 75 | boost::icl::interval_map<VAddr, std::set<SpecialRegion>> special_regions; | 85 | boost::icl::interval_map<VAddr, std::set<SpecialRegion>> special_regions; |
| 76 | 86 | ||
| 77 | /** | 87 | /** |
| 78 | * Array of fine grained page attributes. If it is set to any value other than `Memory`, then | 88 | * Vector of fine grained page attributes. If it is set to any value other than `Memory`, then |
| 79 | * the corresponding entry in `pointers` MUST be set to null. | 89 | * the corresponding entry in `pointers` MUST be set to null. |
| 80 | */ | 90 | */ |
| 81 | std::array<PageType, PAGE_TABLE_NUM_ENTRIES> attributes; | 91 | std::vector<PageType> attributes; |
| 82 | }; | 92 | }; |
| 83 | 93 | ||
| 84 | /// Virtual user-space memory regions | 94 | /// Virtual user-space memory regions |
| 85 | enum : VAddr { | 95 | enum : VAddr { |
| 86 | /// Where the application text, data and bss reside. | ||
| 87 | PROCESS_IMAGE_VADDR = 0x08000000, | ||
| 88 | PROCESS_IMAGE_MAX_SIZE = 0x08000000, | ||
| 89 | PROCESS_IMAGE_VADDR_END = PROCESS_IMAGE_VADDR + PROCESS_IMAGE_MAX_SIZE, | ||
| 90 | |||
| 91 | /// Read-only page containing kernel and system configuration values. | 96 | /// Read-only page containing kernel and system configuration values. |
| 92 | CONFIG_MEMORY_VADDR = 0x1FF80000, | 97 | CONFIG_MEMORY_VADDR = 0x1FF80000, |
| 93 | CONFIG_MEMORY_SIZE = 0x00001000, | 98 | CONFIG_MEMORY_SIZE = 0x00001000, |
| @@ -98,36 +103,12 @@ enum : VAddr { | |||
| 98 | SHARED_PAGE_SIZE = 0x00001000, | 103 | SHARED_PAGE_SIZE = 0x00001000, |
| 99 | SHARED_PAGE_VADDR_END = SHARED_PAGE_VADDR + SHARED_PAGE_SIZE, | 104 | SHARED_PAGE_VADDR_END = SHARED_PAGE_VADDR + SHARED_PAGE_SIZE, |
| 100 | 105 | ||
| 101 | /// Area where TLS (Thread-Local Storage) buffers are allocated. | 106 | /// TLS (Thread-Local Storage) related. |
| 102 | TLS_AREA_VADDR = 0x40000000, | ||
| 103 | TLS_ENTRY_SIZE = 0x200, | 107 | TLS_ENTRY_SIZE = 0x200, |
| 104 | TLS_AREA_SIZE = 0x10000000, | ||
| 105 | TLS_AREA_VADDR_END = TLS_AREA_VADDR + TLS_AREA_SIZE, | ||
| 106 | 108 | ||
| 107 | /// Application stack | 109 | /// Application stack |
| 108 | STACK_AREA_VADDR = TLS_AREA_VADDR_END, | ||
| 109 | STACK_AREA_SIZE = 0x10000000, | ||
| 110 | STACK_AREA_VADDR_END = STACK_AREA_VADDR + STACK_AREA_SIZE, | ||
| 111 | DEFAULT_STACK_SIZE = 0x100000, | 110 | DEFAULT_STACK_SIZE = 0x100000, |
| 112 | 111 | ||
| 113 | /// Application heap | ||
| 114 | /// Size is confirmed to be a static value on fw 3.0.0 | ||
| 115 | HEAP_VADDR = 0x108000000, | ||
| 116 | HEAP_SIZE = 0x180000000, | ||
| 117 | HEAP_VADDR_END = HEAP_VADDR + HEAP_SIZE, | ||
| 118 | |||
| 119 | /// New map region | ||
| 120 | /// Size is confirmed to be a static value on fw 3.0.0 | ||
| 121 | NEW_MAP_REGION_VADDR = HEAP_VADDR_END, | ||
| 122 | NEW_MAP_REGION_SIZE = 0x80000000, | ||
| 123 | NEW_MAP_REGION_VADDR_END = NEW_MAP_REGION_VADDR + NEW_MAP_REGION_SIZE, | ||
| 124 | |||
| 125 | /// Map region | ||
| 126 | /// Size is confirmed to be a static value on fw 3.0.0 | ||
| 127 | MAP_REGION_VADDR = NEW_MAP_REGION_VADDR_END, | ||
| 128 | MAP_REGION_SIZE = 0x1000000000, | ||
| 129 | MAP_REGION_VADDR_END = MAP_REGION_VADDR + MAP_REGION_SIZE, | ||
| 130 | |||
| 131 | /// Kernel Virtual Address Range | 112 | /// Kernel Virtual Address Range |
| 132 | KERNEL_REGION_VADDR = 0xFFFFFF8000000000, | 113 | KERNEL_REGION_VADDR = 0xFFFFFF8000000000, |
| 133 | KERNEL_REGION_SIZE = 0x7FFFE00000, | 114 | KERNEL_REGION_SIZE = 0x7FFFE00000, |
diff --git a/src/tests/core/arm/arm_test_common.cpp b/src/tests/core/arm/arm_test_common.cpp index 7c69fc26e..c17a122cd 100644 --- a/src/tests/core/arm/arm_test_common.cpp +++ b/src/tests/core/arm/arm_test_common.cpp | |||
| @@ -2,6 +2,8 @@ | |||
| 2 | // Licensed under GPLv2 or any later version | 2 | // Licensed under GPLv2 or any later version |
| 3 | // Refer to the license.txt file included. | 3 | // Refer to the license.txt file included. |
| 4 | 4 | ||
| 5 | #include <algorithm> | ||
| 6 | |||
| 5 | #include "core/core.h" | 7 | #include "core/core.h" |
| 6 | #include "core/hle/kernel/process.h" | 8 | #include "core/hle/kernel/process.h" |
| 7 | #include "core/memory.h" | 9 | #include "core/memory.h" |
| @@ -16,9 +18,10 @@ TestEnvironment::TestEnvironment(bool mutable_memory_) | |||
| 16 | Core::CurrentProcess() = Kernel::Process::Create(kernel, ""); | 18 | Core::CurrentProcess() = Kernel::Process::Create(kernel, ""); |
| 17 | page_table = &Core::CurrentProcess()->vm_manager.page_table; | 19 | page_table = &Core::CurrentProcess()->vm_manager.page_table; |
| 18 | 20 | ||
| 19 | page_table->pointers.fill(nullptr); | 21 | std::fill(page_table->pointers.begin(), page_table->pointers.end(), nullptr); |
| 20 | page_table->special_regions.clear(); | 22 | page_table->special_regions.clear(); |
| 21 | page_table->attributes.fill(Memory::PageType::Unmapped); | 23 | std::fill(page_table->attributes.begin(), page_table->attributes.end(), |
| 24 | Memory::PageType::Unmapped); | ||
| 22 | 25 | ||
| 23 | Memory::MapIoRegion(*page_table, 0x00000000, 0x80000000, test_memory); | 26 | Memory::MapIoRegion(*page_table, 0x00000000, 0x80000000, test_memory); |
| 24 | Memory::MapIoRegion(*page_table, 0x80000000, 0x80000000, test_memory); | 27 | Memory::MapIoRegion(*page_table, 0x80000000, 0x80000000, test_memory); |
diff --git a/src/video_core/engines/maxwell_3d.h b/src/video_core/engines/maxwell_3d.h index 16cdfc7e2..9f5581045 100644 --- a/src/video_core/engines/maxwell_3d.h +++ b/src/video_core/engines/maxwell_3d.h | |||
| @@ -41,6 +41,7 @@ public: | |||
| 41 | static constexpr std::size_t NumCBData = 16; | 41 | static constexpr std::size_t NumCBData = 16; |
| 42 | static constexpr std::size_t NumVertexArrays = 32; | 42 | static constexpr std::size_t NumVertexArrays = 32; |
| 43 | static constexpr std::size_t NumVertexAttributes = 32; | 43 | static constexpr std::size_t NumVertexAttributes = 32; |
| 44 | static constexpr std::size_t NumTextureSamplers = 32; | ||
| 44 | static constexpr std::size_t MaxShaderProgram = 6; | 45 | static constexpr std::size_t MaxShaderProgram = 6; |
| 45 | static constexpr std::size_t MaxShaderStage = 5; | 46 | static constexpr std::size_t MaxShaderStage = 5; |
| 46 | // Maximum number of const buffers per shader stage. | 47 | // Maximum number of const buffers per shader stage. |
| @@ -641,7 +642,11 @@ public: | |||
| 641 | 642 | ||
| 642 | u32 vb_element_base; | 643 | u32 vb_element_base; |
| 643 | 644 | ||
| 644 | INSERT_PADDING_WORDS(0x40); | 645 | INSERT_PADDING_WORDS(0x38); |
| 646 | |||
| 647 | float point_size; | ||
| 648 | |||
| 649 | INSERT_PADDING_WORDS(0x7); | ||
| 645 | 650 | ||
| 646 | u32 zeta_enable; | 651 | u32 zeta_enable; |
| 647 | 652 | ||
| @@ -1017,6 +1022,7 @@ ASSERT_REG_POSITION(stencil_front_func_mask, 0x4E6); | |||
| 1017 | ASSERT_REG_POSITION(stencil_front_mask, 0x4E7); | 1022 | ASSERT_REG_POSITION(stencil_front_mask, 0x4E7); |
| 1018 | ASSERT_REG_POSITION(screen_y_control, 0x4EB); | 1023 | ASSERT_REG_POSITION(screen_y_control, 0x4EB); |
| 1019 | ASSERT_REG_POSITION(vb_element_base, 0x50D); | 1024 | ASSERT_REG_POSITION(vb_element_base, 0x50D); |
| 1025 | ASSERT_REG_POSITION(point_size, 0x546); | ||
| 1020 | ASSERT_REG_POSITION(zeta_enable, 0x54E); | 1026 | ASSERT_REG_POSITION(zeta_enable, 0x54E); |
| 1021 | ASSERT_REG_POSITION(tsc, 0x557); | 1027 | ASSERT_REG_POSITION(tsc, 0x557); |
| 1022 | ASSERT_REG_POSITION(tic, 0x55D); | 1028 | ASSERT_REG_POSITION(tic, 0x55D); |
diff --git a/src/video_core/renderer_opengl/gl_rasterizer.cpp b/src/video_core/renderer_opengl/gl_rasterizer.cpp index 44850d193..1fcd13f04 100644 --- a/src/video_core/renderer_opengl/gl_rasterizer.cpp +++ b/src/video_core/renderer_opengl/gl_rasterizer.cpp | |||
| @@ -452,6 +452,7 @@ void RasterizerOpenGL::DrawArrays() { | |||
| 452 | SyncCullMode(); | 452 | SyncCullMode(); |
| 453 | SyncAlphaTest(); | 453 | SyncAlphaTest(); |
| 454 | SyncTransformFeedback(); | 454 | SyncTransformFeedback(); |
| 455 | SyncPointState(); | ||
| 455 | 456 | ||
| 456 | // TODO(bunnei): Sync framebuffer_scale uniform here | 457 | // TODO(bunnei): Sync framebuffer_scale uniform here |
| 457 | // TODO(bunnei): Sync scissorbox uniform(s) here | 458 | // TODO(bunnei): Sync scissorbox uniform(s) here |
| @@ -905,4 +906,10 @@ void RasterizerOpenGL::SyncTransformFeedback() { | |||
| 905 | } | 906 | } |
| 906 | } | 907 | } |
| 907 | 908 | ||
| 909 | void RasterizerOpenGL::SyncPointState() { | ||
| 910 | const auto& regs = Core::System::GetInstance().GPU().Maxwell3D().regs; | ||
| 911 | |||
| 912 | state.point.size = regs.point_size; | ||
| 913 | } | ||
| 914 | |||
| 908 | } // namespace OpenGL | 915 | } // namespace OpenGL |
diff --git a/src/video_core/renderer_opengl/gl_rasterizer.h b/src/video_core/renderer_opengl/gl_rasterizer.h index c3f1e14bf..4c8ecbd1c 100644 --- a/src/video_core/renderer_opengl/gl_rasterizer.h +++ b/src/video_core/renderer_opengl/gl_rasterizer.h | |||
| @@ -164,6 +164,9 @@ private: | |||
| 164 | /// Syncs the transform feedback state to match the guest state | 164 | /// Syncs the transform feedback state to match the guest state |
| 165 | void SyncTransformFeedback(); | 165 | void SyncTransformFeedback(); |
| 166 | 166 | ||
| 167 | /// Syncs the point state to match the guest state | ||
| 168 | void SyncPointState(); | ||
| 169 | |||
| 167 | bool has_ARB_direct_state_access = false; | 170 | bool has_ARB_direct_state_access = false; |
| 168 | bool has_ARB_multi_bind = false; | 171 | bool has_ARB_multi_bind = false; |
| 169 | bool has_ARB_separate_shader_objects = false; | 172 | bool has_ARB_separate_shader_objects = false; |
| @@ -184,7 +187,7 @@ private: | |||
| 184 | OGLVertexArray> | 187 | OGLVertexArray> |
| 185 | vertex_array_cache; | 188 | vertex_array_cache; |
| 186 | 189 | ||
| 187 | std::array<SamplerInfo, GLShader::NumTextureSamplers> texture_samplers; | 190 | std::array<SamplerInfo, Tegra::Engines::Maxwell3D::Regs::NumTextureSamplers> texture_samplers; |
| 188 | 191 | ||
| 189 | static constexpr std::size_t STREAM_BUFFER_SIZE = 128 * 1024 * 1024; | 192 | static constexpr std::size_t STREAM_BUFFER_SIZE = 128 * 1024 * 1024; |
| 190 | OGLBufferCache buffer_cache; | 193 | OGLBufferCache buffer_cache; |
diff --git a/src/video_core/renderer_opengl/gl_shader_manager.h b/src/video_core/renderer_opengl/gl_shader_manager.h index b86cd96e8..3de15ba9b 100644 --- a/src/video_core/renderer_opengl/gl_shader_manager.h +++ b/src/video_core/renderer_opengl/gl_shader_manager.h | |||
| @@ -11,9 +11,6 @@ | |||
| 11 | 11 | ||
| 12 | namespace OpenGL::GLShader { | 12 | namespace OpenGL::GLShader { |
| 13 | 13 | ||
| 14 | /// Number of OpenGL texture samplers that can be used in the fragment shader | ||
| 15 | static constexpr std::size_t NumTextureSamplers = 32; | ||
| 16 | |||
| 17 | using Tegra::Engines::Maxwell3D; | 14 | using Tegra::Engines::Maxwell3D; |
| 18 | 15 | ||
| 19 | /// Uniform structure for the Uniform Buffer Object, all vectors must be 16-byte aligned | 16 | /// Uniform structure for the Uniform Buffer Object, all vectors must be 16-byte aligned |
diff --git a/src/video_core/renderer_opengl/gl_state.cpp b/src/video_core/renderer_opengl/gl_state.cpp index e5173e20a..1fe26a2a9 100644 --- a/src/video_core/renderer_opengl/gl_state.cpp +++ b/src/video_core/renderer_opengl/gl_state.cpp | |||
| @@ -79,6 +79,8 @@ OpenGLState::OpenGLState() { | |||
| 79 | viewport.height = 0; | 79 | viewport.height = 0; |
| 80 | 80 | ||
| 81 | clip_distance = {}; | 81 | clip_distance = {}; |
| 82 | |||
| 83 | point.size = 1; | ||
| 82 | } | 84 | } |
| 83 | 85 | ||
| 84 | void OpenGLState::Apply() const { | 86 | void OpenGLState::Apply() const { |
| @@ -205,9 +207,6 @@ void OpenGLState::Apply() const { | |||
| 205 | glActiveTexture(TextureUnits::MaxwellTexture(static_cast<int>(i)).Enum()); | 207 | glActiveTexture(TextureUnits::MaxwellTexture(static_cast<int>(i)).Enum()); |
| 206 | glBindTexture(texture_unit.target, texture_unit.texture); | 208 | glBindTexture(texture_unit.target, texture_unit.texture); |
| 207 | } | 209 | } |
| 208 | if (texture_unit.sampler != cur_state_texture_unit.sampler) { | ||
| 209 | glBindSampler(static_cast<GLuint>(i), texture_unit.sampler); | ||
| 210 | } | ||
| 211 | // Update the texture swizzle | 210 | // Update the texture swizzle |
| 212 | if (texture_unit.swizzle.r != cur_state_texture_unit.swizzle.r || | 211 | if (texture_unit.swizzle.r != cur_state_texture_unit.swizzle.r || |
| 213 | texture_unit.swizzle.g != cur_state_texture_unit.swizzle.g || | 212 | texture_unit.swizzle.g != cur_state_texture_unit.swizzle.g || |
| @@ -219,6 +218,27 @@ void OpenGLState::Apply() const { | |||
| 219 | } | 218 | } |
| 220 | } | 219 | } |
| 221 | 220 | ||
| 221 | // Samplers | ||
| 222 | { | ||
| 223 | bool has_delta{}; | ||
| 224 | std::size_t first{}, last{}; | ||
| 225 | std::array<GLuint, Tegra::Engines::Maxwell3D::Regs::NumTextureSamplers> samplers; | ||
| 226 | for (std::size_t i = 0; i < std::size(samplers); ++i) { | ||
| 227 | samplers[i] = texture_units[i].sampler; | ||
| 228 | if (samplers[i] != cur_state.texture_units[i].sampler) { | ||
| 229 | if (!has_delta) { | ||
| 230 | first = i; | ||
| 231 | has_delta = true; | ||
| 232 | } | ||
| 233 | last = i; | ||
| 234 | } | ||
| 235 | } | ||
| 236 | if (has_delta) { | ||
| 237 | glBindSamplers(static_cast<GLuint>(first), static_cast<GLsizei>(last - first + 1), | ||
| 238 | samplers.data()); | ||
| 239 | } | ||
| 240 | } | ||
| 241 | |||
| 222 | // Framebuffer | 242 | // Framebuffer |
| 223 | if (draw.read_framebuffer != cur_state.draw.read_framebuffer) { | 243 | if (draw.read_framebuffer != cur_state.draw.read_framebuffer) { |
| 224 | glBindFramebuffer(GL_READ_FRAMEBUFFER, draw.read_framebuffer); | 244 | glBindFramebuffer(GL_READ_FRAMEBUFFER, draw.read_framebuffer); |
| @@ -283,6 +303,11 @@ void OpenGLState::Apply() const { | |||
| 283 | } | 303 | } |
| 284 | } | 304 | } |
| 285 | 305 | ||
| 306 | // Point | ||
| 307 | if (point.size != cur_state.point.size) { | ||
| 308 | glPointSize(point.size); | ||
| 309 | } | ||
| 310 | |||
| 286 | cur_state = *this; | 311 | cur_state = *this; |
| 287 | } | 312 | } |
| 288 | 313 | ||
diff --git a/src/video_core/renderer_opengl/gl_state.h b/src/video_core/renderer_opengl/gl_state.h index 9a93029d8..dc21a2ee3 100644 --- a/src/video_core/renderer_opengl/gl_state.h +++ b/src/video_core/renderer_opengl/gl_state.h | |||
| @@ -6,6 +6,7 @@ | |||
| 6 | 6 | ||
| 7 | #include <array> | 7 | #include <array> |
| 8 | #include <glad/glad.h> | 8 | #include <glad/glad.h> |
| 9 | #include "video_core/engines/maxwell_3d.h" | ||
| 9 | 10 | ||
| 10 | namespace OpenGL { | 11 | namespace OpenGL { |
| 11 | 12 | ||
| @@ -114,7 +115,7 @@ public: | |||
| 114 | target = GL_TEXTURE_2D; | 115 | target = GL_TEXTURE_2D; |
| 115 | } | 116 | } |
| 116 | }; | 117 | }; |
| 117 | std::array<TextureUnit, 32> texture_units; | 118 | std::array<TextureUnit, Tegra::Engines::Maxwell3D::Regs::NumTextureSamplers> texture_units; |
| 118 | 119 | ||
| 119 | struct { | 120 | struct { |
| 120 | GLuint read_framebuffer; // GL_READ_FRAMEBUFFER_BINDING | 121 | GLuint read_framebuffer; // GL_READ_FRAMEBUFFER_BINDING |
| @@ -141,6 +142,10 @@ public: | |||
| 141 | GLsizei height; | 142 | GLsizei height; |
| 142 | } viewport; | 143 | } viewport; |
| 143 | 144 | ||
| 145 | struct { | ||
| 146 | float size; // GL_POINT_SIZE | ||
| 147 | } point; | ||
| 148 | |||
| 144 | std::array<bool, 2> clip_distance; // GL_CLIP_DISTANCE | 149 | std::array<bool, 2> clip_distance; // GL_CLIP_DISTANCE |
| 145 | 150 | ||
| 146 | OpenGLState(); | 151 | OpenGLState(); |
diff --git a/src/yuzu/game_list.cpp b/src/yuzu/game_list.cpp index 991ae10cd..67890455a 100644 --- a/src/yuzu/game_list.cpp +++ b/src/yuzu/game_list.cpp | |||
| @@ -26,10 +26,10 @@ | |||
| 26 | #include "yuzu/main.h" | 26 | #include "yuzu/main.h" |
| 27 | #include "yuzu/ui_settings.h" | 27 | #include "yuzu/ui_settings.h" |
| 28 | 28 | ||
| 29 | GameList::SearchField::KeyReleaseEater::KeyReleaseEater(GameList* gamelist) : gamelist{gamelist} {} | 29 | GameListSearchField::KeyReleaseEater::KeyReleaseEater(GameList* gamelist) : gamelist{gamelist} {} |
| 30 | 30 | ||
| 31 | // EventFilter in order to process systemkeys while editing the searchfield | 31 | // EventFilter in order to process systemkeys while editing the searchfield |
| 32 | bool GameList::SearchField::KeyReleaseEater::eventFilter(QObject* obj, QEvent* event) { | 32 | bool GameListSearchField::KeyReleaseEater::eventFilter(QObject* obj, QEvent* event) { |
| 33 | // If it isn't a KeyRelease event then continue with standard event processing | 33 | // If it isn't a KeyRelease event then continue with standard event processing |
| 34 | if (event->type() != QEvent::KeyRelease) | 34 | if (event->type() != QEvent::KeyRelease) |
| 35 | return QObject::eventFilter(obj, event); | 35 | return QObject::eventFilter(obj, event); |
| @@ -88,21 +88,21 @@ bool GameList::SearchField::KeyReleaseEater::eventFilter(QObject* obj, QEvent* e | |||
| 88 | return QObject::eventFilter(obj, event); | 88 | return QObject::eventFilter(obj, event); |
| 89 | } | 89 | } |
| 90 | 90 | ||
| 91 | void GameList::SearchField::setFilterResult(int visible, int total) { | 91 | void GameListSearchField::setFilterResult(int visible, int total) { |
| 92 | label_filter_result->setText(tr("%1 of %n result(s)", "", total).arg(visible)); | 92 | label_filter_result->setText(tr("%1 of %n result(s)", "", total).arg(visible)); |
| 93 | } | 93 | } |
| 94 | 94 | ||
| 95 | void GameList::SearchField::clear() { | 95 | void GameListSearchField::clear() { |
| 96 | edit_filter->setText(""); | 96 | edit_filter->setText(""); |
| 97 | } | 97 | } |
| 98 | 98 | ||
| 99 | void GameList::SearchField::setFocus() { | 99 | void GameListSearchField::setFocus() { |
| 100 | if (edit_filter->isVisible()) { | 100 | if (edit_filter->isVisible()) { |
| 101 | edit_filter->setFocus(); | 101 | edit_filter->setFocus(); |
| 102 | } | 102 | } |
| 103 | } | 103 | } |
| 104 | 104 | ||
| 105 | GameList::SearchField::SearchField(GameList* parent) : QWidget{parent} { | 105 | GameListSearchField::GameListSearchField(GameList* parent) : QWidget{parent} { |
| 106 | KeyReleaseEater* keyReleaseEater = new KeyReleaseEater(parent); | 106 | KeyReleaseEater* keyReleaseEater = new KeyReleaseEater(parent); |
| 107 | layout_filter = new QHBoxLayout; | 107 | layout_filter = new QHBoxLayout; |
| 108 | layout_filter->setMargin(8); | 108 | layout_filter->setMargin(8); |
| @@ -202,7 +202,7 @@ GameList::GameList(FileSys::VirtualFilesystem vfs, GMainWindow* parent) | |||
| 202 | this->main_window = parent; | 202 | this->main_window = parent; |
| 203 | layout = new QVBoxLayout; | 203 | layout = new QVBoxLayout; |
| 204 | tree_view = new QTreeView; | 204 | tree_view = new QTreeView; |
| 205 | search_field = new SearchField(this); | 205 | search_field = new GameListSearchField(this); |
| 206 | item_model = new QStandardItemModel(tree_view); | 206 | item_model = new QStandardItemModel(tree_view); |
| 207 | tree_view->setModel(item_model); | 207 | tree_view->setModel(item_model); |
| 208 | 208 | ||
diff --git a/src/yuzu/game_list.h b/src/yuzu/game_list.h index 3bf51870e..05e115e19 100644 --- a/src/yuzu/game_list.h +++ b/src/yuzu/game_list.h | |||
| @@ -22,6 +22,7 @@ | |||
| 22 | #include "yuzu/compatibility_list.h" | 22 | #include "yuzu/compatibility_list.h" |
| 23 | 23 | ||
| 24 | class GameListWorker; | 24 | class GameListWorker; |
| 25 | class GameListSearchField; | ||
| 25 | class GMainWindow; | 26 | class GMainWindow; |
| 26 | 27 | ||
| 27 | namespace FileSys { | 28 | namespace FileSys { |
| @@ -46,33 +47,6 @@ public: | |||
| 46 | COLUMN_COUNT, // Number of columns | 47 | COLUMN_COUNT, // Number of columns |
| 47 | }; | 48 | }; |
| 48 | 49 | ||
| 49 | class SearchField : public QWidget { | ||
| 50 | public: | ||
| 51 | void setFilterResult(int visible, int total); | ||
| 52 | void clear(); | ||
| 53 | void setFocus(); | ||
| 54 | explicit SearchField(GameList* parent = nullptr); | ||
| 55 | |||
| 56 | private: | ||
| 57 | class KeyReleaseEater : public QObject { | ||
| 58 | public: | ||
| 59 | explicit KeyReleaseEater(GameList* gamelist); | ||
| 60 | |||
| 61 | private: | ||
| 62 | GameList* gamelist = nullptr; | ||
| 63 | QString edit_filter_text_old; | ||
| 64 | |||
| 65 | protected: | ||
| 66 | bool eventFilter(QObject* obj, QEvent* event) override; | ||
| 67 | }; | ||
| 68 | QHBoxLayout* layout_filter = nullptr; | ||
| 69 | QTreeView* tree_view = nullptr; | ||
| 70 | QLabel* label_filter = nullptr; | ||
| 71 | QLineEdit* edit_filter = nullptr; | ||
| 72 | QLabel* label_filter_result = nullptr; | ||
| 73 | QToolButton* button_filter_close = nullptr; | ||
| 74 | }; | ||
| 75 | |||
| 76 | explicit GameList(std::shared_ptr<FileSys::VfsFilesystem> vfs, GMainWindow* parent = nullptr); | 50 | explicit GameList(std::shared_ptr<FileSys::VfsFilesystem> vfs, GMainWindow* parent = nullptr); |
| 77 | ~GameList() override; | 51 | ~GameList() override; |
| 78 | 52 | ||
| @@ -110,7 +84,7 @@ private: | |||
| 110 | void RefreshGameDirectory(); | 84 | void RefreshGameDirectory(); |
| 111 | 85 | ||
| 112 | std::shared_ptr<FileSys::VfsFilesystem> vfs; | 86 | std::shared_ptr<FileSys::VfsFilesystem> vfs; |
| 113 | SearchField* search_field; | 87 | GameListSearchField* search_field; |
| 114 | GMainWindow* main_window = nullptr; | 88 | GMainWindow* main_window = nullptr; |
| 115 | QVBoxLayout* layout = nullptr; | 89 | QVBoxLayout* layout = nullptr; |
| 116 | QTreeView* tree_view = nullptr; | 90 | QTreeView* tree_view = nullptr; |
| @@ -118,6 +92,8 @@ private: | |||
| 118 | GameListWorker* current_worker = nullptr; | 92 | GameListWorker* current_worker = nullptr; |
| 119 | QFileSystemWatcher* watcher = nullptr; | 93 | QFileSystemWatcher* watcher = nullptr; |
| 120 | CompatibilityList compatibility_list; | 94 | CompatibilityList compatibility_list; |
| 95 | |||
| 96 | friend class GameListSearchField; | ||
| 121 | }; | 97 | }; |
| 122 | 98 | ||
| 123 | Q_DECLARE_METATYPE(GameListOpenTarget); | 99 | Q_DECLARE_METATYPE(GameListOpenTarget); |
diff --git a/src/yuzu/game_list_p.h b/src/yuzu/game_list_p.h index cee109730..3db0e90da 100644 --- a/src/yuzu/game_list_p.h +++ b/src/yuzu/game_list_p.h | |||
| @@ -16,6 +16,7 @@ | |||
| 16 | #include <QObject> | 16 | #include <QObject> |
| 17 | #include <QStandardItem> | 17 | #include <QStandardItem> |
| 18 | #include <QString> | 18 | #include <QString> |
| 19 | #include <QWidget> | ||
| 19 | 20 | ||
| 20 | #include "common/common_types.h" | 21 | #include "common/common_types.h" |
| 21 | #include "common/logging/log.h" | 22 | #include "common/logging/log.h" |
| @@ -176,3 +177,42 @@ public: | |||
| 176 | return data(SizeRole).toULongLong() < other.data(SizeRole).toULongLong(); | 177 | return data(SizeRole).toULongLong() < other.data(SizeRole).toULongLong(); |
| 177 | } | 178 | } |
| 178 | }; | 179 | }; |
| 180 | |||
| 181 | class GameList; | ||
| 182 | class QHBoxLayout; | ||
| 183 | class QTreeView; | ||
| 184 | class QLabel; | ||
| 185 | class QLineEdit; | ||
| 186 | class QToolButton; | ||
| 187 | |||
| 188 | class GameListSearchField : public QWidget { | ||
| 189 | Q_OBJECT | ||
| 190 | |||
| 191 | public: | ||
| 192 | explicit GameListSearchField(GameList* parent = nullptr); | ||
| 193 | |||
| 194 | void setFilterResult(int visible, int total); | ||
| 195 | |||
| 196 | void clear(); | ||
| 197 | void setFocus(); | ||
| 198 | |||
| 199 | private: | ||
| 200 | class KeyReleaseEater : public QObject { | ||
| 201 | public: | ||
| 202 | explicit KeyReleaseEater(GameList* gamelist); | ||
| 203 | |||
| 204 | private: | ||
| 205 | GameList* gamelist = nullptr; | ||
| 206 | QString edit_filter_text_old; | ||
| 207 | |||
| 208 | protected: | ||
| 209 | // EventFilter in order to process systemkeys while editing the searchfield | ||
| 210 | bool eventFilter(QObject* obj, QEvent* event) override; | ||
| 211 | }; | ||
| 212 | QHBoxLayout* layout_filter = nullptr; | ||
| 213 | QTreeView* tree_view = nullptr; | ||
| 214 | QLabel* label_filter = nullptr; | ||
| 215 | QLineEdit* edit_filter = nullptr; | ||
| 216 | QLabel* label_filter_result = nullptr; | ||
| 217 | QToolButton* button_filter_close = nullptr; | ||
| 218 | }; | ||