diff --git a/src/audio_core/hle/hle.cpp b/src/audio_core/hle/hle.cpp index db50c0bff..4fa4145e2 100644 --- a/src/audio_core/hle/hle.cpp +++ b/src/audio_core/hle/hle.cpp @@ -24,7 +24,7 @@ static constexpr u64 audio_frame_ticks = 1310252ull; ///< Units: ARM11 cycles struct DspHle::Impl final { public: - explicit Impl(DspHle& parent); + explicit Impl(DspHle& parent, Memory::MemorySystem& memory); ~Impl(); DspState GetDspState() const; @@ -69,9 +69,13 @@ private: std::weak_ptr dsp_dsp; }; -DspHle::Impl::Impl(DspHle& parent_) : parent(parent_) { +DspHle::Impl::Impl(DspHle& parent_, Memory::MemorySystem& memory) : parent(parent_) { dsp_memory.raw_memory.fill(0); + for (auto& source : sources) { + source.SetMemory(memory); + } + Core::Timing& timing = Core::System::GetInstance().CoreTiming(); tick_event = timing.RegisterEvent("AudioCore::DspHle::tick_event", [this](u64, s64 cycles_late) { @@ -335,7 +339,7 @@ void DspHle::Impl::AudioTickCallback(s64 cycles_late) { timing.ScheduleEvent(audio_frame_ticks - cycles_late, tick_event); } -DspHle::DspHle() : impl(std::make_unique(*this)) {} +DspHle::DspHle(Memory::MemorySystem& memory) : impl(std::make_unique(*this, memory)) {} DspHle::~DspHle() = default; DspState DspHle::GetDspState() const { diff --git a/src/audio_core/hle/hle.h b/src/audio_core/hle/hle.h index a957ee2f4..70abddbd5 100644 --- a/src/audio_core/hle/hle.h +++ b/src/audio_core/hle/hle.h @@ -13,11 +13,15 @@ #include "core/hle/service/dsp/dsp_dsp.h" #include "core/memory.h" +namespace Memory { +class MemorySystem; +} + namespace AudioCore { class DspHle final : public DspInterface { public: - DspHle(); + explicit DspHle(Memory::MemorySystem& memory); ~DspHle(); DspState GetDspState() const override; diff --git a/src/audio_core/hle/source.cpp b/src/audio_core/hle/source.cpp index cbf99ec9d..704a79f05 100644 --- a/src/audio_core/hle/source.cpp +++ b/src/audio_core/hle/source.cpp @@ -45,6 +45,10 @@ void Source::Reset() { state = {}; } +void Source::SetMemory(Memory::MemorySystem& memory) { + memory_system = &memory; +} + void Source::ParseConfig(SourceConfiguration::Configuration& config, const s16_le (&adpcm_coeffs)[16]) { if (!config.dirty_raw) { @@ -286,7 +290,7 @@ bool Source::DequeueBuffer() { // This physical address masking occurs due to how the DSP DMA hardware is configured by the // firmware. - const u8* const memory = Memory::GetPhysicalPointer(buf.physical_address & 0xFFFFFFFC); + const u8* const memory = memory_system->GetPhysicalPointer(buf.physical_address & 0xFFFFFFFC); if (memory) { const unsigned num_channels = buf.mono_or_stereo == MonoOrStereo::Stereo ? 2 : 1; switch (buf.format) { diff --git a/src/audio_core/hle/source.h b/src/audio_core/hle/source.h index 2e24c5eab..5f9f5b924 100644 --- a/src/audio_core/hle/source.h +++ b/src/audio_core/hle/source.h @@ -14,6 +14,10 @@ #include "audio_core/interpolate.h" #include "common/common_types.h" +namespace Memory { +class MemorySystem; +} + namespace AudioCore { namespace HLE { @@ -35,6 +39,9 @@ public: /// Resets internal state. void Reset(); + /// Sets the memory system to read data from + void SetMemory(Memory::MemorySystem& memory); + /** * This is called once every audio frame. This performs per-source processing every frame. * @param config The new configuration we've got for this Source from the application. @@ -56,6 +63,7 @@ public: private: const std::size_t source_id; + Memory::MemorySystem* memory_system; StereoFrame16 current_frame; using Format = SourceConfiguration::Configuration::Format; diff --git a/src/citra_qt/debugger/graphics/graphics_cmdlists.cpp b/src/citra_qt/debugger/graphics/graphics_cmdlists.cpp index 069f84b8e..6fdfbee1e 100644 --- a/src/citra_qt/debugger/graphics/graphics_cmdlists.cpp +++ b/src/citra_qt/debugger/graphics/graphics_cmdlists.cpp @@ -17,6 +17,7 @@ #include "citra_qt/util/spinbox.h" #include "citra_qt/util/util.h" #include "common/vector_math.h" +#include "core/core.h" #include "core/memory.h" #include "video_core/debug_utils/debug_utils.h" #include "video_core/pica_state.h" @@ -166,7 +167,8 @@ void GPUCommandListWidget::SetCommandInfo(const QModelIndex& index) { const auto format = texture.format; const auto info = Pica::Texture::TextureInfo::FromPicaRegister(config, format); - const u8* src = Memory::GetPhysicalPointer(config.GetPhysicalAddress()); + const u8* src = + Core::System::GetInstance().Memory().GetPhysicalPointer(config.GetPhysicalAddress()); new_info_widget = new TextureInfoWidget(src, info); } if (command_info_widget) { diff --git a/src/citra_qt/debugger/graphics/graphics_surface.cpp b/src/citra_qt/debugger/graphics/graphics_surface.cpp index d480505b0..8b2aa4c9f 100644 --- a/src/citra_qt/debugger/graphics/graphics_surface.cpp +++ b/src/citra_qt/debugger/graphics/graphics_surface.cpp @@ -14,6 +14,7 @@ #include "citra_qt/debugger/graphics/graphics_surface.h" #include "citra_qt/util/spinbox.h" #include "common/color.h" +#include "core/core.h" #include "core/hw/gpu.h" #include "core/memory.h" #include "video_core/pica_state.h" @@ -283,7 +284,7 @@ void GraphicsSurfaceWidget::Pick(int x, int y) { return; } - u8* buffer = Memory::GetPhysicalPointer(surface_address); + u8* buffer = Core::System::GetInstance().Memory().GetPhysicalPointer(surface_address); if (buffer == nullptr) { surface_info_label->setText(tr("(unable to access pixel data)")); surface_info_label->setAlignment(Qt::AlignCenter); @@ -549,7 +550,7 @@ void GraphicsSurfaceWidget::OnUpdate() { // TODO: Implement a good way to visualize alpha components! QImage decoded_image(surface_width, surface_height, QImage::Format_ARGB32); - u8* buffer = Memory::GetPhysicalPointer(surface_address); + u8* buffer = Core::System::GetInstance().Memory().GetPhysicalPointer(surface_address); if (buffer == nullptr) { surface_picture_label->hide(); @@ -679,7 +680,7 @@ void GraphicsSurfaceWidget::SaveSurface() { if (pixmap) pixmap->save(&file, "PNG"); } else if (selectedFilter == bin_filter) { - const u8* buffer = Memory::GetPhysicalPointer(surface_address); + const u8* buffer = Core::System::GetInstance().Memory().GetPhysicalPointer(surface_address); ASSERT_MSG(buffer != nullptr, "Memory not accessible"); QFile file(filename); diff --git a/src/core/arm/dynarmic/arm_dynarmic.cpp b/src/core/arm/dynarmic/arm_dynarmic.cpp index 19b6753a4..62c63f9ac 100644 --- a/src/core/arm/dynarmic/arm_dynarmic.cpp +++ b/src/core/arm/dynarmic/arm_dynarmic.cpp @@ -72,33 +72,34 @@ private: class DynarmicUserCallbacks final : public Dynarmic::A32::UserCallbacks { public: explicit DynarmicUserCallbacks(ARM_Dynarmic& parent) - : parent(parent), timing(parent.system.CoreTiming()), svc_context(parent.system) {} + : parent(parent), timing(parent.system.CoreTiming()), svc_context(parent.system), + memory(parent.system.Memory()) {} ~DynarmicUserCallbacks() = default; std::uint8_t MemoryRead8(VAddr vaddr) override { - return Memory::Read8(vaddr); + return memory.Read8(vaddr); } std::uint16_t MemoryRead16(VAddr vaddr) override { - return Memory::Read16(vaddr); + return memory.Read16(vaddr); } std::uint32_t MemoryRead32(VAddr vaddr) override { - return Memory::Read32(vaddr); + return memory.Read32(vaddr); } std::uint64_t MemoryRead64(VAddr vaddr) override { - return Memory::Read64(vaddr); + return memory.Read64(vaddr); } void MemoryWrite8(VAddr vaddr, std::uint8_t value) override { - Memory::Write8(vaddr, value); + memory.Write8(vaddr, value); } void MemoryWrite16(VAddr vaddr, std::uint16_t value) override { - Memory::Write16(vaddr, value); + memory.Write16(vaddr, value); } void MemoryWrite32(VAddr vaddr, std::uint32_t value) override { - Memory::Write32(vaddr, value); + memory.Write32(vaddr, value); } void MemoryWrite64(VAddr vaddr, std::uint64_t value) override { - Memory::Write64(vaddr, value); + memory.Write64(vaddr, value); } void InterpreterFallback(VAddr pc, std::size_t num_instructions) override { @@ -136,7 +137,7 @@ public: parent.jit->HaltExecution(); parent.SetPC(pc); Kernel::Thread* thread = - Core::System::GetInstance().Kernel().GetThreadManager().GetCurrentThread(); + parent.system.Kernel().GetThreadManager().GetCurrentThread(); parent.SaveContext(thread->context); GDBStub::Break(); GDBStub::SendTrap(thread, 5); @@ -159,11 +160,12 @@ public: ARM_Dynarmic& parent; Core::Timing& timing; Kernel::SVCContext svc_context; + Memory::MemorySystem& memory; }; ARM_Dynarmic::ARM_Dynarmic(Core::System& system, PrivilegeMode initial_mode) : system(system), cb(std::make_unique(*this)) { - interpreter_state = std::make_shared(initial_mode); + interpreter_state = std::make_shared(system, initial_mode); PageTableChanged(); } @@ -172,7 +174,7 @@ ARM_Dynarmic::~ARM_Dynarmic() = default; MICROPROFILE_DEFINE(ARM_Jit, "ARM JIT", "ARM JIT", MP_RGB(255, 64, 64)); void ARM_Dynarmic::Run() { - ASSERT(Memory::GetCurrentPageTable() == current_page_table); + ASSERT(system.Memory().GetCurrentPageTable() == current_page_table); MICROPROFILE_SCOPE(ARM_Jit); jit->Run(); @@ -279,7 +281,7 @@ void ARM_Dynarmic::InvalidateCacheRange(u32 start_address, std::size_t length) { } void ARM_Dynarmic::PageTableChanged() { - current_page_table = Memory::GetCurrentPageTable(); + current_page_table = system.Memory().GetCurrentPageTable(); auto iter = jits.find(current_page_table); if (iter != jits.end()) { diff --git a/src/core/arm/dyncom/arm_dyncom.cpp b/src/core/arm/dyncom/arm_dyncom.cpp index d3113632c..4ee22dfdd 100644 --- a/src/core/arm/dyncom/arm_dyncom.cpp +++ b/src/core/arm/dyncom/arm_dyncom.cpp @@ -68,14 +68,14 @@ private: u32 fpexc; }; -ARM_DynCom::ARM_DynCom(PrivilegeMode initial_mode) { - state = std::make_unique(initial_mode); +ARM_DynCom::ARM_DynCom(Core::System& system, PrivilegeMode initial_mode) : system(system) { + state = std::make_unique(system, initial_mode); } ARM_DynCom::~ARM_DynCom() {} void ARM_DynCom::Run() { - ExecuteInstructions(std::max(Core::System::GetInstance().CoreTiming().GetDowncount(), 0)); + ExecuteInstructions(std::max(system.CoreTiming().GetDowncount(), 0)); } void ARM_DynCom::Step() { @@ -146,7 +146,7 @@ void ARM_DynCom::SetCP15Register(CP15Register reg, u32 value) { void ARM_DynCom::ExecuteInstructions(u64 num_instructions) { state->NumInstrsToExecute = num_instructions; unsigned ticks_executed = InterpreterMainLoop(state.get()); - Core::System::GetInstance().CoreTiming().AddTicks(ticks_executed); + system.CoreTiming().AddTicks(ticks_executed); state->ServeBreak(); } diff --git a/src/core/arm/dyncom/arm_dyncom.h b/src/core/arm/dyncom/arm_dyncom.h index 38d6a33c7..83366e09d 100644 --- a/src/core/arm/dyncom/arm_dyncom.h +++ b/src/core/arm/dyncom/arm_dyncom.h @@ -10,9 +10,13 @@ #include "core/arm/skyeye_common/arm_regformat.h" #include "core/arm/skyeye_common/armstate.h" +namespace Core { +struct System; +} + class ARM_DynCom final : public ARM_Interface { public: - explicit ARM_DynCom(PrivilegeMode initial_mode); + explicit ARM_DynCom(Core::System& system, PrivilegeMode initial_mode); ~ARM_DynCom(); void Run() override; @@ -44,5 +48,6 @@ public: private: void ExecuteInstructions(u64 num_instructions); + Core::System& system; std::unique_ptr state; }; diff --git a/src/core/arm/dyncom/arm_dyncom_interpreter.cpp b/src/core/arm/dyncom/arm_dyncom_interpreter.cpp index 4854eb23e..0a50d31b6 100644 --- a/src/core/arm/dyncom/arm_dyncom_interpreter.cpp +++ b/src/core/arm/dyncom/arm_dyncom_interpreter.cpp @@ -811,7 +811,7 @@ MICROPROFILE_DEFINE(DynCom_Decode, "DynCom", "Decode", MP_RGB(255, 64, 64)); static unsigned int InterpreterTranslateInstruction(const ARMul_State* cpu, const u32 phys_addr, ARM_INST_PTR& inst_base) { u32 inst_size = 4; - u32 inst = Memory::Read32(phys_addr & 0xFFFFFFFC); + u32 inst = cpu->system.Memory().Read32(phys_addr & 0xFFFFFFFC); // If we are in Thumb mode, we'll translate one Thumb instruction to the corresponding ARM // instruction @@ -3860,11 +3860,11 @@ SUB_INST : { SWI_INST : { if (inst_base->cond == ConditionCode::AL || CondPassed(cpu, inst_base->cond)) { swi_inst* const inst_cream = (swi_inst*)inst_base->component; - Core::System::GetInstance().CoreTiming().AddTicks(num_instrs); + cpu->system.CoreTiming().AddTicks(num_instrs); cpu->NumInstrsToExecute = num_instrs >= cpu->NumInstrsToExecute ? 0 : cpu->NumInstrsToExecute - num_instrs; num_instrs = 0; - Kernel::SVCContext{Core::System::GetInstance()}.CallSVC(inst_cream->num & 0xFFFF); + Kernel::SVCContext{cpu->system}.CallSVC(inst_cream->num & 0xFFFF); // The kernel would call ERET to get here, which clears exclusive memory state. cpu->UnsetExclusiveMemoryAddress(); } diff --git a/src/core/arm/skyeye_common/armstate.cpp b/src/core/arm/skyeye_common/armstate.cpp index a6920c89b..27a7540cc 100644 --- a/src/core/arm/skyeye_common/armstate.cpp +++ b/src/core/arm/skyeye_common/armstate.cpp @@ -10,7 +10,7 @@ #include "core/core.h" #include "core/memory.h" -ARMul_State::ARMul_State(PrivilegeMode initial_mode) { +ARMul_State::ARMul_State(Core::System& system, PrivilegeMode initial_mode) : system(system) { Reset(); ChangePrivilegeMode(initial_mode); } @@ -191,13 +191,13 @@ static void CheckMemoryBreakpoint(u32 address, GDBStub::BreakpointType type) { u8 ARMul_State::ReadMemory8(u32 address) const { CheckMemoryBreakpoint(address, GDBStub::BreakpointType::Read); - return Memory::Read8(address); + return system.Memory().Read8(address); } u16 ARMul_State::ReadMemory16(u32 address) const { CheckMemoryBreakpoint(address, GDBStub::BreakpointType::Read); - u16 data = Memory::Read16(address); + u16 data = system.Memory().Read16(address); if (InBigEndianMode()) data = Common::swap16(data); @@ -208,7 +208,7 @@ u16 ARMul_State::ReadMemory16(u32 address) const { u32 ARMul_State::ReadMemory32(u32 address) const { CheckMemoryBreakpoint(address, GDBStub::BreakpointType::Read); - u32 data = Memory::Read32(address); + u32 data = system.Memory().Read32(address); if (InBigEndianMode()) data = Common::swap32(data); @@ -219,7 +219,7 @@ u32 ARMul_State::ReadMemory32(u32 address) const { u64 ARMul_State::ReadMemory64(u32 address) const { CheckMemoryBreakpoint(address, GDBStub::BreakpointType::Read); - u64 data = Memory::Read64(address); + u64 data = system.Memory().Read64(address); if (InBigEndianMode()) data = Common::swap64(data); @@ -230,7 +230,7 @@ u64 ARMul_State::ReadMemory64(u32 address) const { void ARMul_State::WriteMemory8(u32 address, u8 data) { CheckMemoryBreakpoint(address, GDBStub::BreakpointType::Write); - Memory::Write8(address, data); + system.Memory().Write8(address, data); } void ARMul_State::WriteMemory16(u32 address, u16 data) { @@ -239,7 +239,7 @@ void ARMul_State::WriteMemory16(u32 address, u16 data) { if (InBigEndianMode()) data = Common::swap16(data); - Memory::Write16(address, data); + system.Memory().Write16(address, data); } void ARMul_State::WriteMemory32(u32 address, u32 data) { @@ -248,7 +248,7 @@ void ARMul_State::WriteMemory32(u32 address, u32 data) { if (InBigEndianMode()) data = Common::swap32(data); - Memory::Write32(address, data); + system.Memory().Write32(address, data); } void ARMul_State::WriteMemory64(u32 address, u64 data) { @@ -257,7 +257,7 @@ void ARMul_State::WriteMemory64(u32 address, u64 data) { if (InBigEndianMode()) data = Common::swap64(data); - Memory::Write64(address, data); + system.Memory().Write64(address, data); } // Reads from the CP15 registers. Used with implementation of the MRC instruction. @@ -603,9 +603,8 @@ void ARMul_State::ServeBreak() { if (last_bkpt_hit) { Reg[15] = last_bkpt.address; } - Kernel::Thread* thread = - Core::System::GetInstance().Kernel().GetThreadManager().GetCurrentThread(); - Core::CPU().SaveContext(thread->context); + Kernel::Thread* thread = system.Kernel().GetThreadManager().GetCurrentThread(); + system.CPU().SaveContext(thread->context); if (last_bkpt_hit || GDBStub::GetCpuStepFlag()) { last_bkpt_hit = false; GDBStub::Break(); diff --git a/src/core/arm/skyeye_common/armstate.h b/src/core/arm/skyeye_common/armstate.h index 2f99b738b..9327dc88c 100644 --- a/src/core/arm/skyeye_common/armstate.h +++ b/src/core/arm/skyeye_common/armstate.h @@ -23,6 +23,10 @@ #include "core/arm/skyeye_common/arm_regformat.h" #include "core/gdbstub/gdbstub.h" +namespace Core { +class System; +} + // Signal levels enum { LOW = 0, HIGH = 1, LOWHIGH = 1, HIGHLOW = 2 }; @@ -139,7 +143,7 @@ enum { struct ARMul_State final { public: - explicit ARMul_State(PrivilegeMode initial_mode); + explicit ARMul_State(Core::System& system, PrivilegeMode initial_mode); void ChangePrivilegeMode(u32 new_mode); void Reset(); @@ -197,6 +201,8 @@ public: void ServeBreak(); + Core::System& system; + std::array Reg{}; // The current register file std::array Reg_usr{}; std::array Reg_svc{}; // R13_SVC R14_SVC diff --git a/src/core/cheats/gateway_cheat.cpp b/src/core/cheats/gateway_cheat.cpp index 06fb41485..af7e0f8cf 100644 --- a/src/core/cheats/gateway_cheat.cpp +++ b/src/core/cheats/gateway_cheat.cpp @@ -49,9 +49,10 @@ static inline std::enable_if_t> CompOp(const GatewayCheat: } } -static inline void LoadOffsetOp(const GatewayCheat::CheatLine& line, State& state) { +static inline void LoadOffsetOp(Memory::MemorySystem& memory, const GatewayCheat::CheatLine& line, + State& state) { u32 addr = line.address + state.offset; - state.offset = Memory::Read32(addr); + state.offset = memory.Read32(addr); } static inline void LoopOp(const GatewayCheat::CheatLine& line, State& state) { @@ -154,7 +155,7 @@ static inline void PatchOp(const GatewayCheat::CheatLine& line, State& state, Co state.current_line_nr++; } first = !first; - Memory::Write32(addr, tmp); + system.Memory().Write32(addr, tmp); addr += 4; num_bytes -= 4; } @@ -162,7 +163,7 @@ static inline void PatchOp(const GatewayCheat::CheatLine& line, State& state, Co u32 tmp = (first ? cheat_lines[state.current_line_nr].first : cheat_lines[state.current_line_nr].value) >> bit_offset; - Memory::Write8(addr, tmp); + system.Memory().Write8(addr, tmp); addr += 1; num_bytes -= 1; bit_offset += 8; @@ -205,6 +206,14 @@ GatewayCheat::~GatewayCheat() = default; void GatewayCheat::Execute(Core::System& system) { State state; + Memory::MemorySystem& memory = system.Memory(); + auto Read8 = [&memory](VAddr addr) { return memory.Read8(addr); }; + auto Read16 = [&memory](VAddr addr) { return memory.Read16(addr); }; + auto Read32 = [&memory](VAddr addr) { return memory.Read32(addr); }; + auto Write8 = [&memory](VAddr addr, u8 value) { memory.Write8(addr, value); }; + auto Write16 = [&memory](VAddr addr, u16 value) { memory.Write16(addr, value); }; + auto Write32 = [&memory](VAddr addr, u32 value) { memory.Write32(addr, value); }; + for (state.current_line_nr = 0; state.current_line_nr < cheat_lines.size(); state.current_line_nr++) { auto line = cheat_lines[state.current_line_nr]; @@ -247,63 +256,61 @@ void GatewayCheat::Execute(Core::System& system) { break; case CheatType::Write32: // 0XXXXXXX YYYYYYYY - word[XXXXXXX+offset] = YYYYYYYY - WriteOp(line, state, &Memory::Write32, system); + WriteOp(line, state, Write32, system); break; case CheatType::Write16: // 1XXXXXXX 0000YYYY - half[XXXXXXX+offset] = YYYY - WriteOp(line, state, &Memory::Write16, system); + WriteOp(line, state, Write16, system); break; case CheatType::Write8: // 2XXXXXXX 000000YY - byte[XXXXXXX+offset] = YY - WriteOp(line, state, &Memory::Write8, system); + WriteOp(line, state, Write8, system); break; case CheatType::GreaterThan32: // 3XXXXXXX YYYYYYYY - Execute next block IF YYYYYYYY > word[XXXXXXX] ;unsigned - CompOp(line, state, &Memory::Read32, - [&line](u32 val) -> bool { return line.value > val; }); + CompOp(line, state, Read32, [&line](u32 val) -> bool { return line.value > val; }); break; case CheatType::LessThan32: // 4XXXXXXX YYYYYYYY - Execute next block IF YYYYYYYY < word[XXXXXXX] ;unsigned - CompOp(line, state, &Memory::Read32, - [&line](u32 val) -> bool { return line.value < val; }); + CompOp(line, state, Read32, [&line](u32 val) -> bool { return line.value < val; }); break; case CheatType::EqualTo32: // 5XXXXXXX YYYYYYYY - Execute next block IF YYYYYYYY == word[XXXXXXX] ;unsigned - CompOp(line, state, &Memory::Read32, + CompOp(line, state, Read32, [&line](u32 val) -> bool { return line.value == val; }); break; case CheatType::NotEqualTo32: // 6XXXXXXX YYYYYYYY - Execute next block IF YYYYYYYY != word[XXXXXXX] ;unsigned - CompOp(line, state, &Memory::Read32, + CompOp(line, state, Read32, [&line](u32 val) -> bool { return line.value != val; }); break; case CheatType::GreaterThan16WithMask: // 7XXXXXXX ZZZZYYYY - Execute next block IF YYYY > ((not ZZZZ) AND half[XXXXXXX]) - CompOp(line, state, &Memory::Read16, [&line](u16 val) -> bool { + CompOp(line, state, Read16, [&line](u16 val) -> bool { return static_cast(line.value) > (static_cast(~line.value >> 16) & val); }); break; case CheatType::LessThan16WithMask: // 8XXXXXXX ZZZZYYYY - Execute next block IF YYYY < ((not ZZZZ) AND half[XXXXXXX]) - CompOp(line, state, &Memory::Read16, [&line](u16 val) -> bool { + CompOp(line, state, Read16, [&line](u16 val) -> bool { return static_cast(line.value) < (static_cast(~line.value >> 16) & val); }); break; case CheatType::EqualTo16WithMask: // 9XXXXXXX ZZZZYYYY - Execute next block IF YYYY = ((not ZZZZ) AND half[XXXXXXX]) - CompOp(line, state, &Memory::Read16, [&line](u16 val) -> bool { + CompOp(line, state, Read16, [&line](u16 val) -> bool { return static_cast(line.value) == (static_cast(~line.value >> 16) & val); }); break; case CheatType::NotEqualTo16WithMask: // AXXXXXXX ZZZZYYYY - Execute next block IF YYYY <> ((not ZZZZ) AND half[XXXXXXX]) - CompOp(line, state, &Memory::Read16, [&line](u16 val) -> bool { + CompOp(line, state, Read16, [&line](u16 val) -> bool { return static_cast(line.value) != (static_cast(~line.value >> 16) & val); }); break; case CheatType::LoadOffset: // BXXXXXXX 00000000 - offset = word[XXXXXXX+offset] - LoadOffsetOp(line, state); + LoadOffsetOp(system.Memory(), line, state); break; case CheatType::Loop: { // C0000000 YYYYYYYY - LOOP next block YYYYYYYY times @@ -343,32 +350,32 @@ void GatewayCheat::Execute(Core::System& system) { } case CheatType::IncrementiveWrite32: { // D6000000 XXXXXXXX – (32bit) [XXXXXXXX+offset] = reg ; offset += 4 - IncrementiveWriteOp(line, state, &Memory::Write32, system); + IncrementiveWriteOp(line, state, Write32, system); break; } case CheatType::IncrementiveWrite16: { // D7000000 XXXXXXXX – (16bit) [XXXXXXXX+offset] = reg & 0xffff ; offset += 2 - IncrementiveWriteOp(line, state, &Memory::Write16, system); + IncrementiveWriteOp(line, state, Write16, system); break; } case CheatType::IncrementiveWrite8: { // D8000000 XXXXXXXX – (16bit) [XXXXXXXX+offset] = reg & 0xff ; offset++ - IncrementiveWriteOp(line, state, &Memory::Write8, system); + IncrementiveWriteOp(line, state, Write8, system); break; } case CheatType::Load32: { // D9000000 XXXXXXXX – reg = [XXXXXXXX+offset] - LoadOp(line, state, &Memory::Read32); + LoadOp(line, state, Read32); break; } case CheatType::Load16: { // DA000000 XXXXXXXX – reg = [XXXXXXXX+offset] & 0xFFFF - LoadOp(line, state, &Memory::Read16); + LoadOp(line, state, Read16); break; } case CheatType::Load8: { // DB000000 XXXXXXXX – reg = [XXXXXXXX+offset] & 0xFF - LoadOp(line, state, &Memory::Read8); + LoadOp(line, state, Read8); break; } case CheatType::AddOffset: { diff --git a/src/core/core.cpp b/src/core/core.cpp index 295a2d7a8..c5c56d11a 100644 --- a/src/core/core.cpp +++ b/src/core/core.cpp @@ -143,7 +143,7 @@ System::ResultStatus System::Load(EmuWindow& emu_window, const std::string& file return ResultStatus::ErrorLoader; } } - Memory::SetCurrentPageTable(&kernel->GetCurrentProcess()->vm_manager.page_table); + memory->SetCurrentPageTable(&kernel->GetCurrentProcess()->vm_manager.page_table); cheat_engine = std::make_unique(*this); status = ResultStatus::Success; m_emu_window = &emu_window; @@ -172,22 +172,24 @@ void System::Reschedule() { System::ResultStatus System::Init(EmuWindow& emu_window, u32 system_mode) { LOG_DEBUG(HW_Memory, "initialized OK"); + memory = std::make_unique(); + timing = std::make_unique(); - kernel = std::make_unique(system_mode); + kernel = std::make_unique(*memory, system_mode); if (Settings::values.use_cpu_jit) { #ifdef ARCHITECTURE_x86_64 cpu_core = std::make_unique(*this, USER32MODE); #else - cpu_core = std::make_unique(USER32MODE); + cpu_core = std::make_unique(*this, USER32MODE); LOG_WARNING(Core, "CPU JIT requested, but Dynarmic not available"); #endif } else { - cpu_core = std::make_unique(USER32MODE); + cpu_core = std::make_unique(*this, USER32MODE); } - dsp_core = std::make_unique(); + dsp_core = std::make_unique(*memory); dsp_core->SetSink(Settings::values.sink_id, Settings::values.audio_device_id); dsp_core->EnableStretching(Settings::values.enable_audio_stretching); @@ -200,11 +202,11 @@ System::ResultStatus System::Init(EmuWindow& emu_window, u32 system_mode) { service_manager = std::make_shared(*this); archive_manager = std::make_unique(*this); - HW::Init(); + HW::Init(*memory); Service::Init(*this); GDBStub::Init(); - ResultStatus result = VideoCore::Init(emu_window); + ResultStatus result = VideoCore::Init(emu_window, *memory); if (result != ResultStatus::Success) { return result; } @@ -250,6 +252,14 @@ const Timing& System::CoreTiming() const { return *timing; } +Memory::MemorySystem& System::Memory() { + return *memory; +} + +const Memory::MemorySystem& System::Memory() const { + return *memory; +} + Cheats::CheatEngine& System::CheatEngine() { return *cheat_engine; } diff --git a/src/core/core.h b/src/core/core.h index e3b58b620..81d0dfffd 100644 --- a/src/core/core.h +++ b/src/core/core.h @@ -16,6 +16,10 @@ class EmuWindow; class ARM_Interface; +namespace Memory { +class MemorySystem; +} + namespace AudioCore { class DspInterface; } @@ -188,6 +192,12 @@ public: /// Gets a const reference to the timing system const Timing& CoreTiming() const; + /// Gets a reference to the memory system + Memory::MemorySystem& Memory(); + + /// Gets a const reference to the memory system + const Memory::MemorySystem& Memory() const; + /// Gets a reference to the cheat engine Cheats::CheatEngine& CheatEngine(); @@ -269,6 +279,9 @@ public: // HACK: this is temporary exposed for tests, std::unique_ptr kernel; std::unique_ptr timing; + /// Memory system + std::unique_ptr memory; + private: static System s_instance; diff --git a/src/core/gdbstub/gdbstub.cpp b/src/core/gdbstub/gdbstub.cpp index 55936ed97..035448efa 100644 --- a/src/core/gdbstub/gdbstub.cpp +++ b/src/core/gdbstub/gdbstub.cpp @@ -409,8 +409,9 @@ static void RemoveBreakpoint(BreakpointType type, VAddr addr) { LOG_DEBUG(Debug_GDBStub, "gdb: removed a breakpoint: {:08x} bytes at {:08x} of type {}", bp->second.len, bp->second.addr, static_cast(type)); - Memory::WriteBlock(*Core::System::GetInstance().Kernel().GetCurrentProcess(), bp->second.addr, - bp->second.inst.data(), bp->second.inst.size()); + Core::System::GetInstance().Memory().WriteBlock( + *Core::System::GetInstance().Kernel().GetCurrentProcess(), bp->second.addr, + bp->second.inst.data(), bp->second.inst.size()); Core::CPU().ClearInstructionCache(); p.erase(addr); } @@ -837,8 +838,8 @@ static void ReadMemory() { } std::vector data(len); - Memory::ReadBlock(*Core::System::GetInstance().Kernel().GetCurrentProcess(), addr, data.data(), - len); + Core::System::GetInstance().Memory().ReadBlock( + *Core::System::GetInstance().Kernel().GetCurrentProcess(), addr, data.data(), len); MemToGdbHex(reply, data.data(), len); reply[len * 2] = '\0'; @@ -863,8 +864,8 @@ static void WriteMemory() { std::vector data(len); GdbHexToMem(data.data(), len_pos + 1, len); - Memory::WriteBlock(*Core::System::GetInstance().Kernel().GetCurrentProcess(), addr, data.data(), - len); + Core::System::GetInstance().Memory().WriteBlock( + *Core::System::GetInstance().Kernel().GetCurrentProcess(), addr, data.data(), len); Core::CPU().ClearInstructionCache(); SendReply("OK"); } @@ -917,11 +918,13 @@ static bool CommitBreakpoint(BreakpointType type, VAddr addr, u32 len) { breakpoint.active = true; breakpoint.addr = addr; breakpoint.len = len; - Memory::ReadBlock(*Core::System::GetInstance().Kernel().GetCurrentProcess(), addr, - breakpoint.inst.data(), breakpoint.inst.size()); + Core::System::GetInstance().Memory().ReadBlock( + *Core::System::GetInstance().Kernel().GetCurrentProcess(), addr, breakpoint.inst.data(), + breakpoint.inst.size()); static constexpr std::array btrap{0x70, 0x00, 0x20, 0xe1}; - Memory::WriteBlock(*Core::System::GetInstance().Kernel().GetCurrentProcess(), addr, - btrap.data(), btrap.size()); + Core::System::GetInstance().Memory().WriteBlock( + *Core::System::GetInstance().Kernel().GetCurrentProcess(), addr, btrap.data(), + btrap.size()); Core::CPU().ClearInstructionCache(); p.insert({addr, breakpoint}); diff --git a/src/core/hle/kernel/address_arbiter.cpp b/src/core/hle/kernel/address_arbiter.cpp index d391da208..cc5404570 100644 --- a/src/core/hle/kernel/address_arbiter.cpp +++ b/src/core/hle/kernel/address_arbiter.cpp @@ -65,7 +65,7 @@ SharedPtr AddressArbiter::ResumeHighestPriorityThread(VAddr address) { return thread; } -AddressArbiter::AddressArbiter(KernelSystem& kernel) : Object(kernel) {} +AddressArbiter::AddressArbiter(KernelSystem& kernel) : Object(kernel), kernel(kernel) {} AddressArbiter::~AddressArbiter() {} SharedPtr KernelSystem::CreateAddressArbiter(std::string name) { @@ -103,31 +103,31 @@ ResultCode AddressArbiter::ArbitrateAddress(SharedPtr thread, Arbitratio // Wait current thread (acquire the arbiter)... case ArbitrationType::WaitIfLessThan: - if ((s32)Memory::Read32(address) < value) { + if ((s32)kernel.memory.Read32(address) < value) { WaitThread(std::move(thread), address); } break; case ArbitrationType::WaitIfLessThanWithTimeout: - if ((s32)Memory::Read32(address) < value) { + if ((s32)kernel.memory.Read32(address) < value) { thread->wakeup_callback = timeout_callback; thread->WakeAfterDelay(nanoseconds); WaitThread(std::move(thread), address); } break; case ArbitrationType::DecrementAndWaitIfLessThan: { - s32 memory_value = Memory::Read32(address); + s32 memory_value = kernel.memory.Read32(address); if (memory_value < value) { // Only change the memory value if the thread should wait - Memory::Write32(address, (s32)memory_value - 1); + kernel.memory.Write32(address, (s32)memory_value - 1); WaitThread(std::move(thread), address); } break; } case ArbitrationType::DecrementAndWaitIfLessThanWithTimeout: { - s32 memory_value = Memory::Read32(address); + s32 memory_value = kernel.memory.Read32(address); if (memory_value < value) { // Only change the memory value if the thread should wait - Memory::Write32(address, (s32)memory_value - 1); + kernel.memory.Write32(address, (s32)memory_value - 1); thread->wakeup_callback = timeout_callback; thread->WakeAfterDelay(nanoseconds); WaitThread(std::move(thread), address); diff --git a/src/core/hle/kernel/address_arbiter.h b/src/core/hle/kernel/address_arbiter.h index cdfa64ec2..ac01749f7 100644 --- a/src/core/hle/kernel/address_arbiter.h +++ b/src/core/hle/kernel/address_arbiter.h @@ -52,6 +52,8 @@ private: explicit AddressArbiter(KernelSystem& kernel); ~AddressArbiter() override; + KernelSystem& kernel; + /// Puts the thread to wait on the specified arbitration address under this address arbiter. void WaitThread(SharedPtr thread, VAddr wait_address); diff --git a/src/core/hle/kernel/hle_ipc.cpp b/src/core/hle/kernel/hle_ipc.cpp index a72d33dd9..746da245e 100644 --- a/src/core/hle/kernel/hle_ipc.cpp +++ b/src/core/hle/kernel/hle_ipc.cpp @@ -48,12 +48,13 @@ SharedPtr HLERequestContext::SleepClientThread(SharedPtr thread, // the translation might need to read from it in order to retrieve the StaticBuffer // target addresses. std::array cmd_buff; - Memory::ReadBlock(*process, thread->GetCommandBufferAddress(), cmd_buff.data(), - cmd_buff.size() * sizeof(u32)); + Memory::MemorySystem& memory = Core::System::GetInstance().Memory(); + memory.ReadBlock(*process, thread->GetCommandBufferAddress(), cmd_buff.data(), + cmd_buff.size() * sizeof(u32)); context.WriteToOutgoingCommandBuffer(cmd_buff.data(), *process); // Copy the translated command buffer back into the thread's command buffer area. - Memory::WriteBlock(*process, thread->GetCommandBufferAddress(), cmd_buff.data(), - cmd_buff.size() * sizeof(u32)); + memory.WriteBlock(*process, thread->GetCommandBufferAddress(), cmd_buff.data(), + cmd_buff.size() * sizeof(u32)); }; auto event = Core::System::GetInstance().Kernel().CreateEvent(Kernel::ResetType::OneShot, @@ -142,7 +143,8 @@ ResultCode HLERequestContext::PopulateFromIncomingCommandBuffer(const u32_le* sr // Copy the input buffer into our own vector and store it. std::vector data(buffer_info.size); - Memory::ReadBlock(src_process, source_address, data.data(), data.size()); + Core::System::GetInstance().Memory().ReadBlock(src_process, source_address, data.data(), + data.size()); AddStaticBuffer(buffer_info.buffer_id, std::move(data)); cmd_buf[i++] = source_address; @@ -209,7 +211,8 @@ ResultCode HLERequestContext::WriteToOutgoingCommandBuffer(u32_le* dst_cmdbuf, ASSERT_MSG(target_descriptor.size >= data.size(), "Static buffer data is too big"); - Memory::WriteBlock(dst_process, target_address, data.data(), data.size()); + Core::System::GetInstance().Memory().WriteBlock(dst_process, target_address, + data.data(), data.size()); dst_cmdbuf[i++] = target_address; break; @@ -242,13 +245,15 @@ MappedBuffer::MappedBuffer(const Process& process, u32 descriptor, VAddr address void MappedBuffer::Read(void* dest_buffer, std::size_t offset, std::size_t size) { ASSERT(perms & IPC::R); ASSERT(offset + size <= this->size); - Memory::ReadBlock(*process, address + static_cast(offset), dest_buffer, size); + Core::System::GetInstance().Memory().ReadBlock(*process, address + static_cast(offset), + dest_buffer, size); } void MappedBuffer::Write(const void* src_buffer, std::size_t offset, std::size_t size) { ASSERT(perms & IPC::W); ASSERT(offset + size <= this->size); - Memory::WriteBlock(*process, address + static_cast(offset), src_buffer, size); + Core::System::GetInstance().Memory().WriteBlock(*process, address + static_cast(offset), + src_buffer, size); } } // namespace Kernel diff --git a/src/core/hle/kernel/ipc.cpp b/src/core/hle/kernel/ipc.cpp index 7a59f0301..7eb16ba9e 100644 --- a/src/core/hle/kernel/ipc.cpp +++ b/src/core/hle/kernel/ipc.cpp @@ -4,6 +4,7 @@ #include #include "common/alignment.h" +#include "core/core.h" #include "core/hle/ipc.h" #include "core/hle/kernel/handle_table.h" #include "core/hle/kernel/ipc.h" @@ -19,13 +20,13 @@ ResultCode TranslateCommandBuffer(SharedPtr src_thread, SharedPtr& mapped_buffer_context, bool reply) { - + Memory::MemorySystem& memory = Core::System::GetInstance().Memory(); auto& src_process = src_thread->owner_process; auto& dst_process = dst_thread->owner_process; IPC::Header header; // TODO(Subv): Replace by Memory::Read32 when possible. - Memory::ReadBlock(*src_process, src_address, &header.raw, sizeof(header.raw)); + memory.ReadBlock(*src_process, src_address, &header.raw, sizeof(header.raw)); std::size_t untranslated_size = 1u + header.normal_params_size; std::size_t command_size = untranslated_size + header.translate_params_size; @@ -34,7 +35,7 @@ ResultCode TranslateCommandBuffer(SharedPtr src_thread, SharedPtr cmd_buf; - Memory::ReadBlock(*src_process, src_address, cmd_buf.data(), command_size * sizeof(u32)); + memory.ReadBlock(*src_process, src_address, cmd_buf.data(), command_size * sizeof(u32)); std::size_t i = untranslated_size; while (i < command_size) { @@ -90,7 +91,7 @@ ResultCode TranslateCommandBuffer(SharedPtr src_thread, SharedPtr data(bufferInfo.size); - Memory::ReadBlock(*src_process, static_buffer_src_address, data.data(), data.size()); + memory.ReadBlock(*src_process, static_buffer_src_address, data.data(), data.size()); // Grab the address that the target thread set up to receive the response static buffer // and write our data there. The static buffers area is located right after the command @@ -106,15 +107,15 @@ ResultCode TranslateCommandBuffer(SharedPtr src_thread, SharedPtr= data.size(), "Static buffer data is too big"); - Memory::WriteBlock(*dst_process, target_buffer.address, data.data(), data.size()); + memory.WriteBlock(*dst_process, target_buffer.address, data.data(), data.size()); cmd_buf[i++] = target_buffer.address; break; @@ -153,8 +154,8 @@ ResultCode TranslateCommandBuffer(SharedPtr src_thread, SharedPtrtarget_address, - found->source_address, size); + memory.CopyBlock(*src_process, *dst_process, found->target_address, + found->source_address, size); } VAddr prev_reserve = page_start - Memory::PAGE_SIZE; @@ -187,7 +188,7 @@ ResultCode TranslateCommandBuffer(SharedPtr src_thread, SharedPtr(num_pages * Memory::PAGE_SIZE); - Memory::ReadBlock(*src_process, source_address, buffer.get() + page_offset, size); + memory.ReadBlock(*src_process, source_address, buffer.get() + page_offset, size); // Map the page(s) into the target process' address space. target_address = @@ -215,7 +216,7 @@ ResultCode TranslateCommandBuffer(SharedPtr src_thread, SharedPtr(*this); - thread_manager = std::make_unique(); + thread_manager = std::make_unique(*this); timer_manager = std::make_unique(); } diff --git a/src/core/hle/kernel/kernel.h b/src/core/hle/kernel/kernel.h index cf6e95fe4..0a4aefec0 100644 --- a/src/core/hle/kernel/kernel.h +++ b/src/core/hle/kernel/kernel.h @@ -23,6 +23,10 @@ namespace SharedPage { class Handler; } +namespace Memory { +class MemorySystem; +} + namespace Kernel { class AddressArbiter; @@ -42,6 +46,7 @@ class SharedMemory; class ThreadManager; class TimerManager; class VMManager; +struct AddressMapping; enum class ResetType { OneShot, @@ -73,7 +78,7 @@ using SharedPtr = boost::intrusive_ptr; class KernelSystem { public: - explicit KernelSystem(u32 system_mode); + explicit KernelSystem(Memory::MemorySystem& memory, u32 system_mode); ~KernelSystem(); /** @@ -212,6 +217,8 @@ public: MemoryRegionInfo* GetMemoryRegion(MemoryRegion region); + void HandleSpecialMapping(VMManager& address_space, const AddressMapping& mapping); + std::array memory_regions; /// Adds a port to the named port table @@ -220,6 +227,8 @@ public: /// Map of named ports managed by the kernel, which can be retrieved using the ConnectToPort std::unordered_map> named_ports; + Memory::MemorySystem& memory; + private: void MemoryInit(u32 mem_type); diff --git a/src/core/hle/kernel/memory.cpp b/src/core/hle/kernel/memory.cpp index b53c273fe..c2d4d3053 100644 --- a/src/core/hle/kernel/memory.cpp +++ b/src/core/hle/kernel/memory.cpp @@ -83,7 +83,7 @@ MemoryRegionInfo* KernelSystem::GetMemoryRegion(MemoryRegion region) { } } -void HandleSpecialMapping(VMManager& address_space, const AddressMapping& mapping) { +void KernelSystem::HandleSpecialMapping(VMManager& address_space, const AddressMapping& mapping) { using namespace Memory; struct MemoryArea { @@ -128,7 +128,7 @@ void HandleSpecialMapping(VMManager& address_space, const AddressMapping& mappin return; } - u8* target_pointer = Memory::GetPhysicalPointer(area->paddr_base + offset_into_region); + u8* target_pointer = memory.GetPhysicalPointer(area->paddr_base + offset_into_region); // TODO(yuriks): This flag seems to have some other effect, but it's unknown what MemoryState memory_state = mapping.unk_flag ? MemoryState::Static : MemoryState::IO; diff --git a/src/core/hle/kernel/memory.h b/src/core/hle/kernel/memory.h index 67512df79..bb4e174f7 100644 --- a/src/core/hle/kernel/memory.h +++ b/src/core/hle/kernel/memory.h @@ -62,6 +62,4 @@ struct MemoryRegionInfo { void Free(u32 offset, u32 size); }; -void HandleSpecialMapping(VMManager& address_space, const AddressMapping& mapping); - } // namespace Kernel diff --git a/src/core/hle/kernel/process.cpp b/src/core/hle/kernel/process.cpp index 235d14043..a3b8b0d9c 100644 --- a/src/core/hle/kernel/process.cpp +++ b/src/core/hle/kernel/process.cpp @@ -120,8 +120,8 @@ void Process::Run(s32 main_thread_priority, u32 stack_size) { auto MapSegment = [&](CodeSet::Segment& segment, VMAPermission permissions, MemoryState memory_state) { HeapAllocate(segment.addr, segment.size, permissions, memory_state, true); - Memory::WriteBlock(*this, segment.addr, codeset->memory->data() + segment.offset, - segment.size); + kernel.memory.WriteBlock(*this, segment.addr, codeset->memory->data() + segment.offset, + segment.size); }; // Map CodeSet segments @@ -136,7 +136,7 @@ void Process::Run(s32 main_thread_priority, u32 stack_size) { // Map special address mappings kernel.MapSharedPages(vm_manager); for (const auto& mapping : address_mappings) { - HandleSpecialMapping(vm_manager, mapping); + kernel.HandleSpecialMapping(vm_manager, mapping); } status = ProcessStatus::Running; @@ -188,10 +188,11 @@ ResultVal Process::HeapAllocate(VAddr target, u32 size, VMAPermission per u32 interval_size = interval.upper() - interval.lower(); LOG_DEBUG(Kernel, "Allocated FCRAM region lower={:08X}, upper={:08X}", interval.lower(), interval.upper()); - std::fill(Memory::fcram.begin() + interval.lower(), - Memory::fcram.begin() + interval.upper(), 0); - auto vma = vm_manager.MapBackingMemory( - interval_target, Memory::fcram.data() + interval.lower(), interval_size, memory_state); + std::fill(kernel.memory.GetFCRAMPointer(interval.lower()), + kernel.memory.GetFCRAMPointer(interval.upper()), 0); + auto vma = vm_manager.MapBackingMemory(interval_target, + kernel.memory.GetFCRAMPointer(interval.lower()), + interval_size, memory_state); ASSERT(vma.Succeeded()); vm_manager.Reprotect(vma.Unwrap(), perms); interval_target += interval_size; @@ -218,7 +219,7 @@ ResultCode Process::HeapFree(VAddr target, u32 size) { // Free heaps block by block CASCADE_RESULT(auto backing_blocks, vm_manager.GetBackingBlocksForRange(target, size)); for (const auto [backing_memory, block_size] : backing_blocks) { - memory_region->Free(Memory::GetFCRAMOffset(backing_memory), block_size); + memory_region->Free(kernel.memory.GetFCRAMOffset(backing_memory), block_size); } ResultCode result = vm_manager.UnmapRange(target, size); @@ -262,7 +263,7 @@ ResultVal Process::LinearAllocate(VAddr target, u32 size, VMAPermission p } } - u8* backing_memory = Memory::fcram.data() + physical_offset; + u8* backing_memory = kernel.memory.GetFCRAMPointer(physical_offset); std::fill(backing_memory, backing_memory + size, 0); auto vma = vm_manager.MapBackingMemory(target, backing_memory, size, MemoryState::Continuous); diff --git a/src/core/hle/kernel/shared_memory.cpp b/src/core/hle/kernel/shared_memory.cpp index f1acca74d..3e1e6d9f5 100644 --- a/src/core/hle/kernel/shared_memory.cpp +++ b/src/core/hle/kernel/shared_memory.cpp @@ -43,8 +43,8 @@ ResultVal> KernelSystem::CreateSharedMemory( ASSERT_MSG(offset, "Not enough space in region to allocate shared memory!"); - std::fill(Memory::fcram.data() + *offset, Memory::fcram.data() + *offset + size, 0); - shared_memory->backing_blocks = {{Memory::fcram.data() + *offset, size}}; + std::fill(memory.GetFCRAMPointer(*offset), memory.GetFCRAMPointer(*offset + size), 0); + shared_memory->backing_blocks = {{memory.GetFCRAMPointer(*offset), size}}; shared_memory->holding_memory += MemoryRegionInfo::Interval(*offset, *offset + size); shared_memory->linear_heap_phys_offset = *offset; @@ -86,9 +86,9 @@ SharedPtr KernelSystem::CreateSharedMemoryForApplet( shared_memory->other_permissions = other_permissions; for (const auto& interval : backing_blocks) { shared_memory->backing_blocks.push_back( - {Memory::fcram.data() + interval.lower(), interval.upper() - interval.lower()}); - std::fill(Memory::fcram.data() + interval.lower(), Memory::fcram.data() + interval.upper(), - 0); + {memory.GetFCRAMPointer(interval.lower()), interval.upper() - interval.lower()}); + std::fill(memory.GetFCRAMPointer(interval.lower()), + memory.GetFCRAMPointer(interval.upper()), 0); } shared_memory->base_address = Memory::HEAP_VADDR + offset; diff --git a/src/core/hle/kernel/svc.cpp b/src/core/hle/kernel/svc.cpp index 465ba76a5..f28717570 100644 --- a/src/core/hle/kernel/svc.cpp +++ b/src/core/hle/kernel/svc.cpp @@ -105,6 +105,7 @@ public: private: Core::System& system; Kernel::KernelSystem& kernel; + Memory::MemorySystem& memory; friend class SVCWrapper; @@ -351,7 +352,7 @@ ResultCode SVC::ConnectToPort(Handle* out_handle, VAddr port_name_address) { static constexpr std::size_t PortNameMaxLength = 11; // Read 1 char beyond the max allowed port name to detect names that are too long. - std::string port_name = Memory::ReadCString(port_name_address, PortNameMaxLength + 1); + std::string port_name = memory.ReadCString(port_name_address, PortNameMaxLength + 1); if (port_name.size() > PortNameMaxLength) return ERR_PORT_NAME_TOO_LONG; @@ -466,7 +467,7 @@ ResultCode SVC::WaitSynchronizationN(s32* out, VAddr handles_address, s32 handle std::vector objects(handle_count); for (int i = 0; i < handle_count; ++i) { - Handle handle = Memory::Read32(handles_address + i * sizeof(Handle)); + Handle handle = memory.Read32(handles_address + i * sizeof(Handle)); auto object = kernel.GetCurrentProcess()->handle_table.Get(handle); if (object == nullptr) return ERR_INVALID_HANDLE; @@ -635,7 +636,7 @@ ResultCode SVC::ReplyAndReceive(s32* index, VAddr handles_address, s32 handle_co SharedPtr current_process = kernel.GetCurrentProcess(); for (int i = 0; i < handle_count; ++i) { - Handle handle = Memory::Read32(handles_address + i * sizeof(Handle)); + Handle handle = memory.Read32(handles_address + i * sizeof(Handle)); auto object = current_process->handle_table.Get(handle); if (object == nullptr) return ERR_INVALID_HANDLE; @@ -645,7 +646,7 @@ ResultCode SVC::ReplyAndReceive(s32* index, VAddr handles_address, s32 handle_co // We are also sending a command reply. // Do not send a reply if the command id in the command buffer is 0xFFFF. Thread* thread = kernel.GetThreadManager().GetCurrentThread(); - u32 cmd_buff_header = Memory::Read32(thread->GetCommandBufferAddress()); + u32 cmd_buff_header = memory.Read32(thread->GetCommandBufferAddress()); IPC::Header header{cmd_buff_header}; if (reply_target != 0 && header.command_id != 0xFFFF) { auto session = current_process->handle_table.Get(reply_target); @@ -801,7 +802,7 @@ void SVC::OutputDebugString(VAddr address, s32 len) { } std::string string(len, ' '); - Memory::ReadBlock(*kernel.GetCurrentProcess(), address, string.data(), len); + memory.ReadBlock(*kernel.GetCurrentProcess(), address, string.data(), len); LOG_DEBUG(Debug_Emulated, "{}", string); } @@ -831,9 +832,9 @@ ResultCode SVC::GetResourceLimitCurrentValues(VAddr values, Handle resource_limi return ERR_INVALID_HANDLE; for (unsigned int i = 0; i < name_count; ++i) { - u32 name = Memory::Read32(names + i * sizeof(u32)); + u32 name = memory.Read32(names + i * sizeof(u32)); s64 value = resource_limit->GetCurrentResourceValue(name); - Memory::Write64(values + i * sizeof(u64), value); + memory.Write64(values + i * sizeof(u64), value); } return RESULT_SUCCESS; @@ -851,9 +852,9 @@ ResultCode SVC::GetResourceLimitLimitValues(VAddr values, Handle resource_limit_ return ERR_INVALID_HANDLE; for (unsigned int i = 0; i < name_count; ++i) { - u32 name = Memory::Read32(names + i * sizeof(u32)); + u32 name = memory.Read32(names + i * sizeof(u32)); s64 value = resource_limit->GetMaxResourceValue(name); - Memory::Write64(values + i * sizeof(u64), value); + memory.Write64(values + i * sizeof(u64), value); } return RESULT_SUCCESS; @@ -1584,7 +1585,7 @@ void SVC::CallSVC(u32 immediate) { } } -SVC::SVC(Core::System& system) : system(system), kernel(system.Kernel()) {} +SVC::SVC(Core::System& system) : system(system), kernel(system.Kernel()), memory(system.Memory()) {} u32 SVC::GetReg(std::size_t n) { return system.CPU().GetReg(static_cast(n)); diff --git a/src/core/hle/kernel/thread.cpp b/src/core/hle/kernel/thread.cpp index 7f1749a5f..4f4c9b174 100644 --- a/src/core/hle/kernel/thread.cpp +++ b/src/core/hle/kernel/thread.cpp @@ -104,7 +104,7 @@ void ThreadManager::SwitchContext(Thread* new_thread) { // Cancel any outstanding wakeup events for this thread timing.UnscheduleEvent(ThreadWakeupEventType, new_thread->thread_id); - auto previous_process = Core::System::GetInstance().Kernel().GetCurrentProcess(); + auto previous_process = kernel.GetCurrentProcess(); current_thread = new_thread; @@ -112,8 +112,9 @@ void ThreadManager::SwitchContext(Thread* new_thread) { new_thread->status = ThreadStatus::Running; if (previous_process != current_thread->owner_process) { - Core::System::GetInstance().Kernel().SetCurrentProcess(current_thread->owner_process); - SetCurrentPageTable(¤t_thread->owner_process->vm_manager.page_table); + kernel.SetCurrentProcess(current_thread->owner_process); + kernel.memory.SetCurrentPageTable( + ¤t_thread->owner_process->vm_manager.page_table); } Core::CPU().LoadContext(new_thread->context); @@ -354,7 +355,7 @@ ResultVal> KernelSystem::CreateThread(std::string name, VAddr // Map the page to the current process' address space. vm_manager.MapBackingMemory(Memory::TLS_AREA_VADDR + available_page * Memory::PAGE_SIZE, - Memory::fcram.data() + *offset, Memory::PAGE_SIZE, + memory.GetFCRAMPointer(*offset), Memory::PAGE_SIZE, MemoryState::Locked); } @@ -363,7 +364,7 @@ ResultVal> KernelSystem::CreateThread(std::string name, VAddr thread->tls_address = Memory::TLS_AREA_VADDR + available_page * Memory::PAGE_SIZE + available_slot * Memory::TLS_ENTRY_SIZE; - Memory::ZeroBlock(owner_process, thread->tls_address, Memory::TLS_ENTRY_SIZE); + memory.ZeroBlock(owner_process, thread->tls_address, Memory::TLS_ENTRY_SIZE); // TODO(peachum): move to ScheduleThread() when scheduler is added so selected core is used // to initialize the context @@ -460,7 +461,7 @@ VAddr Thread::GetCommandBufferAddress() const { return GetTLSAddress() + CommandHeaderOffset; } -ThreadManager::ThreadManager() { +ThreadManager::ThreadManager(Kernel::KernelSystem& kernel) : kernel(kernel) { ThreadWakeupEventType = Core::System::GetInstance().CoreTiming().RegisterEvent( "ThreadWakeupCallback", [this](u64 thread_id, s64 cycle_late) { ThreadWakeupCallback(thread_id, cycle_late); }); diff --git a/src/core/hle/kernel/thread.h b/src/core/hle/kernel/thread.h index acb75a374..e0af473e0 100644 --- a/src/core/hle/kernel/thread.h +++ b/src/core/hle/kernel/thread.h @@ -57,7 +57,7 @@ enum class ThreadWakeupReason { class ThreadManager { public: - ThreadManager(); + explicit ThreadManager(Kernel::KernelSystem& kernel); ~ThreadManager(); /** @@ -121,6 +121,8 @@ private: */ void ThreadWakeupCallback(u64 thread_id, s64 cycles_late); + Kernel::KernelSystem& kernel; + u32 next_thread_id = 1; SharedPtr current_thread; Common::ThreadQueueList ready_queue; diff --git a/src/core/hle/service/cam/cam.cpp b/src/core/hle/service/cam/cam.cpp index 78d2e268e..bf1bab8c0 100644 --- a/src/core/hle/service/cam/cam.cpp +++ b/src/core/hle/service/cam/cam.cpp @@ -113,7 +113,7 @@ void Module::CompletionEventCallBack(u64 port_id, s64) { if (copy_length <= 0) { break; } - Memory::WriteBlock(*port.dest_process, dest_ptr, src_ptr, copy_length); + system.Memory().WriteBlock(*port.dest_process, dest_ptr, src_ptr, copy_length); dest_ptr += copy_length; dest_size_left -= copy_length; src_ptr += original_width; @@ -125,8 +125,8 @@ void Module::CompletionEventCallBack(u64 port_id, s64) { LOG_ERROR(Service_CAM, "The destination size ({}) doesn't match the source ({})!", port.dest_size, buffer_size); } - Memory::WriteBlock(*port.dest_process, port.dest, buffer.data(), - std::min(port.dest_size, buffer_size)); + system.Memory().WriteBlock(*port.dest_process, port.dest, buffer.data(), + std::min(port.dest_size, buffer_size)); } port.is_receiving = false; diff --git a/src/core/hle/service/gsp/gsp_gpu.cpp b/src/core/hle/service/gsp/gsp_gpu.cpp index 9445aa3c3..50bb30bb9 100644 --- a/src/core/hle/service/gsp/gsp_gpu.cpp +++ b/src/core/hle/service/gsp/gsp_gpu.cpp @@ -491,6 +491,7 @@ static void ExecuteCommand(const Command& command, u32 thread_id) { // GX request DMA - typically used for copying memory from GSP heap to VRAM case CommandId::REQUEST_DMA: { MICROPROFILE_SCOPE(GPU_GSP_DMA); + Memory::MemorySystem& memory = Core::System::GetInstance().Memory(); // TODO: Consider attempting rasterizer-accelerated surface blit if that usage is ever // possible/likely @@ -502,9 +503,9 @@ static void ExecuteCommand(const Command& command, u32 thread_id) { // TODO(Subv): These memory accesses should not go through the application's memory mapping. // They should go through the GSP module's memory mapping. - Memory::CopyBlock(*Core::System::GetInstance().Kernel().GetCurrentProcess(), - command.dma_request.dest_address, command.dma_request.source_address, - command.dma_request.size); + memory.CopyBlock(*Core::System::GetInstance().Kernel().GetCurrentProcess(), + command.dma_request.dest_address, command.dma_request.source_address, + command.dma_request.size); SignalInterrupt(InterruptId::DMA); break; } diff --git a/src/core/hle/service/ldr_ro/cro_helper.cpp b/src/core/hle/service/ldr_ro/cro_helper.cpp index 9e6635a69..755614662 100644 --- a/src/core/hle/service/ldr_ro/cro_helper.cpp +++ b/src/core/hle/service/ldr_ro/cro_helper.cpp @@ -55,7 +55,7 @@ VAddr CROHelper::SegmentTagToAddress(SegmentTag segment_tag) const { return 0; SegmentEntry entry; - GetEntry(segment_tag.segment_index, entry); + GetEntry(memory, segment_tag.segment_index, entry); if (segment_tag.offset_into_segment >= entry.size) return 0; @@ -71,11 +71,11 @@ ResultCode CROHelper::ApplyRelocation(VAddr target_address, RelocationType reloc break; case RelocationType::AbsoluteAddress: case RelocationType::AbsoluteAddress2: - Memory::Write32(target_address, symbol_address + addend); + memory.Write32(target_address, symbol_address + addend); Core::CPU().InvalidateCacheRange(target_address, sizeof(u32)); break; case RelocationType::RelativeAddress: - Memory::Write32(target_address, symbol_address + addend - target_future_address); + memory.Write32(target_address, symbol_address + addend - target_future_address); Core::CPU().InvalidateCacheRange(target_address, sizeof(u32)); break; case RelocationType::ThumbBranch: @@ -98,7 +98,7 @@ ResultCode CROHelper::ClearRelocation(VAddr target_address, RelocationType reloc case RelocationType::AbsoluteAddress: case RelocationType::AbsoluteAddress2: case RelocationType::RelativeAddress: - Memory::Write32(target_address, 0); + memory.Write32(target_address, 0); Core::CPU().InvalidateCacheRange(target_address, sizeof(u32)); break; case RelocationType::ThumbBranch: @@ -121,7 +121,7 @@ ResultCode CROHelper::ApplyRelocationBatch(VAddr batch, u32 symbol_address, bool VAddr relocation_address = batch; while (true) { RelocationEntry relocation; - Memory::ReadBlock(process, relocation_address, &relocation, sizeof(RelocationEntry)); + memory.ReadBlock(process, relocation_address, &relocation, sizeof(RelocationEntry)); VAddr relocation_target = SegmentTagToAddress(relocation.target_position); if (relocation_target == 0) { @@ -142,9 +142,9 @@ ResultCode CROHelper::ApplyRelocationBatch(VAddr batch, u32 symbol_address, bool } RelocationEntry relocation; - Memory::ReadBlock(process, batch, &relocation, sizeof(RelocationEntry)); + memory.ReadBlock(process, batch, &relocation, sizeof(RelocationEntry)); relocation.is_batch_resolved = reset ? 0 : 1; - Memory::WriteBlock(process, batch, &relocation, sizeof(RelocationEntry)); + memory.WriteBlock(process, batch, &relocation, sizeof(RelocationEntry)); return RESULT_SUCCESS; } @@ -154,13 +154,13 @@ VAddr CROHelper::FindExportNamedSymbol(const std::string& name) const { std::size_t len = name.size(); ExportTreeEntry entry; - GetEntry(0, entry); + GetEntry(memory, 0, entry); ExportTreeEntry::Child next; next.raw = entry.left.raw; u32 found_id; while (true) { - GetEntry(next.next_index, entry); + GetEntry(memory, next.next_index, entry); if (next.is_end) { found_id = entry.export_table_index; @@ -186,9 +186,9 @@ VAddr CROHelper::FindExportNamedSymbol(const std::string& name) const { u32 export_strings_size = GetField(ExportStringsSize); ExportNamedSymbolEntry symbol_entry; - GetEntry(found_id, symbol_entry); + GetEntry(memory, found_id, symbol_entry); - if (Memory::ReadCString(symbol_entry.name_offset, export_strings_size) != name) + if (memory.ReadCString(symbol_entry.name_offset, export_strings_size) != name) return 0; return SegmentTagToAddress(symbol_entry.symbol_position); @@ -279,7 +279,7 @@ ResultVal CROHelper::RebaseSegmentTable(u32 cro_size, VAddr data_segment_ u32 segment_num = GetField(SegmentNum); for (u32 i = 0; i < segment_num; ++i) { SegmentEntry segment; - GetEntry(i, segment); + GetEntry(memory, i, segment); if (segment.type == SegmentType::Data) { if (segment.size != 0) { if (segment.size > data_segment_size) @@ -298,7 +298,7 @@ ResultVal CROHelper::RebaseSegmentTable(u32 cro_size, VAddr data_segment_ if (segment.offset > module_address + cro_size) return CROFormatError(0x19); } - SetEntry(i, segment); + SetEntry(memory, i, segment); } return MakeResult(prev_data_segment + module_address); } @@ -310,7 +310,7 @@ ResultCode CROHelper::RebaseExportNamedSymbolTable() { u32 export_named_symbol_num = GetField(ExportNamedSymbolNum); for (u32 i = 0; i < export_named_symbol_num; ++i) { ExportNamedSymbolEntry entry; - GetEntry(i, entry); + GetEntry(memory, i, entry); if (entry.name_offset != 0) { entry.name_offset += module_address; @@ -320,7 +320,7 @@ ResultCode CROHelper::RebaseExportNamedSymbolTable() { } } - SetEntry(i, entry); + SetEntry(memory, i, entry); } return RESULT_SUCCESS; } @@ -329,7 +329,7 @@ ResultCode CROHelper::VerifyExportTreeTable() const { u32 tree_num = GetField(ExportTreeNum); for (u32 i = 0; i < tree_num; ++i) { ExportTreeEntry entry; - GetEntry(i, entry); + GetEntry(memory, i, entry); if (entry.left.next_index >= tree_num || entry.right.next_index >= tree_num) { return CROFormatError(0x11); @@ -353,7 +353,7 @@ ResultCode CROHelper::RebaseImportModuleTable() { u32 module_num = GetField(ImportModuleNum); for (u32 i = 0; i < module_num; ++i) { ImportModuleEntry entry; - GetEntry(i, entry); + GetEntry(memory, i, entry); if (entry.name_offset != 0) { entry.name_offset += module_address; @@ -379,7 +379,7 @@ ResultCode CROHelper::RebaseImportModuleTable() { } } - SetEntry(i, entry); + SetEntry(memory, i, entry); } return RESULT_SUCCESS; } @@ -395,7 +395,7 @@ ResultCode CROHelper::RebaseImportNamedSymbolTable() { u32 num = GetField(ImportNamedSymbolNum); for (u32 i = 0; i < num; ++i) { ImportNamedSymbolEntry entry; - GetEntry(i, entry); + GetEntry(memory, i, entry); if (entry.name_offset != 0) { entry.name_offset += module_address; @@ -413,7 +413,7 @@ ResultCode CROHelper::RebaseImportNamedSymbolTable() { } } - SetEntry(i, entry); + SetEntry(memory, i, entry); } return RESULT_SUCCESS; } @@ -427,7 +427,7 @@ ResultCode CROHelper::RebaseImportIndexedSymbolTable() { u32 num = GetField(ImportIndexedSymbolNum); for (u32 i = 0; i < num; ++i) { ImportIndexedSymbolEntry entry; - GetEntry(i, entry); + GetEntry(memory, i, entry); if (entry.relocation_batch_offset != 0) { entry.relocation_batch_offset += module_address; @@ -437,7 +437,7 @@ ResultCode CROHelper::RebaseImportIndexedSymbolTable() { } } - SetEntry(i, entry); + SetEntry(memory, i, entry); } return RESULT_SUCCESS; } @@ -451,7 +451,7 @@ ResultCode CROHelper::RebaseImportAnonymousSymbolTable() { u32 num = GetField(ImportAnonymousSymbolNum); for (u32 i = 0; i < num; ++i) { ImportAnonymousSymbolEntry entry; - GetEntry(i, entry); + GetEntry(memory, i, entry); if (entry.relocation_batch_offset != 0) { entry.relocation_batch_offset += module_address; @@ -461,7 +461,7 @@ ResultCode CROHelper::RebaseImportAnonymousSymbolTable() { } } - SetEntry(i, entry); + SetEntry(memory, i, entry); } return RESULT_SUCCESS; } @@ -476,14 +476,14 @@ ResultCode CROHelper::ResetExternalRelocations() { ExternalRelocationEntry relocation; // Verifies that the last relocation is the end of a batch - GetEntry(external_relocation_num - 1, relocation); + GetEntry(memory, external_relocation_num - 1, relocation); if (!relocation.is_batch_end) { return CROFormatError(0x12); } bool batch_begin = true; for (u32 i = 0; i < external_relocation_num; ++i) { - GetEntry(i, relocation); + GetEntry(memory, i, relocation); VAddr relocation_target = SegmentTagToAddress(relocation.target_position); if (relocation_target == 0) { @@ -500,7 +500,7 @@ ResultCode CROHelper::ResetExternalRelocations() { if (batch_begin) { // resets to unresolved state relocation.is_batch_resolved = 0; - SetEntry(i, relocation); + SetEntry(memory, i, relocation); } // if current is an end, then the next is a beginning @@ -516,7 +516,7 @@ ResultCode CROHelper::ClearExternalRelocations() { bool batch_begin = true; for (u32 i = 0; i < external_relocation_num; ++i) { - GetEntry(i, relocation); + GetEntry(memory, i, relocation); VAddr relocation_target = SegmentTagToAddress(relocation.target_position); if (relocation_target == 0) { @@ -532,7 +532,7 @@ ResultCode CROHelper::ClearExternalRelocations() { if (batch_begin) { // resets to unresolved state relocation.is_batch_resolved = 0; - SetEntry(i, relocation); + SetEntry(memory, i, relocation); } // if current is an end, then the next is a beginning @@ -548,13 +548,13 @@ ResultCode CROHelper::ApplyStaticAnonymousSymbolToCRS(VAddr crs_address) { static_relocation_table_offset + GetField(StaticRelocationNum) * sizeof(StaticRelocationEntry); - CROHelper crs(crs_address, process); + CROHelper crs(crs_address, process, memory); u32 offset_export_num = GetField(StaticAnonymousSymbolNum); LOG_INFO(Service_LDR, "CRO \"{}\" exports {} static anonymous symbols", ModuleName(), offset_export_num); for (u32 i = 0; i < offset_export_num; ++i) { StaticAnonymousSymbolEntry entry; - GetEntry(i, entry); + GetEntry(memory, i, entry); u32 batch_address = entry.relocation_batch_offset + module_address; if (batch_address < static_relocation_table_offset || @@ -579,7 +579,7 @@ ResultCode CROHelper::ApplyInternalRelocations(u32 old_data_segment_address) { u32 internal_relocation_num = GetField(InternalRelocationNum); for (u32 i = 0; i < internal_relocation_num; ++i) { InternalRelocationEntry relocation; - GetEntry(i, relocation); + GetEntry(memory, i, relocation); VAddr target_addressB = SegmentTagToAddress(relocation.target_position); if (target_addressB == 0) { return CROFormatError(0x15); @@ -587,7 +587,7 @@ ResultCode CROHelper::ApplyInternalRelocations(u32 old_data_segment_address) { VAddr target_address; SegmentEntry target_segment; - GetEntry(relocation.target_position.segment_index, target_segment); + GetEntry(memory, relocation.target_position.segment_index, target_segment); if (target_segment.type == SegmentType::Data) { // If the relocation is to the .data segment, we need to relocate it in the old buffer @@ -602,7 +602,7 @@ ResultCode CROHelper::ApplyInternalRelocations(u32 old_data_segment_address) { } SegmentEntry symbol_segment; - GetEntry(relocation.symbol_segment, symbol_segment); + GetEntry(memory, relocation.symbol_segment, symbol_segment); LOG_TRACE(Service_LDR, "Internally relocates 0x{:08X} with 0x{:08X}", target_address, symbol_segment.offset); ResultCode result = ApplyRelocation(target_address, relocation.type, relocation.addend, @@ -619,7 +619,7 @@ ResultCode CROHelper::ClearInternalRelocations() { u32 internal_relocation_num = GetField(InternalRelocationNum); for (u32 i = 0; i < internal_relocation_num; ++i) { InternalRelocationEntry relocation; - GetEntry(i, relocation); + GetEntry(memory, i, relocation); VAddr target_address = SegmentTagToAddress(relocation.target_position); if (target_address == 0) { @@ -639,13 +639,13 @@ void CROHelper::UnrebaseImportAnonymousSymbolTable() { u32 num = GetField(ImportAnonymousSymbolNum); for (u32 i = 0; i < num; ++i) { ImportAnonymousSymbolEntry entry; - GetEntry(i, entry); + GetEntry(memory, i, entry); if (entry.relocation_batch_offset != 0) { entry.relocation_batch_offset -= module_address; } - SetEntry(i, entry); + SetEntry(memory, i, entry); } } @@ -653,13 +653,13 @@ void CROHelper::UnrebaseImportIndexedSymbolTable() { u32 num = GetField(ImportIndexedSymbolNum); for (u32 i = 0; i < num; ++i) { ImportIndexedSymbolEntry entry; - GetEntry(i, entry); + GetEntry(memory, i, entry); if (entry.relocation_batch_offset != 0) { entry.relocation_batch_offset -= module_address; } - SetEntry(i, entry); + SetEntry(memory, i, entry); } } @@ -667,7 +667,7 @@ void CROHelper::UnrebaseImportNamedSymbolTable() { u32 num = GetField(ImportNamedSymbolNum); for (u32 i = 0; i < num; ++i) { ImportNamedSymbolEntry entry; - GetEntry(i, entry); + GetEntry(memory, i, entry); if (entry.name_offset != 0) { entry.name_offset -= module_address; @@ -677,7 +677,7 @@ void CROHelper::UnrebaseImportNamedSymbolTable() { entry.relocation_batch_offset -= module_address; } - SetEntry(i, entry); + SetEntry(memory, i, entry); } } @@ -685,7 +685,7 @@ void CROHelper::UnrebaseImportModuleTable() { u32 module_num = GetField(ImportModuleNum); for (u32 i = 0; i < module_num; ++i) { ImportModuleEntry entry; - GetEntry(i, entry); + GetEntry(memory, i, entry); if (entry.name_offset != 0) { entry.name_offset -= module_address; @@ -699,7 +699,7 @@ void CROHelper::UnrebaseImportModuleTable() { entry.import_anonymous_symbol_table_offset -= module_address; } - SetEntry(i, entry); + SetEntry(memory, i, entry); } } @@ -707,13 +707,13 @@ void CROHelper::UnrebaseExportNamedSymbolTable() { u32 export_named_symbol_num = GetField(ExportNamedSymbolNum); for (u32 i = 0; i < export_named_symbol_num; ++i) { ExportNamedSymbolEntry entry; - GetEntry(i, entry); + GetEntry(memory, i, entry); if (entry.name_offset != 0) { entry.name_offset -= module_address; } - SetEntry(i, entry); + SetEntry(memory, i, entry); } } @@ -721,7 +721,7 @@ void CROHelper::UnrebaseSegmentTable() { u32 segment_num = GetField(SegmentNum); for (u32 i = 0; i < segment_num; ++i) { SegmentEntry segment; - GetEntry(i, segment); + GetEntry(memory, i, segment); if (segment.type == SegmentType::BSS) { segment.offset = 0; @@ -729,7 +729,7 @@ void CROHelper::UnrebaseSegmentTable() { segment.offset -= module_address; } - SetEntry(i, segment); + SetEntry(memory, i, segment); } } @@ -751,17 +751,17 @@ ResultCode CROHelper::ApplyImportNamedSymbol(VAddr crs_address) { u32 symbol_import_num = GetField(ImportNamedSymbolNum); for (u32 i = 0; i < symbol_import_num; ++i) { ImportNamedSymbolEntry entry; - GetEntry(i, entry); + GetEntry(memory, i, entry); VAddr relocation_addr = entry.relocation_batch_offset; ExternalRelocationEntry relocation_entry; - Memory::ReadBlock(process, relocation_addr, &relocation_entry, - sizeof(ExternalRelocationEntry)); + memory.ReadBlock(process, relocation_addr, &relocation_entry, + sizeof(ExternalRelocationEntry)); if (!relocation_entry.is_batch_resolved) { - ResultCode result = - ForEachAutoLinkCRO(process, crs_address, [&](CROHelper source) -> ResultVal { + ResultCode result = ForEachAutoLinkCRO( + process, memory, crs_address, [&](CROHelper source) -> ResultVal { std::string symbol_name = - Memory::ReadCString(entry.name_offset, import_strings_size); + memory.ReadCString(entry.name_offset, import_strings_size); u32 symbol_address = source.FindExportNamedSymbol(symbol_name); if (symbol_address != 0) { @@ -794,11 +794,11 @@ ResultCode CROHelper::ResetImportNamedSymbol() { u32 symbol_import_num = GetField(ImportNamedSymbolNum); for (u32 i = 0; i < symbol_import_num; ++i) { ImportNamedSymbolEntry entry; - GetEntry(i, entry); + GetEntry(memory, i, entry); VAddr relocation_addr = entry.relocation_batch_offset; ExternalRelocationEntry relocation_entry; - Memory::ReadBlock(process, relocation_addr, &relocation_entry, - sizeof(ExternalRelocationEntry)); + memory.ReadBlock(process, relocation_addr, &relocation_entry, + sizeof(ExternalRelocationEntry)); ResultCode result = ApplyRelocationBatch(relocation_addr, unresolved_symbol, true); if (result.IsError()) { @@ -815,11 +815,11 @@ ResultCode CROHelper::ResetImportIndexedSymbol() { u32 import_num = GetField(ImportIndexedSymbolNum); for (u32 i = 0; i < import_num; ++i) { ImportIndexedSymbolEntry entry; - GetEntry(i, entry); + GetEntry(memory, i, entry); VAddr relocation_addr = entry.relocation_batch_offset; ExternalRelocationEntry relocation_entry; - Memory::ReadBlock(process, relocation_addr, &relocation_entry, - sizeof(ExternalRelocationEntry)); + memory.ReadBlock(process, relocation_addr, &relocation_entry, + sizeof(ExternalRelocationEntry)); ResultCode result = ApplyRelocationBatch(relocation_addr, unresolved_symbol, true); if (result.IsError()) { @@ -836,11 +836,11 @@ ResultCode CROHelper::ResetImportAnonymousSymbol() { u32 import_num = GetField(ImportAnonymousSymbolNum); for (u32 i = 0; i < import_num; ++i) { ImportAnonymousSymbolEntry entry; - GetEntry(i, entry); + GetEntry(memory, i, entry); VAddr relocation_addr = entry.relocation_batch_offset; ExternalRelocationEntry relocation_entry; - Memory::ReadBlock(process, relocation_addr, &relocation_entry, - sizeof(ExternalRelocationEntry)); + memory.ReadBlock(process, relocation_addr, &relocation_entry, + sizeof(ExternalRelocationEntry)); ResultCode result = ApplyRelocationBatch(relocation_addr, unresolved_symbol, true); if (result.IsError()) { @@ -857,19 +857,19 @@ ResultCode CROHelper::ApplyModuleImport(VAddr crs_address) { u32 import_module_num = GetField(ImportModuleNum); for (u32 i = 0; i < import_module_num; ++i) { ImportModuleEntry entry; - GetEntry(i, entry); - std::string want_cro_name = Memory::ReadCString(entry.name_offset, import_strings_size); + GetEntry(memory, i, entry); + std::string want_cro_name = memory.ReadCString(entry.name_offset, import_strings_size); - ResultCode result = - ForEachAutoLinkCRO(process, crs_address, [&](CROHelper source) -> ResultVal { + ResultCode result = ForEachAutoLinkCRO( + process, memory, crs_address, [&](CROHelper source) -> ResultVal { if (want_cro_name == source.ModuleName()) { LOG_INFO(Service_LDR, "CRO \"{}\" imports {} indexed symbols from \"{}\"", ModuleName(), entry.import_indexed_symbol_num, source.ModuleName()); for (u32 j = 0; j < entry.import_indexed_symbol_num; ++j) { ImportIndexedSymbolEntry im; - entry.GetImportIndexedSymbolEntry(process, j, im); + entry.GetImportIndexedSymbolEntry(process, memory, j, im); ExportIndexedSymbolEntry ex; - source.GetEntry(im.index, ex); + source.GetEntry(memory, im.index, ex); u32 symbol_address = source.SegmentTagToAddress(ex.symbol_position); LOG_TRACE(Service_LDR, " Imports 0x{:08X}", symbol_address); ResultCode result = @@ -884,7 +884,7 @@ ResultCode CROHelper::ApplyModuleImport(VAddr crs_address) { ModuleName(), entry.import_anonymous_symbol_num, source.ModuleName()); for (u32 j = 0; j < entry.import_anonymous_symbol_num; ++j) { ImportAnonymousSymbolEntry im; - entry.GetImportAnonymousSymbolEntry(process, j, im); + entry.GetImportAnonymousSymbolEntry(process, memory, j, im); u32 symbol_address = source.SegmentTagToAddress(im.symbol_position); LOG_TRACE(Service_LDR, " Imports 0x{:08X}", symbol_address); ResultCode result = @@ -913,15 +913,15 @@ ResultCode CROHelper::ApplyExportNamedSymbol(CROHelper target) { u32 target_symbol_import_num = target.GetField(ImportNamedSymbolNum); for (u32 i = 0; i < target_symbol_import_num; ++i) { ImportNamedSymbolEntry entry; - target.GetEntry(i, entry); + target.GetEntry(memory, i, entry); VAddr relocation_addr = entry.relocation_batch_offset; ExternalRelocationEntry relocation_entry; - Memory::ReadBlock(process, relocation_addr, &relocation_entry, - sizeof(ExternalRelocationEntry)); + memory.ReadBlock(process, relocation_addr, &relocation_entry, + sizeof(ExternalRelocationEntry)); if (!relocation_entry.is_batch_resolved) { std::string symbol_name = - Memory::ReadCString(entry.name_offset, target_import_strings_size); + memory.ReadCString(entry.name_offset, target_import_strings_size); u32 symbol_address = FindExportNamedSymbol(symbol_name); if (symbol_address != 0) { LOG_TRACE(Service_LDR, " exports symbol \"{}\"", symbol_name); @@ -944,15 +944,15 @@ ResultCode CROHelper::ResetExportNamedSymbol(CROHelper target) { u32 target_symbol_import_num = target.GetField(ImportNamedSymbolNum); for (u32 i = 0; i < target_symbol_import_num; ++i) { ImportNamedSymbolEntry entry; - target.GetEntry(i, entry); + target.GetEntry(memory, i, entry); VAddr relocation_addr = entry.relocation_batch_offset; ExternalRelocationEntry relocation_entry; - Memory::ReadBlock(process, relocation_addr, &relocation_entry, - sizeof(ExternalRelocationEntry)); + memory.ReadBlock(process, relocation_addr, &relocation_entry, + sizeof(ExternalRelocationEntry)); if (relocation_entry.is_batch_resolved) { std::string symbol_name = - Memory::ReadCString(entry.name_offset, target_import_strings_size); + memory.ReadCString(entry.name_offset, target_import_strings_size); u32 symbol_address = FindExportNamedSymbol(symbol_name); if (symbol_address != 0) { LOG_TRACE(Service_LDR, " unexports symbol \"{}\"", symbol_name); @@ -974,18 +974,18 @@ ResultCode CROHelper::ApplyModuleExport(CROHelper target) { u32 target_import_module_num = target.GetField(ImportModuleNum); for (u32 i = 0; i < target_import_module_num; ++i) { ImportModuleEntry entry; - target.GetEntry(i, entry); + target.GetEntry(memory, i, entry); - if (Memory::ReadCString(entry.name_offset, target_import_string_size) != module_name) + if (memory.ReadCString(entry.name_offset, target_import_string_size) != module_name) continue; LOG_INFO(Service_LDR, "CRO \"{}\" exports {} indexed symbols to \"{}\"", module_name, entry.import_indexed_symbol_num, target.ModuleName()); for (u32 j = 0; j < entry.import_indexed_symbol_num; ++j) { ImportIndexedSymbolEntry im; - entry.GetImportIndexedSymbolEntry(process, j, im); + entry.GetImportIndexedSymbolEntry(process, memory, j, im); ExportIndexedSymbolEntry ex; - GetEntry(im.index, ex); + GetEntry(memory, im.index, ex); u32 symbol_address = SegmentTagToAddress(ex.symbol_position); LOG_TRACE(Service_LDR, " exports symbol 0x{:08X}", symbol_address); ResultCode result = @@ -1000,7 +1000,7 @@ ResultCode CROHelper::ApplyModuleExport(CROHelper target) { entry.import_anonymous_symbol_num, target.ModuleName()); for (u32 j = 0; j < entry.import_anonymous_symbol_num; ++j) { ImportAnonymousSymbolEntry im; - entry.GetImportAnonymousSymbolEntry(process, j, im); + entry.GetImportAnonymousSymbolEntry(process, memory, j, im); u32 symbol_address = SegmentTagToAddress(im.symbol_position); LOG_TRACE(Service_LDR, " exports symbol 0x{:08X}", symbol_address); ResultCode result = @@ -1023,16 +1023,16 @@ ResultCode CROHelper::ResetModuleExport(CROHelper target) { u32 target_import_module_num = target.GetField(ImportModuleNum); for (u32 i = 0; i < target_import_module_num; ++i) { ImportModuleEntry entry; - target.GetEntry(i, entry); + target.GetEntry(memory, i, entry); - if (Memory::ReadCString(entry.name_offset, target_import_string_size) != module_name) + if (memory.ReadCString(entry.name_offset, target_import_string_size) != module_name) continue; LOG_DEBUG(Service_LDR, "CRO \"{}\" unexports indexed symbols to \"{}\"", module_name, target.ModuleName()); for (u32 j = 0; j < entry.import_indexed_symbol_num; ++j) { ImportIndexedSymbolEntry im; - entry.GetImportIndexedSymbolEntry(process, j, im); + entry.GetImportIndexedSymbolEntry(process, memory, j, im); ResultCode result = target.ApplyRelocationBatch(im.relocation_batch_offset, unresolved_symbol, true); if (result.IsError()) { @@ -1045,7 +1045,7 @@ ResultCode CROHelper::ResetModuleExport(CROHelper target) { target.ModuleName()); for (u32 j = 0; j < entry.import_anonymous_symbol_num; ++j) { ImportAnonymousSymbolEntry im; - entry.GetImportAnonymousSymbolEntry(process, j, im); + entry.GetImportAnonymousSymbolEntry(process, memory, j, im); ResultCode result = target.ApplyRelocationBatch(im.relocation_batch_offset, unresolved_symbol, true); if (result.IsError()) { @@ -1063,15 +1063,15 @@ ResultCode CROHelper::ApplyExitRelocations(VAddr crs_address) { u32 symbol_import_num = GetField(ImportNamedSymbolNum); for (u32 i = 0; i < symbol_import_num; ++i) { ImportNamedSymbolEntry entry; - GetEntry(i, entry); + GetEntry(memory, i, entry); VAddr relocation_addr = entry.relocation_batch_offset; ExternalRelocationEntry relocation_entry; - Memory::ReadBlock(process, relocation_addr, &relocation_entry, - sizeof(ExternalRelocationEntry)); + memory.ReadBlock(process, relocation_addr, &relocation_entry, + sizeof(ExternalRelocationEntry)); - if (Memory::ReadCString(entry.name_offset, import_strings_size) == "__aeabi_atexit") { - ResultCode result = - ForEachAutoLinkCRO(process, crs_address, [&](CROHelper source) -> ResultVal { + if (memory.ReadCString(entry.name_offset, import_strings_size) == "__aeabi_atexit") { + ResultCode result = ForEachAutoLinkCRO( + process, memory, crs_address, [&](CROHelper source) -> ResultVal { u32 symbol_address = source.FindExportNamedSymbol("nnroAeabiAtexit_"); if (symbol_address != 0) { @@ -1108,9 +1108,9 @@ ResultCode CROHelper::ApplyExitRelocations(VAddr crs_address) { * @param size the size of the string (table), including the terminating 0 * @returns ResultCode RESULT_SUCCESS if the size matches, otherwise error code. */ -static ResultCode VerifyStringTableLength(VAddr address, u32 size) { +static ResultCode VerifyStringTableLength(Memory::MemorySystem& memory, VAddr address, u32 size) { if (size != 0) { - if (Memory::Read8(address + size - 1) != 0) + if (memory.Read8(address + size - 1) != 0) return CROFormatError(0x0B); } return RESULT_SUCCESS; @@ -1126,7 +1126,7 @@ ResultCode CROHelper::Rebase(VAddr crs_address, u32 cro_size, VAddr data_segment return result; } - result = VerifyStringTableLength(GetField(ModuleNameOffset), GetField(ModuleNameSize)); + result = VerifyStringTableLength(memory, GetField(ModuleNameOffset), GetField(ModuleNameSize)); if (result.IsError()) { LOG_ERROR(Service_LDR, "Error verifying module name {:08X}", result.raw); return result; @@ -1155,7 +1155,8 @@ ResultCode CROHelper::Rebase(VAddr crs_address, u32 cro_size, VAddr data_segment return result; } - result = VerifyStringTableLength(GetField(ExportStringsOffset), GetField(ExportStringsSize)); + result = + VerifyStringTableLength(memory, GetField(ExportStringsOffset), GetField(ExportStringsSize)); if (result.IsError()) { LOG_ERROR(Service_LDR, "Error verifying export strings {:08X}", result.raw); return result; @@ -1191,7 +1192,8 @@ ResultCode CROHelper::Rebase(VAddr crs_address, u32 cro_size, VAddr data_segment return result; } - result = VerifyStringTableLength(GetField(ImportStringsOffset), GetField(ImportStringsSize)); + result = + VerifyStringTableLength(memory, GetField(ImportStringsOffset), GetField(ImportStringsSize)); if (result.IsError()) { LOG_ERROR(Service_LDR, "Error verifying import strings {:08X}", result.raw); return result; @@ -1264,11 +1266,11 @@ ResultCode CROHelper::Link(VAddr crs_address, bool link_on_load_bug_fix) { // so we do the same if (GetField(SegmentNum) >= 2) { // means we have .data segment SegmentEntry entry; - GetEntry(2, entry); + GetEntry(memory, 2, entry); ASSERT(entry.type == SegmentType::Data); data_segment_address = entry.offset; entry.offset = GetField(DataOffset); - SetEntry(2, entry); + SetEntry(memory, 2, entry); } } SCOPE_EXIT({ @@ -1276,9 +1278,9 @@ ResultCode CROHelper::Link(VAddr crs_address, bool link_on_load_bug_fix) { if (link_on_load_bug_fix) { if (GetField(SegmentNum) >= 2) { SegmentEntry entry; - GetEntry(2, entry); + GetEntry(memory, 2, entry); entry.offset = data_segment_address; - SetEntry(2, entry); + SetEntry(memory, 2, entry); } } }); @@ -1299,17 +1301,18 @@ ResultCode CROHelper::Link(VAddr crs_address, bool link_on_load_bug_fix) { } // Exports symbols to other modules - result = ForEachAutoLinkCRO(process, crs_address, [this](CROHelper target) -> ResultVal { - ResultCode result = ApplyExportNamedSymbol(target); - if (result.IsError()) - return result; + result = ForEachAutoLinkCRO(process, memory, crs_address, + [this](CROHelper target) -> ResultVal { + ResultCode result = ApplyExportNamedSymbol(target); + if (result.IsError()) + return result; - result = ApplyModuleExport(target); - if (result.IsError()) - return result; + result = ApplyModuleExport(target); + if (result.IsError()) + return result; - return MakeResult(true); - }); + return MakeResult(true); + }); if (result.IsError()) { LOG_ERROR(Service_LDR, "Error applying export {:08X}", result.raw); return result; @@ -1343,17 +1346,18 @@ ResultCode CROHelper::Unlink(VAddr crs_address) { // Resets all symbols in other modules imported from this module // Note: the RO service seems only searching in auto-link modules - result = ForEachAutoLinkCRO(process, crs_address, [this](CROHelper target) -> ResultVal { - ResultCode result = ResetExportNamedSymbol(target); - if (result.IsError()) - return result; + result = ForEachAutoLinkCRO(process, memory, crs_address, + [this](CROHelper target) -> ResultVal { + ResultCode result = ResetExportNamedSymbol(target); + if (result.IsError()) + return result; - result = ResetModuleExport(target); - if (result.IsError()) - return result; + result = ResetModuleExport(target); + if (result.IsError()) + return result; - return MakeResult(true); - }); + return MakeResult(true); + }); if (result.IsError()) { LOG_ERROR(Service_LDR, "Error resetting export {:08X}", result.raw); return result; @@ -1383,13 +1387,13 @@ void CROHelper::InitCRS() { } void CROHelper::Register(VAddr crs_address, bool auto_link) { - CROHelper crs(crs_address, process); - CROHelper head(auto_link ? crs.NextModule() : crs.PreviousModule(), process); + CROHelper crs(crs_address, process, memory); + CROHelper head(auto_link ? crs.NextModule() : crs.PreviousModule(), process, memory); if (head.module_address) { // there are already CROs registered // register as the new tail - CROHelper tail(head.PreviousModule(), process); + CROHelper tail(head.PreviousModule(), process, memory); // link with the old tail ASSERT(tail.NextModule() == 0); @@ -1415,9 +1419,11 @@ void CROHelper::Register(VAddr crs_address, bool auto_link) { } void CROHelper::Unregister(VAddr crs_address) { - CROHelper crs(crs_address, process); - CROHelper next_head(crs.NextModule(), process), previous_head(crs.PreviousModule(), process); - CROHelper next(NextModule(), process), previous(PreviousModule(), process); + CROHelper crs(crs_address, process, memory); + CROHelper next_head(crs.NextModule(), process, memory); + CROHelper previous_head(crs.PreviousModule(), process, memory); + CROHelper next(NextModule(), process, memory); + CROHelper previous(PreviousModule(), process, memory); if (module_address == next_head.module_address || module_address == previous_head.module_address) { @@ -1511,7 +1517,7 @@ std::tuple CROHelper::GetExecutablePages() const { u32 segment_num = GetField(SegmentNum); for (u32 i = 0; i < segment_num; ++i) { SegmentEntry entry; - GetEntry(i, entry); + GetEntry(memory, i, entry); if (entry.type == SegmentType::Code && entry.size != 0) { VAddr begin = Common::AlignDown(entry.offset, Memory::PAGE_SIZE); VAddr end = Common::AlignUp(entry.offset + entry.size, Memory::PAGE_SIZE); diff --git a/src/core/hle/service/ldr_ro/cro_helper.h b/src/core/hle/service/ldr_ro/cro_helper.h index f61483bd7..1eee90045 100644 --- a/src/core/hle/service/ldr_ro/cro_helper.h +++ b/src/core/hle/service/ldr_ro/cro_helper.h @@ -40,11 +40,11 @@ static constexpr u32 CRO_HASH_SIZE = 0x80; class CROHelper final { public: // TODO (wwylele): pass in the process handle for memory access - explicit CROHelper(VAddr cro_address, Kernel::Process& process) - : module_address(cro_address), process(process) {} + explicit CROHelper(VAddr cro_address, Kernel::Process& process, Memory::MemorySystem& memory) + : module_address(cro_address), process(process), memory(memory) {} std::string ModuleName() const { - return Memory::ReadCString(GetField(ModuleNameOffset), GetField(ModuleNameSize)); + return memory.ReadCString(GetField(ModuleNameOffset), GetField(ModuleNameSize)); } u32 GetFileSize() const { @@ -150,6 +150,7 @@ public: private: const VAddr module_address; ///< the virtual address of this module Kernel::Process& process; ///< the owner process of this module + Memory::MemorySystem& memory; /** * Each item in this enum represents a u32 field in the header begin from address+0x80, @@ -317,20 +318,20 @@ private: static constexpr HeaderField TABLE_OFFSET_FIELD = ImportModuleTableOffset; - void GetImportIndexedSymbolEntry(Kernel::Process& process, u32 index, - ImportIndexedSymbolEntry& entry) { - Memory::ReadBlock(process, - import_indexed_symbol_table_offset + - index * sizeof(ImportIndexedSymbolEntry), - &entry, sizeof(ImportIndexedSymbolEntry)); + void GetImportIndexedSymbolEntry(Kernel::Process& process, Memory::MemorySystem& memory, + u32 index, ImportIndexedSymbolEntry& entry) { + memory.ReadBlock(process, + import_indexed_symbol_table_offset + + index * sizeof(ImportIndexedSymbolEntry), + &entry, sizeof(ImportIndexedSymbolEntry)); } - void GetImportAnonymousSymbolEntry(Kernel::Process& process, u32 index, - ImportAnonymousSymbolEntry& entry) { - Memory::ReadBlock(process, - import_anonymous_symbol_table_offset + - index * sizeof(ImportAnonymousSymbolEntry), - &entry, sizeof(ImportAnonymousSymbolEntry)); + void GetImportAnonymousSymbolEntry(Kernel::Process& process, Memory::MemorySystem& memory, + u32 index, ImportAnonymousSymbolEntry& entry) { + memory.ReadBlock(process, + import_anonymous_symbol_table_offset + + index * sizeof(ImportAnonymousSymbolEntry), + &entry, sizeof(ImportAnonymousSymbolEntry)); } }; ASSERT_CRO_STRUCT(ImportModuleEntry, 20); @@ -407,11 +408,11 @@ private: } u32 GetField(HeaderField field) const { - return Memory::Read32(Field(field)); + return memory.Read32(Field(field)); } void SetField(HeaderField field, u32 value) { - Memory::Write32(Field(field), value); + memory.Write32(Field(field), value); } /** @@ -422,10 +423,10 @@ private: * indicating which table the entry is in. */ template - void GetEntry(std::size_t index, T& data) const { - Memory::ReadBlock(process, - GetField(T::TABLE_OFFSET_FIELD) + static_cast(index * sizeof(T)), - &data, sizeof(T)); + void GetEntry(Memory::MemorySystem& memory, std::size_t index, T& data) const { + memory.ReadBlock(process, + GetField(T::TABLE_OFFSET_FIELD) + static_cast(index * sizeof(T)), + &data, sizeof(T)); } /** @@ -436,10 +437,10 @@ private: * indicating which table the entry is in. */ template - void SetEntry(std::size_t index, const T& data) { - Memory::WriteBlock(process, - GetField(T::TABLE_OFFSET_FIELD) + static_cast(index * sizeof(T)), - &data, sizeof(T)); + void SetEntry(Memory::MemorySystem& memory, std::size_t index, const T& data) { + memory.WriteBlock(process, + GetField(T::TABLE_OFFSET_FIELD) + static_cast(index * sizeof(T)), + &data, sizeof(T)); } /** @@ -478,11 +479,11 @@ private: * otherwise error code of the last iteration. */ template - static ResultCode ForEachAutoLinkCRO(Kernel::Process& process, VAddr crs_address, - FunctionObject func) { + static ResultCode ForEachAutoLinkCRO(Kernel::Process& process, Memory::MemorySystem& memory, + VAddr crs_address, FunctionObject func) { VAddr current = crs_address; while (current != 0) { - CROHelper cro(current, process); + CROHelper cro(current, process, memory); CASCADE_RESULT(bool next, func(cro)); if (!next) break; diff --git a/src/core/hle/service/ldr_ro/ldr_ro.cpp b/src/core/hle/service/ldr_ro/ldr_ro.cpp index 87195ad39..1b56c0629 100644 --- a/src/core/hle/service/ldr_ro/ldr_ro.cpp +++ b/src/core/hle/service/ldr_ro/ldr_ro.cpp @@ -115,7 +115,7 @@ void RO::Initialize(Kernel::HLERequestContext& ctx) { return; } - CROHelper crs(crs_address, *process); + CROHelper crs(crs_address, *process, system.Memory()); crs.InitCRS(); result = crs.Rebase(0, crs_size, 0, 0, 0, 0, true); @@ -249,7 +249,7 @@ void RO::LoadCRO(Kernel::HLERequestContext& ctx, bool link_on_load_bug_fix) { return; } - CROHelper cro(cro_address, *process); + CROHelper cro(cro_address, *process, system.Memory()); result = cro.VerifyHash(cro_size, crr_address); if (result.IsError()) { @@ -331,7 +331,7 @@ void RO::UnloadCRO(Kernel::HLERequestContext& ctx) { LOG_DEBUG(Service_LDR, "called, cro_address=0x{:08X}, zero={}, cro_buffer_ptr=0x{:08X}", cro_address, zero, cro_buffer_ptr); - CROHelper cro(cro_address, *process); + CROHelper cro(cro_address, *process, system.Memory()); IPC::RequestBuilder rb = rp.MakeBuilder(1, 0); @@ -398,7 +398,7 @@ void RO::LinkCRO(Kernel::HLERequestContext& ctx) { LOG_DEBUG(Service_LDR, "called, cro_address=0x{:08X}", cro_address); - CROHelper cro(cro_address, *process); + CROHelper cro(cro_address, *process, system.Memory()); IPC::RequestBuilder rb = rp.MakeBuilder(1, 0); @@ -438,7 +438,7 @@ void RO::UnlinkCRO(Kernel::HLERequestContext& ctx) { LOG_DEBUG(Service_LDR, "called, cro_address=0x{:08X}", cro_address); - CROHelper cro(cro_address, *process); + CROHelper cro(cro_address, *process, system.Memory()); IPC::RequestBuilder rb = rp.MakeBuilder(1, 0); @@ -487,7 +487,7 @@ void RO::Shutdown(Kernel::HLERequestContext& ctx) { return; } - CROHelper crs(slot->loaded_crs, *process); + CROHelper crs(slot->loaded_crs, *process, system.Memory()); crs.Unrebase(true); ResultCode result = RESULT_SUCCESS; @@ -502,7 +502,7 @@ void RO::Shutdown(Kernel::HLERequestContext& ctx) { rb.Push(result); } -RO::RO() : ServiceFramework("ldr:ro", 2) { +RO::RO(Core::System& system) : ServiceFramework("ldr:ro", 2), system(system) { static const FunctionInfo functions[] = { {0x000100C2, &RO::Initialize, "Initialize"}, {0x00020082, &RO::LoadCRR, "LoadCRR"}, @@ -519,7 +519,7 @@ RO::RO() : ServiceFramework("ldr:ro", 2) { void InstallInterfaces(Core::System& system) { auto& service_manager = system.ServiceManager(); - std::make_shared()->InstallAsService(service_manager); + std::make_shared(system)->InstallAsService(service_manager); } } // namespace Service::LDR diff --git a/src/core/hle/service/ldr_ro/ldr_ro.h b/src/core/hle/service/ldr_ro/ldr_ro.h index 54776feb0..f90005d13 100644 --- a/src/core/hle/service/ldr_ro/ldr_ro.h +++ b/src/core/hle/service/ldr_ro/ldr_ro.h @@ -18,7 +18,7 @@ struct ClientSlot : public Kernel::SessionRequestHandler::SessionDataBase { class RO final : public ServiceFramework { public: - RO(); + explicit RO(Core::System& system); private: /** @@ -149,6 +149,8 @@ private: * 1 : Result of function, 0 on success, otherwise error code */ void Shutdown(Kernel::HLERequestContext& self); + + Core::System& system; }; void InstallInterfaces(Core::System& system); diff --git a/src/core/hle/service/service.cpp b/src/core/hle/service/service.cpp index 795f720e3..b065208d3 100644 --- a/src/core/hle/service/service.cpp +++ b/src/core/hle/service/service.cpp @@ -180,7 +180,8 @@ void ServiceFrameworkBase::HandleSyncRequest(SharedPtr server_ses Kernel::KernelSystem& kernel = Core::System::GetInstance().Kernel(); auto thread = kernel.GetThreadManager().GetCurrentThread(); // TODO(wwylele): avoid GetPointer - u32* cmd_buf = reinterpret_cast(Memory::GetPointer(thread->GetCommandBufferAddress())); + u32* cmd_buf = reinterpret_cast( + Core::System::GetInstance().Memory().GetPointer(thread->GetCommandBufferAddress())); u32 header_code = cmd_buf[0]; auto itr = handlers.find(header_code); diff --git a/src/core/hw/gpu.cpp b/src/core/hw/gpu.cpp index 47bb852f8..07dbd0d94 100644 --- a/src/core/hw/gpu.cpp +++ b/src/core/hw/gpu.cpp @@ -27,6 +27,7 @@ namespace GPU { Regs g_regs; +Memory::MemorySystem* g_memory; /// 268MHz CPU clocks / 60Hz frames per second const u64 frame_ticks = static_cast(BASE_CLOCK_RATE_ARM11 / SCREEN_REFRESH_RATE); @@ -78,12 +79,12 @@ static void MemoryFill(const Regs::MemoryFillConfig& config) { const PAddr end_addr = config.GetEndAddress(); // TODO: do hwtest with these cases - if (!Memory::IsValidPhysicalAddress(start_addr)) { + if (!g_memory->IsValidPhysicalAddress(start_addr)) { LOG_CRITICAL(HW_GPU, "invalid start address {:#010X}", start_addr); return; } - if (!Memory::IsValidPhysicalAddress(end_addr)) { + if (!g_memory->IsValidPhysicalAddress(end_addr)) { LOG_CRITICAL(HW_GPU, "invalid end address {:#010X}", end_addr); return; } @@ -94,8 +95,8 @@ static void MemoryFill(const Regs::MemoryFillConfig& config) { return; } - u8* start = Memory::GetPhysicalPointer(start_addr); - u8* end = Memory::GetPhysicalPointer(end_addr); + u8* start = g_memory->GetPhysicalPointer(start_addr); + u8* end = g_memory->GetPhysicalPointer(end_addr); if (VideoCore::g_renderer->Rasterizer()->AccelerateFill(config)) return; @@ -131,12 +132,12 @@ static void DisplayTransfer(const Regs::DisplayTransferConfig& config) { const PAddr dst_addr = config.GetPhysicalOutputAddress(); // TODO: do hwtest with these cases - if (!Memory::IsValidPhysicalAddress(src_addr)) { + if (!g_memory->IsValidPhysicalAddress(src_addr)) { LOG_CRITICAL(HW_GPU, "invalid input address {:#010X}", src_addr); return; } - if (!Memory::IsValidPhysicalAddress(dst_addr)) { + if (!g_memory->IsValidPhysicalAddress(dst_addr)) { LOG_CRITICAL(HW_GPU, "invalid output address {:#010X}", dst_addr); return; } @@ -164,8 +165,8 @@ static void DisplayTransfer(const Regs::DisplayTransferConfig& config) { if (VideoCore::g_renderer->Rasterizer()->AccelerateDisplayTransfer(config)) return; - u8* src_pointer = Memory::GetPhysicalPointer(src_addr); - u8* dst_pointer = Memory::GetPhysicalPointer(dst_addr); + u8* src_pointer = g_memory->GetPhysicalPointer(src_addr); + u8* dst_pointer = g_memory->GetPhysicalPointer(dst_addr); if (config.scaling > config.ScaleXY) { LOG_CRITICAL(HW_GPU, "Unimplemented display transfer scaling mode {}", @@ -307,12 +308,12 @@ static void TextureCopy(const Regs::DisplayTransferConfig& config) { const PAddr dst_addr = config.GetPhysicalOutputAddress(); // TODO: do hwtest with invalid addresses - if (!Memory::IsValidPhysicalAddress(src_addr)) { + if (!g_memory->IsValidPhysicalAddress(src_addr)) { LOG_CRITICAL(HW_GPU, "invalid input address {:#010X}", src_addr); return; } - if (!Memory::IsValidPhysicalAddress(dst_addr)) { + if (!g_memory->IsValidPhysicalAddress(dst_addr)) { LOG_CRITICAL(HW_GPU, "invalid output address {:#010X}", dst_addr); return; } @@ -320,8 +321,8 @@ static void TextureCopy(const Regs::DisplayTransferConfig& config) { if (VideoCore::g_renderer->Rasterizer()->AccelerateTextureCopy(config)) return; - u8* src_pointer = Memory::GetPhysicalPointer(src_addr); - u8* dst_pointer = Memory::GetPhysicalPointer(dst_addr); + u8* src_pointer = g_memory->GetPhysicalPointer(src_addr); + u8* dst_pointer = g_memory->GetPhysicalPointer(dst_addr); u32 remaining_size = Common::AlignDown(config.texture_copy.size, 16); @@ -470,7 +471,7 @@ inline void Write(u32 addr, const T data) { if (config.trigger & 1) { MICROPROFILE_SCOPE(GPU_CmdlistProcessing); - u32* buffer = (u32*)Memory::GetPhysicalPointer(config.GetPhysicalAddress()); + u32* buffer = (u32*)g_memory->GetPhysicalPointer(config.GetPhysicalAddress()); if (Pica::g_debug_context && Pica::g_debug_context->recorder) { Pica::g_debug_context->recorder->MemoryAccessed((u8*)buffer, config.size, @@ -526,7 +527,8 @@ static void VBlankCallback(u64 userdata, s64 cycles_late) { } /// Initialize hardware -void Init() { +void Init(Memory::MemorySystem& memory) { + g_memory = &memory; memset(&g_regs, 0, sizeof(g_regs)); auto& framebuffer_top = g_regs.framebuffer_config[0]; diff --git a/src/core/hw/gpu.h b/src/core/hw/gpu.h index 8184066da..606ab9504 100644 --- a/src/core/hw/gpu.h +++ b/src/core/hw/gpu.h @@ -11,6 +11,10 @@ #include "common/common_funcs.h" #include "common/common_types.h" +namespace Memory { +class MemorySystem; +} + namespace GPU { constexpr float SCREEN_REFRESH_RATE = 60; @@ -326,7 +330,7 @@ template void Write(u32 addr, const T data); /// Initialize hardware -void Init(); +void Init(Memory::MemorySystem& memory); /// Shutdown hardware void Shutdown(); diff --git a/src/core/hw/hw.cpp b/src/core/hw/hw.cpp index 4d31b3c80..e7d80a5c7 100644 --- a/src/core/hw/hw.cpp +++ b/src/core/hw/hw.cpp @@ -86,9 +86,9 @@ template void Write(u32 addr, const u8 data); void Update() {} /// Initialize hardware -void Init() { +void Init(Memory::MemorySystem& memory) { AES::InitKeys(); - GPU::Init(); + GPU::Init(memory); LCD::Init(); LOG_DEBUG(HW, "initialized OK"); } diff --git a/src/core/hw/hw.h b/src/core/hw/hw.h index 5890d2b5c..cc7b04294 100644 --- a/src/core/hw/hw.h +++ b/src/core/hw/hw.h @@ -6,6 +6,10 @@ #include "common/common_types.h" +namespace Memory { +class MemorySystem; +} + namespace HW { /// Beginnings of IO register regions, in the user VA space. @@ -42,7 +46,7 @@ void Write(u32 addr, const T data); void Update(); /// Initialize hardware -void Init(); +void Init(Memory::MemorySystem& memory); /// Shutdown hardware void Shutdown(); diff --git a/src/core/hw/y2r.cpp b/src/core/hw/y2r.cpp index c1f99b571..a613bbed5 100644 --- a/src/core/hw/y2r.cpp +++ b/src/core/hw/y2r.cpp @@ -10,6 +10,7 @@ #include "common/color.h" #include "common/common_types.h" #include "common/vector_math.h" +#include "core/core.h" #include "core/hle/service/y2r_u.h" #include "core/hw/y2r.h" #include "core/memory.h" @@ -80,7 +81,7 @@ static void ConvertYUVToRGB(InputFormat input_format, const u8* input_Y, const u /// formats to 8-bit. template static void ReceiveData(u8* output, ConversionBuffer& buf, std::size_t amount_of_data) { - const u8* input = Memory::GetPointer(buf.address); + const u8* input = Core::System::GetInstance().Memory().GetPointer(buf.address); std::size_t output_unit = buf.transfer_unit / N; ASSERT(amount_of_data % output_unit == 0); @@ -104,7 +105,7 @@ static void ReceiveData(u8* output, ConversionBuffer& buf, std::size_t amount_of static void SendData(const u32* input, ConversionBuffer& buf, int amount_of_data, OutputFormat output_format, u8 alpha) { - u8* output = Memory::GetPointer(buf.address); + u8* output = Core::System::GetInstance().Memory().GetPointer(buf.address); while (amount_of_data > 0) { u8* unit_end = output + buf.transfer_unit; diff --git a/src/core/memory.cpp b/src/core/memory.cpp index f589c765a..396a00e39 100644 --- a/src/core/memory.cpp +++ b/src/core/memory.cpp @@ -21,21 +21,35 @@ namespace Memory { -static std::array vram; -static std::array n3ds_extra_ram; -std::array fcram; +class MemorySystem::Impl { +public: + Impl() { + std::fill(fcram.get(), fcram.get() + Memory::FCRAM_N3DS_SIZE, 0); + std::fill(vram.get(), vram.get() + Memory::VRAM_SIZE, 0); + std::fill(n3ds_extra_ram.get(), n3ds_extra_ram.get() + Memory::N3DS_EXTRA_RAM_SIZE, 0); + } -static PageTable* current_page_table = nullptr; + // Visual Studio would try to allocate these on compile time if they are std::array, which would + // exceed the memory limit. + std::unique_ptr fcram = std::make_unique(Memory::FCRAM_N3DS_SIZE); + std::unique_ptr vram = std::make_unique(Memory::VRAM_SIZE); + std::unique_ptr n3ds_extra_ram = std::make_unique(Memory::N3DS_EXTRA_RAM_SIZE); -void SetCurrentPageTable(PageTable* page_table) { - current_page_table = page_table; + PageTable* current_page_table = nullptr; +}; + +MemorySystem::MemorySystem() : impl(std::make_unique()) {} +MemorySystem::~MemorySystem() = default; + +void MemorySystem::SetCurrentPageTable(PageTable* page_table) { + impl->current_page_table = page_table; if (Core::System::GetInstance().IsPoweredOn()) { Core::CPU().PageTableChanged(); } } -PageTable* GetCurrentPageTable() { - return current_page_table; +PageTable* MemorySystem::GetCurrentPageTable() const { + return impl->current_page_table; } static void MapPages(PageTable& page_table, u32 base, u32 size, u8* memory, PageType type) { @@ -78,21 +92,15 @@ void UnmapRegion(PageTable& page_table, VAddr base, u32 size) { MapPages(page_table, base / PAGE_SIZE, size / PAGE_SIZE, nullptr, PageType::Unmapped); } -/** - * Gets the pointer for virtual memory where the page is marked as RasterizerCachedMemory. - * This is used to access the memory where the page pointer is nullptr due to rasterizer cache. - * Since the cache only happens on linear heap or VRAM, we know the exact physical address and - * pointer of such virtual address - */ -static u8* GetPointerForRasterizerCache(VAddr addr) { +u8* MemorySystem::GetPointerForRasterizerCache(VAddr addr) { if (addr >= LINEAR_HEAP_VADDR && addr < LINEAR_HEAP_VADDR_END) { - return fcram.data() + (addr - LINEAR_HEAP_VADDR); + return impl->fcram.get() + (addr - LINEAR_HEAP_VADDR); } if (addr >= NEW_LINEAR_HEAP_VADDR && addr < NEW_LINEAR_HEAP_VADDR_END) { - return fcram.data() + (addr - NEW_LINEAR_HEAP_VADDR); + return impl->fcram.get() + (addr - NEW_LINEAR_HEAP_VADDR); } if (addr >= VRAM_VADDR && addr < VRAM_VADDR_END) { - return vram.data() + (addr - VRAM_VADDR); + return impl->vram.get() + (addr - VRAM_VADDR); } UNREACHABLE(); } @@ -114,8 +122,8 @@ template T ReadMMIO(MMIORegionPointer mmio_handler, VAddr addr); template -T Read(const VAddr vaddr) { - const u8* page_pointer = current_page_table->pointers[vaddr >> PAGE_BITS]; +T MemorySystem::Read(const VAddr vaddr) { + const u8* page_pointer = impl->current_page_table->pointers[vaddr >> PAGE_BITS]; if (page_pointer) { // NOTE: Avoid adding any extra logic to this fast-path block T value; @@ -126,7 +134,7 @@ T Read(const VAddr vaddr) { // The memory access might do an MMIO or cached access, so we have to lock the HLE kernel state std::lock_guard lock(HLE::g_hle_lock); - PageType type = current_page_table->attributes[vaddr >> PAGE_BITS]; + PageType type = impl->current_page_table->attributes[vaddr >> PAGE_BITS]; switch (type) { case PageType::Unmapped: LOG_ERROR(HW_Memory, "unmapped Read{} @ 0x{:08X}", sizeof(T) * 8, vaddr); @@ -142,7 +150,7 @@ T Read(const VAddr vaddr) { return value; } case PageType::Special: - return ReadMMIO(GetMMIOHandler(*current_page_table, vaddr), vaddr); + return ReadMMIO(GetMMIOHandler(*impl->current_page_table, vaddr), vaddr); default: UNREACHABLE(); } @@ -152,8 +160,8 @@ template void WriteMMIO(MMIORegionPointer mmio_handler, VAddr addr, const T data); template -void Write(const VAddr vaddr, const T data) { - u8* page_pointer = current_page_table->pointers[vaddr >> PAGE_BITS]; +void MemorySystem::Write(const VAddr vaddr, const T data) { + u8* page_pointer = impl->current_page_table->pointers[vaddr >> PAGE_BITS]; if (page_pointer) { // NOTE: Avoid adding any extra logic to this fast-path block std::memcpy(&page_pointer[vaddr & PAGE_MASK], &data, sizeof(T)); @@ -163,7 +171,7 @@ void Write(const VAddr vaddr, const T data) { // The memory access might do an MMIO or cached access, so we have to lock the HLE kernel state std::lock_guard lock(HLE::g_hle_lock); - PageType type = current_page_table->attributes[vaddr >> PAGE_BITS]; + PageType type = impl->current_page_table->attributes[vaddr >> PAGE_BITS]; switch (type) { case PageType::Unmapped: LOG_ERROR(HW_Memory, "unmapped Write{} 0x{:08X} @ 0x{:08X}", sizeof(data) * 8, (u32)data, @@ -178,7 +186,7 @@ void Write(const VAddr vaddr, const T data) { break; } case PageType::Special: - WriteMMIO(GetMMIOHandler(*current_page_table, vaddr), vaddr, data); + WriteMMIO(GetMMIOHandler(*impl->current_page_table, vaddr), vaddr, data); break; default: UNREACHABLE(); @@ -206,17 +214,18 @@ bool IsValidVirtualAddress(const Kernel::Process& process, const VAddr vaddr) { return false; } -bool IsValidPhysicalAddress(const PAddr paddr) { +bool MemorySystem::IsValidPhysicalAddress(const PAddr paddr) { return GetPhysicalPointer(paddr) != nullptr; } -u8* GetPointer(const VAddr vaddr) { - u8* page_pointer = current_page_table->pointers[vaddr >> PAGE_BITS]; +u8* MemorySystem::GetPointer(const VAddr vaddr) { + u8* page_pointer = impl->current_page_table->pointers[vaddr >> PAGE_BITS]; if (page_pointer) { return page_pointer + (vaddr & PAGE_MASK); } - if (current_page_table->attributes[vaddr >> PAGE_BITS] == PageType::RasterizerCachedMemory) { + if (impl->current_page_table->attributes[vaddr >> PAGE_BITS] == + PageType::RasterizerCachedMemory) { return GetPointerForRasterizerCache(vaddr); } @@ -224,7 +233,7 @@ u8* GetPointer(const VAddr vaddr) { return nullptr; } -std::string ReadCString(VAddr vaddr, std::size_t max_length) { +std::string MemorySystem::ReadCString(VAddr vaddr, std::size_t max_length) { std::string string; string.reserve(max_length); for (std::size_t i = 0; i < max_length; ++i) { @@ -238,7 +247,7 @@ std::string ReadCString(VAddr vaddr, std::size_t max_length) { return string; } -u8* GetPhysicalPointer(PAddr address) { +u8* MemorySystem::GetPhysicalPointer(PAddr address) { struct MemoryArea { PAddr paddr_base; u32 size; @@ -268,16 +277,16 @@ u8* GetPhysicalPointer(PAddr address) { u8* target_pointer = nullptr; switch (area->paddr_base) { case VRAM_PADDR: - target_pointer = vram.data() + offset_into_region; + target_pointer = impl->vram.get() + offset_into_region; break; case DSP_RAM_PADDR: target_pointer = Core::DSP().GetDspMemory().data() + offset_into_region; break; case FCRAM_PADDR: - target_pointer = fcram.data() + offset_into_region; + target_pointer = impl->fcram.get() + offset_into_region; break; case N3DS_EXTRA_RAM_PADDR: - target_pointer = n3ds_extra_ram.data() + offset_into_region; + target_pointer = impl->n3ds_extra_ram.get() + offset_into_region; break; default: UNREACHABLE(); @@ -305,7 +314,7 @@ static std::vector PhysicalToVirtualAddressForRasterizer(PAddr addr) { return {}; } -void RasterizerMarkRegionCached(PAddr start, u32 size, bool cached) { +void MemorySystem::RasterizerMarkRegionCached(PAddr start, u32 size, bool cached) { if (start == 0) { return; } @@ -315,7 +324,7 @@ void RasterizerMarkRegionCached(PAddr start, u32 size, bool cached) { for (unsigned i = 0; i < num_pages; ++i, paddr += PAGE_SIZE) { for (VAddr vaddr : PhysicalToVirtualAddressForRasterizer(paddr)) { - PageType& page_type = current_page_table->attributes[vaddr >> PAGE_BITS]; + PageType& page_type = impl->current_page_table->attributes[vaddr >> PAGE_BITS]; if (cached) { // Switch page type to cached if now cached @@ -326,7 +335,7 @@ void RasterizerMarkRegionCached(PAddr start, u32 size, bool cached) { break; case PageType::Memory: page_type = PageType::RasterizerCachedMemory; - current_page_table->pointers[vaddr >> PAGE_BITS] = nullptr; + impl->current_page_table->pointers[vaddr >> PAGE_BITS] = nullptr; break; default: UNREACHABLE(); @@ -340,7 +349,7 @@ void RasterizerMarkRegionCached(PAddr start, u32 size, bool cached) { break; case PageType::RasterizerCachedMemory: { page_type = PageType::Memory; - current_page_table->pointers[vaddr >> PAGE_BITS] = + impl->current_page_table->pointers[vaddr >> PAGE_BITS] = GetPointerForRasterizerCache(vaddr & ~PAGE_MASK); break; } @@ -417,24 +426,24 @@ void RasterizerFlushVirtualRegion(VAddr start, u32 size, FlushMode mode) { CheckRegion(VRAM_VADDR, VRAM_VADDR_END, VRAM_PADDR); } -u8 Read8(const VAddr addr) { +u8 MemorySystem::Read8(const VAddr addr) { return Read(addr); } -u16 Read16(const VAddr addr) { +u16 MemorySystem::Read16(const VAddr addr) { return Read(addr); } -u32 Read32(const VAddr addr) { +u32 MemorySystem::Read32(const VAddr addr) { return Read(addr); } -u64 Read64(const VAddr addr) { +u64 MemorySystem::Read64(const VAddr addr) { return Read(addr); } -void ReadBlock(const Kernel::Process& process, const VAddr src_addr, void* dest_buffer, - const std::size_t size) { +void MemorySystem::ReadBlock(const Kernel::Process& process, const VAddr src_addr, + void* dest_buffer, const std::size_t size) { auto& page_table = process.vm_manager.page_table; std::size_t remaining_size = size; @@ -483,24 +492,24 @@ void ReadBlock(const Kernel::Process& process, const VAddr src_addr, void* dest_ } } -void Write8(const VAddr addr, const u8 data) { +void MemorySystem::Write8(const VAddr addr, const u8 data) { Write(addr, data); } -void Write16(const VAddr addr, const u16 data) { +void MemorySystem::Write16(const VAddr addr, const u16 data) { Write(addr, data); } -void Write32(const VAddr addr, const u32 data) { +void MemorySystem::Write32(const VAddr addr, const u32 data) { Write(addr, data); } -void Write64(const VAddr addr, const u64 data) { +void MemorySystem::Write64(const VAddr addr, const u64 data) { Write(addr, data); } -void WriteBlock(const Kernel::Process& process, const VAddr dest_addr, const void* src_buffer, - const std::size_t size) { +void MemorySystem::WriteBlock(const Kernel::Process& process, const VAddr dest_addr, + const void* src_buffer, const std::size_t size) { auto& page_table = process.vm_manager.page_table; std::size_t remaining_size = size; std::size_t page_index = dest_addr >> PAGE_BITS; @@ -547,7 +556,8 @@ void WriteBlock(const Kernel::Process& process, const VAddr dest_addr, const voi } } -void ZeroBlock(const Kernel::Process& process, const VAddr dest_addr, const std::size_t size) { +void MemorySystem::ZeroBlock(const Kernel::Process& process, const VAddr dest_addr, + const std::size_t size) { auto& page_table = process.vm_manager.page_table; std::size_t remaining_size = size; std::size_t page_index = dest_addr >> PAGE_BITS; @@ -595,8 +605,8 @@ void ZeroBlock(const Kernel::Process& process, const VAddr dest_addr, const std: } } -void CopyBlock(const Kernel::Process& process, VAddr dest_addr, VAddr src_addr, - const std::size_t size) { +void MemorySystem::CopyBlock(const Kernel::Process& process, VAddr dest_addr, VAddr src_addr, + const std::size_t size) { auto& page_table = process.vm_manager.page_table; std::size_t remaining_size = size; std::size_t page_index = src_addr >> PAGE_BITS; @@ -647,8 +657,9 @@ void CopyBlock(const Kernel::Process& process, VAddr dest_addr, VAddr src_addr, } } -void CopyBlock(const Kernel::Process& src_process, const Kernel::Process& dest_process, - VAddr src_addr, VAddr dest_addr, std::size_t size) { +void MemorySystem::CopyBlock(const Kernel::Process& src_process, + const Kernel::Process& dest_process, VAddr src_addr, VAddr dest_addr, + std::size_t size) { auto& page_table = src_process.vm_manager.page_table; std::size_t remaining_size = size; std::size_t page_index = src_addr >> PAGE_BITS; @@ -739,9 +750,14 @@ void WriteMMIO(MMIORegionPointer mmio_handler, VAddr addr, const u64 data) mmio_handler->Write64(addr, data); } -u32 GetFCRAMOffset(u8* pointer) { - ASSERT(pointer >= fcram.data() && pointer < fcram.data() + fcram.size()); - return pointer - fcram.data(); +u32 MemorySystem::GetFCRAMOffset(u8* pointer) { + ASSERT(pointer >= impl->fcram.get() && pointer <= impl->fcram.get() + Memory::FCRAM_N3DS_SIZE); + return pointer - impl->fcram.get(); +} + +u8* MemorySystem::GetFCRAMPointer(u32 offset) { + ASSERT(offset <= Memory::FCRAM_N3DS_SIZE); + return impl->fcram.get() + offset; } } // namespace Memory diff --git a/src/core/memory.h b/src/core/memory.h index dcefb369e..b6f0fb619 100644 --- a/src/core/memory.h +++ b/src/core/memory.h @@ -6,6 +6,7 @@ #include #include +#include #include #include #include "common/common_types.h" @@ -178,49 +179,6 @@ enum : VAddr { NEW_LINEAR_HEAP_VADDR_END = NEW_LINEAR_HEAP_VADDR + NEW_LINEAR_HEAP_SIZE, }; -extern std::array fcram; - -/// Currently active page table -void SetCurrentPageTable(PageTable* page_table); -PageTable* GetCurrentPageTable(); - -/// Determines if the given VAddr is valid for the specified process. -bool IsValidVirtualAddress(const Kernel::Process& process, VAddr vaddr); - -bool IsValidPhysicalAddress(PAddr paddr); - -u8 Read8(VAddr addr); -u16 Read16(VAddr addr); -u32 Read32(VAddr addr); -u64 Read64(VAddr addr); - -void Write8(VAddr addr, u8 data); -void Write16(VAddr addr, u16 data); -void Write32(VAddr addr, u32 data); -void Write64(VAddr addr, u64 data); - -void ReadBlock(const Kernel::Process& process, VAddr src_addr, void* dest_buffer, std::size_t size); -void WriteBlock(const Kernel::Process& process, VAddr dest_addr, const void* src_buffer, - std::size_t size); -void ZeroBlock(const Kernel::Process& process, VAddr dest_addr, const std::size_t size); -void CopyBlock(const Kernel::Process& process, VAddr dest_addr, VAddr src_addr, std::size_t size); -void CopyBlock(const Kernel::Process& src_process, const Kernel::Process& dest_process, - VAddr src_addr, VAddr dest_addr, std::size_t size); - -u8* GetPointer(VAddr vaddr); - -std::string ReadCString(VAddr vaddr, std::size_t max_length); - -/** - * Gets a pointer to the memory region beginning at the specified physical address. - */ -u8* GetPhysicalPointer(PAddr address); - -/** - * Mark each page touching the region as cached. - */ -void RasterizerMarkRegionCached(PAddr start, u32 size, bool cached); - /** * Flushes any externally cached rasterizer resources touching the given region. */ @@ -251,7 +209,78 @@ enum class FlushMode { */ void RasterizerFlushVirtualRegion(VAddr start, u32 size, FlushMode mode); -/// Gets offset in FCRAM from a pointer inside FCRAM range -u32 GetFCRAMOffset(u8* pointer); +class MemorySystem { +public: + MemorySystem(); + ~MemorySystem(); + + /// Currently active page table + void SetCurrentPageTable(PageTable* page_table); + PageTable* GetCurrentPageTable() const; + + u8 Read8(VAddr addr); + u16 Read16(VAddr addr); + u32 Read32(VAddr addr); + u64 Read64(VAddr addr); + + void Write8(VAddr addr, u8 data); + void Write16(VAddr addr, u16 data); + void Write32(VAddr addr, u32 data); + void Write64(VAddr addr, u64 data); + + void ReadBlock(const Kernel::Process& process, VAddr src_addr, void* dest_buffer, + std::size_t size); + void WriteBlock(const Kernel::Process& process, VAddr dest_addr, const void* src_buffer, + std::size_t size); + void ZeroBlock(const Kernel::Process& process, VAddr dest_addr, const std::size_t size); + void CopyBlock(const Kernel::Process& process, VAddr dest_addr, VAddr src_addr, + std::size_t size); + void CopyBlock(const Kernel::Process& src_process, const Kernel::Process& dest_process, + VAddr src_addr, VAddr dest_addr, std::size_t size); + + std::string ReadCString(VAddr vaddr, std::size_t max_length); + + /** + * Gets a pointer to the memory region beginning at the specified physical address. + */ + u8* GetPhysicalPointer(PAddr address); + + u8* GetPointer(VAddr vaddr); + + bool IsValidPhysicalAddress(PAddr paddr); + + /// Gets offset in FCRAM from a pointer inside FCRAM range + u32 GetFCRAMOffset(u8* pointer); + + /// Gets pointer in FCRAM with given offset + u8* GetFCRAMPointer(u32 offset); + + /** + * Mark each page touching the region as cached. + */ + void RasterizerMarkRegionCached(PAddr start, u32 size, bool cached); + +private: + template + T Read(const VAddr vaddr); + + template + void Write(const VAddr vaddr, const T data); + + /** + * Gets the pointer for virtual memory where the page is marked as RasterizerCachedMemory. + * This is used to access the memory where the page pointer is nullptr due to rasterizer cache. + * Since the cache only happens on linear heap or VRAM, we know the exact physical address and + * pointer of such virtual address + */ + u8* GetPointerForRasterizerCache(VAddr addr); + + class Impl; + + std::unique_ptr impl; +}; + +/// Determines if the given VAddr is valid for the specified process. +bool IsValidVirtualAddress(const Kernel::Process& process, VAddr vaddr); } // namespace Memory diff --git a/src/core/rpc/rpc_server.cpp b/src/core/rpc/rpc_server.cpp index 3a8b7f467..aec99f273 100644 --- a/src/core/rpc/rpc_server.cpp +++ b/src/core/rpc/rpc_server.cpp @@ -30,8 +30,9 @@ void RPCServer::HandleReadMemory(Packet& packet, u32 address, u32 data_size) { } // Note: Memory read occurs asynchronously from the state of the emulator - Memory::ReadBlock(*Core::System::GetInstance().Kernel().GetCurrentProcess(), address, - packet.GetPacketData().data(), data_size); + Core::System::GetInstance().Memory().ReadBlock( + *Core::System::GetInstance().Kernel().GetCurrentProcess(), address, + packet.GetPacketData().data(), data_size); packet.SetPacketDataSize(data_size); packet.SendReply(); } @@ -42,8 +43,8 @@ void RPCServer::HandleWriteMemory(Packet& packet, u32 address, const u8* data, u (address >= Memory::HEAP_VADDR && address <= Memory::HEAP_VADDR_END) || (address >= Memory::N3DS_EXTRA_RAM_VADDR && address <= Memory::N3DS_EXTRA_RAM_VADDR_END)) { // Note: Memory write occurs asynchronously from the state of the emulator - Memory::WriteBlock(*Core::System::GetInstance().Kernel().GetCurrentProcess(), address, data, - data_size); + Core::System::GetInstance().Memory().WriteBlock( + *Core::System::GetInstance().Kernel().GetCurrentProcess(), address, data, data_size); // If the memory happens to be executable code, make sure the changes become visible Core::CPU().InvalidateCacheRange(address, data_size); } diff --git a/src/tests/core/arm/arm_test_common.cpp b/src/tests/core/arm/arm_test_common.cpp index 58b60f506..c316f8f36 100644 --- a/src/tests/core/arm/arm_test_common.cpp +++ b/src/tests/core/arm/arm_test_common.cpp @@ -20,7 +20,9 @@ TestEnvironment::TestEnvironment(bool mutable_memory_) // so we need to create the kernel object there. // Change this when all global states are eliminated. Core::System::GetInstance().timing = std::make_unique(); - Core::System::GetInstance().kernel = std::make_unique(0); + Core::System::GetInstance().memory = std::make_unique(); + Memory::MemorySystem& memory = *Core::System::GetInstance().memory; + Core::System::GetInstance().kernel = std::make_unique(memory, 0); kernel = Core::System::GetInstance().kernel.get(); kernel->SetCurrentProcess(kernel->CreateProcess(kernel->CreateCodeSet("", 0))); @@ -32,7 +34,7 @@ TestEnvironment::TestEnvironment(bool mutable_memory_) Memory::MapIoRegion(*page_table, 0x00000000, 0x80000000, test_memory); Memory::MapIoRegion(*page_table, 0x80000000, 0x80000000, test_memory); - Memory::SetCurrentPageTable(page_table); + memory.SetCurrentPageTable(page_table); } TestEnvironment::~TestEnvironment() { diff --git a/src/tests/core/arm/dyncom/arm_dyncom_vfp_tests.cpp b/src/tests/core/arm/dyncom/arm_dyncom_vfp_tests.cpp index 848ed2c3c..6eb1a3b7f 100644 --- a/src/tests/core/arm/dyncom/arm_dyncom_vfp_tests.cpp +++ b/src/tests/core/arm/dyncom/arm_dyncom_vfp_tests.cpp @@ -3,8 +3,8 @@ // Refer to the license.txt file included. #include - #include "core/arm/dyncom/arm_dyncom.h" +#include "core/core.h" #include "core/core_timing.h" #include "tests/core/arm/arm_test_common.h" @@ -23,7 +23,7 @@ TEST_CASE("ARM_DynCom (vfp): vadd", "[arm_dyncom]") { test_env.SetMemory32(0, 0xEE321A03); // vadd.f32 s2, s4, s6 test_env.SetMemory32(4, 0xEAFFFFFE); // b +#0 - ARM_DynCom dyncom(USER32MODE); + ARM_DynCom dyncom(Core::System::GetInstance(), USER32MODE); std::vector test_cases{{ #include "vfp_vadd_f32.inc" @@ -47,4 +47,4 @@ TEST_CASE("ARM_DynCom (vfp): vadd", "[arm_dyncom]") { } } -} // namespace ArmTests \ No newline at end of file +} // namespace ArmTests diff --git a/src/tests/core/hle/kernel/hle_ipc.cpp b/src/tests/core/hle/kernel/hle_ipc.cpp index 86de36db4..c22c66837 100644 --- a/src/tests/core/hle/kernel/hle_ipc.cpp +++ b/src/tests/core/hle/kernel/hle_ipc.cpp @@ -23,7 +23,8 @@ static SharedPtr MakeObject(Kernel::KernelSystem& kernel) { TEST_CASE("HLERequestContext::PopulateFromIncomingCommandBuffer", "[core][kernel]") { // HACK: see comments of member timing Core::System::GetInstance().timing = std::make_unique(); - Kernel::KernelSystem kernel(0); + auto memory = std::make_unique(); + Kernel::KernelSystem kernel(*memory, 0); auto session = std::get>(kernel.CreateSessionPair()); HLERequestContext context(std::move(session)); @@ -235,7 +236,8 @@ TEST_CASE("HLERequestContext::PopulateFromIncomingCommandBuffer", "[core][kernel TEST_CASE("HLERequestContext::WriteToOutgoingCommandBuffer", "[core][kernel]") { // HACK: see comments of member timing Core::System::GetInstance().timing = std::make_unique(); - Kernel::KernelSystem kernel(0); + auto memory = std::make_unique(); + Kernel::KernelSystem kernel(*memory, 0); auto session = std::get>(kernel.CreateSessionPair()); HLERequestContext context(std::move(session)); diff --git a/src/tests/core/memory/memory.cpp b/src/tests/core/memory/memory.cpp index 196cd78ef..ee795e63d 100644 --- a/src/tests/core/memory/memory.cpp +++ b/src/tests/core/memory/memory.cpp @@ -13,7 +13,8 @@ TEST_CASE("Memory::IsValidVirtualAddress", "[core][memory]") { // HACK: see comments of member timing Core::System::GetInstance().timing = std::make_unique(); - Kernel::KernelSystem kernel(0); + Core::System::GetInstance().memory = std::make_unique(); + Kernel::KernelSystem kernel(*Core::System::GetInstance().memory, 0); SECTION("these regions should not be mapped on an empty process") { auto process = kernel.CreateProcess(kernel.CreateCodeSet("", 0)); CHECK(Memory::IsValidVirtualAddress(*process, Memory::PROCESS_IMAGE_VADDR) == false); @@ -35,13 +36,13 @@ TEST_CASE("Memory::IsValidVirtualAddress", "[core][memory]") { SECTION("special regions should be valid after mapping them") { auto process = kernel.CreateProcess(kernel.CreateCodeSet("", 0)); SECTION("VRAM") { - Kernel::HandleSpecialMapping(process->vm_manager, - {Memory::VRAM_VADDR, Memory::VRAM_SIZE, false, false}); + kernel.HandleSpecialMapping(process->vm_manager, + {Memory::VRAM_VADDR, Memory::VRAM_SIZE, false, false}); CHECK(Memory::IsValidVirtualAddress(*process, Memory::VRAM_VADDR) == true); } SECTION("IO (Not yet implemented)") { - Kernel::HandleSpecialMapping( + kernel.HandleSpecialMapping( process->vm_manager, {Memory::IO_AREA_VADDR, Memory::IO_AREA_SIZE, false, false}); CHECK_FALSE(Memory::IsValidVirtualAddress(*process, Memory::IO_AREA_VADDR) == true); } diff --git a/src/video_core/command_processor.cpp b/src/video_core/command_processor.cpp index 7aec9de98..5810537b9 100644 --- a/src/video_core/command_processor.cpp +++ b/src/video_core/command_processor.cpp @@ -269,7 +269,7 @@ static void WritePicaReg(u32 id, u32 value, u32 mask) { case PICA_REG_INDEX_WORKAROUND(pipeline.command_buffer.trigger[1], 0x23d): { unsigned index = static_cast(id - PICA_REG_INDEX(pipeline.command_buffer.trigger[0])); - u32* head_ptr = (u32*)Memory::GetPhysicalPointer( + u32* head_ptr = (u32*)VideoCore::g_memory->GetPhysicalPointer( regs.pipeline.command_buffer.GetPhysicalAddress(index)); g_state.cmd_list.head_ptr = g_state.cmd_list.current_ptr = head_ptr; g_state.cmd_list.length = regs.pipeline.command_buffer.GetSize(index) / sizeof(u32); @@ -328,7 +328,8 @@ static void WritePicaReg(u32 id, u32 value, u32 mask) { // Load vertices const auto& index_info = regs.pipeline.index_array; - const u8* index_address_8 = Memory::GetPhysicalPointer(base_address + index_info.offset); + const u8* index_address_8 = + VideoCore::g_memory->GetPhysicalPointer(base_address + index_info.offset); const u16* index_address_16 = reinterpret_cast(index_address_8); bool index_u16 = index_info.format != 0; @@ -338,7 +339,8 @@ static void WritePicaReg(u32 id, u32 value, u32 mask) { if (!texture.enabled) continue; - u8* texture_data = Memory::GetPhysicalPointer(texture.config.GetPhysicalAddress()); + u8* texture_data = + VideoCore::g_memory->GetPhysicalPointer(texture.config.GetPhysicalAddress()); g_debug_context->recorder->MemoryAccessed( texture_data, Pica::TexturingRegs::NibblesPerPixel(texture.format) * texture.config.width / @@ -424,8 +426,8 @@ static void WritePicaReg(u32 id, u32 value, u32 mask) { } for (auto& range : memory_accesses.ranges) { - g_debug_context->recorder->MemoryAccessed(Memory::GetPhysicalPointer(range.first), - range.second, range.first); + g_debug_context->recorder->MemoryAccessed( + VideoCore::g_memory->GetPhysicalPointer(range.first), range.second, range.first); } VideoCore::g_renderer->Rasterizer()->DrawTriangles(); diff --git a/src/video_core/renderer_opengl/gl_rasterizer.cpp b/src/video_core/renderer_opengl/gl_rasterizer.cpp index b62320064..50f89a656 100644 --- a/src/video_core/renderer_opengl/gl_rasterizer.cpp +++ b/src/video_core/renderer_opengl/gl_rasterizer.cpp @@ -24,6 +24,7 @@ #include "video_core/renderer_opengl/gl_shader_gen.h" #include "video_core/renderer_opengl/pica_to_gl.h" #include "video_core/renderer_opengl/renderer_opengl.h" +#include "video_core/video_core.h" namespace OpenGL { @@ -259,7 +260,7 @@ RasterizerOpenGL::VertexArrayInfo RasterizerOpenGL::AnalyzeVertexArray(bool is_i if (is_indexed) { const auto& index_info = regs.pipeline.index_array; PAddr address = vertex_attributes.GetPhysicalBaseAddress() + index_info.offset; - const u8* index_address_8 = Memory::GetPhysicalPointer(address); + const u8* index_address_8 = VideoCore::g_memory->GetPhysicalPointer(address); const u16* index_address_16 = reinterpret_cast(index_address_8); bool index_u16 = index_info.format != 0; @@ -340,7 +341,7 @@ void RasterizerOpenGL::SetupVertexArray(u8* array_ptr, GLintptr buffer_offset, u32 data_size = loader.byte_count * vertex_num; res_cache.FlushRegion(data_addr, data_size, nullptr); - std::memcpy(array_ptr, Memory::GetPhysicalPointer(data_addr), data_size); + std::memcpy(array_ptr, VideoCore::g_memory->GetPhysicalPointer(data_addr), data_size); array_ptr += data_size; buffer_offset += data_size; @@ -471,9 +472,9 @@ bool RasterizerOpenGL::AccelerateDrawBatchInternal(bool is_indexed, bool use_gs) return false; } - const u8* index_data = - Memory::GetPhysicalPointer(regs.pipeline.vertex_attributes.GetPhysicalBaseAddress() + - regs.pipeline.index_array.offset); + const u8* index_data = VideoCore::g_memory->GetPhysicalPointer( + regs.pipeline.vertex_attributes.GetPhysicalBaseAddress() + + regs.pipeline.index_array.offset); std::tie(buffer_ptr, buffer_offset, std::ignore) = index_buffer.Map(index_buffer_size, 4); std::memcpy(buffer_ptr, index_data, index_buffer_size); index_buffer.Unmap(index_buffer_size); diff --git a/src/video_core/renderer_opengl/gl_rasterizer_cache.cpp b/src/video_core/renderer_opengl/gl_rasterizer_cache.cpp index 638096e34..51fe40d49 100644 --- a/src/video_core/renderer_opengl/gl_rasterizer_cache.cpp +++ b/src/video_core/renderer_opengl/gl_rasterizer_cache.cpp @@ -134,7 +134,7 @@ static void MortonCopy(u32 stride, u32 height, u8* gl_buffer, PAddr base, PAddr } }; - u8* tile_buffer = Memory::GetPhysicalPointer(start); + u8* tile_buffer = VideoCore::g_memory->GetPhysicalPointer(start); if (start < aligned_start && !morton_to_gl) { std::array tmp_buf; @@ -625,7 +625,7 @@ MICROPROFILE_DEFINE(OpenGL_SurfaceLoad, "OpenGL", "Surface Load", MP_RGB(128, 19 void CachedSurface::LoadGLBuffer(PAddr load_start, PAddr load_end) { ASSERT(type != SurfaceType::Fill); - const u8* const texture_src_data = Memory::GetPhysicalPointer(addr); + const u8* const texture_src_data = VideoCore::g_memory->GetPhysicalPointer(addr); if (texture_src_data == nullptr) return; @@ -680,7 +680,7 @@ void CachedSurface::LoadGLBuffer(PAddr load_start, PAddr load_end) { MICROPROFILE_DEFINE(OpenGL_SurfaceFlush, "OpenGL", "Surface Flush", MP_RGB(128, 192, 64)); void CachedSurface::FlushGLBuffer(PAddr flush_start, PAddr flush_end) { - u8* const dst_buffer = Memory::GetPhysicalPointer(addr); + u8* const dst_buffer = VideoCore::g_memory->GetPhysicalPointer(addr); if (dst_buffer == nullptr) return; @@ -1718,9 +1718,11 @@ void RasterizerCacheOpenGL::UpdatePagesCachedCount(PAddr addr, u32 size, int del const u32 interval_size = interval_end_addr - interval_start_addr; if (delta > 0 && count == delta) - Memory::RasterizerMarkRegionCached(interval_start_addr, interval_size, true); + VideoCore::g_memory->RasterizerMarkRegionCached(interval_start_addr, interval_size, + true); else if (delta < 0 && count == -delta) - Memory::RasterizerMarkRegionCached(interval_start_addr, interval_size, false); + VideoCore::g_memory->RasterizerMarkRegionCached(interval_start_addr, interval_size, + false); else ASSERT(count >= 0); } diff --git a/src/video_core/renderer_opengl/renderer_opengl.cpp b/src/video_core/renderer_opengl/renderer_opengl.cpp index c764aee5a..1b00695d7 100644 --- a/src/video_core/renderer_opengl/renderer_opengl.cpp +++ b/src/video_core/renderer_opengl/renderer_opengl.cpp @@ -228,7 +228,7 @@ void RendererOpenGL::LoadFBToScreenInfo(const GPU::Regs::FramebufferConfig& fram Memory::RasterizerFlushRegion(framebuffer_addr, framebuffer.stride * framebuffer.height); - const u8* framebuffer_data = Memory::GetPhysicalPointer(framebuffer_addr); + const u8* framebuffer_data = VideoCore::g_memory->GetPhysicalPointer(framebuffer_addr); state.texture_units[0].texture_2d = screen_info.texture.resource.handle; state.Apply(); diff --git a/src/video_core/swrasterizer/framebuffer.cpp b/src/video_core/swrasterizer/framebuffer.cpp index 509d2ce45..1365a9835 100644 --- a/src/video_core/swrasterizer/framebuffer.cpp +++ b/src/video_core/swrasterizer/framebuffer.cpp @@ -14,6 +14,7 @@ #include "video_core/regs_framebuffer.h" #include "video_core/swrasterizer/framebuffer.h" #include "video_core/utils.h" +#include "video_core/video_core.h" namespace Pica { namespace Rasterizer { @@ -31,7 +32,7 @@ void DrawPixel(int x, int y, const Math::Vec4& color) { GPU::Regs::BytesPerPixel(GPU::Regs::PixelFormat(framebuffer.color_format.Value())); u32 dst_offset = VideoCore::GetMortonOffset(x, y, bytes_per_pixel) + coarse_y * framebuffer.width * bytes_per_pixel; - u8* dst_pixel = Memory::GetPhysicalPointer(addr) + dst_offset; + u8* dst_pixel = VideoCore::g_memory->GetPhysicalPointer(addr) + dst_offset; switch (framebuffer.color_format) { case FramebufferRegs::ColorFormat::RGBA8: @@ -72,7 +73,7 @@ const Math::Vec4 GetPixel(int x, int y) { GPU::Regs::BytesPerPixel(GPU::Regs::PixelFormat(framebuffer.color_format.Value())); u32 src_offset = VideoCore::GetMortonOffset(x, y, bytes_per_pixel) + coarse_y * framebuffer.width * bytes_per_pixel; - u8* src_pixel = Memory::GetPhysicalPointer(addr) + src_offset; + u8* src_pixel = VideoCore::g_memory->GetPhysicalPointer(addr) + src_offset; switch (framebuffer.color_format) { case FramebufferRegs::ColorFormat::RGBA8: @@ -102,7 +103,7 @@ const Math::Vec4 GetPixel(int x, int y) { u32 GetDepth(int x, int y) { const auto& framebuffer = g_state.regs.framebuffer.framebuffer; const PAddr addr = framebuffer.GetDepthBufferPhysicalAddress(); - u8* depth_buffer = Memory::GetPhysicalPointer(addr); + u8* depth_buffer = VideoCore::g_memory->GetPhysicalPointer(addr); y = framebuffer.height - y; @@ -131,7 +132,7 @@ u32 GetDepth(int x, int y) { u8 GetStencil(int x, int y) { const auto& framebuffer = g_state.regs.framebuffer.framebuffer; const PAddr addr = framebuffer.GetDepthBufferPhysicalAddress(); - u8* depth_buffer = Memory::GetPhysicalPointer(addr); + u8* depth_buffer = VideoCore::g_memory->GetPhysicalPointer(addr); y = framebuffer.height - y; @@ -158,7 +159,7 @@ u8 GetStencil(int x, int y) { void SetDepth(int x, int y, u32 value) { const auto& framebuffer = g_state.regs.framebuffer.framebuffer; const PAddr addr = framebuffer.GetDepthBufferPhysicalAddress(); - u8* depth_buffer = Memory::GetPhysicalPointer(addr); + u8* depth_buffer = VideoCore::g_memory->GetPhysicalPointer(addr); y = framebuffer.height - y; @@ -193,7 +194,7 @@ void SetDepth(int x, int y, u32 value) { void SetStencil(int x, int y, u8 value) { const auto& framebuffer = g_state.regs.framebuffer.framebuffer; const PAddr addr = framebuffer.GetDepthBufferPhysicalAddress(); - u8* depth_buffer = Memory::GetPhysicalPointer(addr); + u8* depth_buffer = VideoCore::g_memory->GetPhysicalPointer(addr); y = framebuffer.height - y; @@ -384,7 +385,7 @@ void DrawShadowMapPixel(int x, int y, u32 depth, u8 stencil) { u32 bytes_per_pixel = 4; u32 dst_offset = VideoCore::GetMortonOffset(x, y, bytes_per_pixel) + coarse_y * framebuffer.width * bytes_per_pixel; - u8* dst_pixel = Memory::GetPhysicalPointer(addr) + dst_offset; + u8* dst_pixel = VideoCore::g_memory->GetPhysicalPointer(addr) + dst_offset; auto ref = DecodeD24S8Shadow(dst_pixel); u32 ref_z = ref.x; diff --git a/src/video_core/swrasterizer/rasterizer.cpp b/src/video_core/swrasterizer/rasterizer.cpp index 53ddfd8d5..52650926d 100644 --- a/src/video_core/swrasterizer/rasterizer.cpp +++ b/src/video_core/swrasterizer/rasterizer.cpp @@ -30,6 +30,7 @@ #include "video_core/swrasterizer/texturing.h" #include "video_core/texture/texture_decode.h" #include "video_core/utils.h" +#include "video_core/video_core.h" namespace Pica { namespace Rasterizer { @@ -402,7 +403,8 @@ static void ProcessTriangleInternal(const Vertex& v0, const Vertex& v1, const Ve t = texture.config.height - 1 - GetWrappedTexCoord(texture.config.wrap_t, t, texture.config.height); - const u8* texture_data = Memory::GetPhysicalPointer(texture_address); + const u8* texture_data = + VideoCore::g_memory->GetPhysicalPointer(texture_address); auto info = Texture::TextureInfo::FromPicaRegister(texture.config, texture.format); diff --git a/src/video_core/vertex_loader.cpp b/src/video_core/vertex_loader.cpp index a6cfd6080..7c65defc5 100644 --- a/src/video_core/vertex_loader.cpp +++ b/src/video_core/vertex_loader.cpp @@ -13,6 +13,7 @@ #include "video_core/regs_pipeline.h" #include "video_core/shader/shader.h" #include "video_core/vertex_loader.h" +#include "video_core/video_core.h" namespace Pica { @@ -95,32 +96,32 @@ void VertexLoader::LoadVertex(u32 base_address, int index, int vertex, switch (vertex_attribute_formats[i]) { case PipelineRegs::VertexAttributeFormat::BYTE: { - const s8* srcdata = - reinterpret_cast(Memory::GetPhysicalPointer(source_addr)); + const s8* srcdata = reinterpret_cast( + VideoCore::g_memory->GetPhysicalPointer(source_addr)); for (unsigned int comp = 0; comp < vertex_attribute_elements[i]; ++comp) { input.attr[i][comp] = float24::FromFloat32(srcdata[comp]); } break; } case PipelineRegs::VertexAttributeFormat::UBYTE: { - const u8* srcdata = - reinterpret_cast(Memory::GetPhysicalPointer(source_addr)); + const u8* srcdata = reinterpret_cast( + VideoCore::g_memory->GetPhysicalPointer(source_addr)); for (unsigned int comp = 0; comp < vertex_attribute_elements[i]; ++comp) { input.attr[i][comp] = float24::FromFloat32(srcdata[comp]); } break; } case PipelineRegs::VertexAttributeFormat::SHORT: { - const s16* srcdata = - reinterpret_cast(Memory::GetPhysicalPointer(source_addr)); + const s16* srcdata = reinterpret_cast( + VideoCore::g_memory->GetPhysicalPointer(source_addr)); for (unsigned int comp = 0; comp < vertex_attribute_elements[i]; ++comp) { input.attr[i][comp] = float24::FromFloat32(srcdata[comp]); } break; } case PipelineRegs::VertexAttributeFormat::FLOAT: { - const float* srcdata = - reinterpret_cast(Memory::GetPhysicalPointer(source_addr)); + const float* srcdata = reinterpret_cast( + VideoCore::g_memory->GetPhysicalPointer(source_addr)); for (unsigned int comp = 0; comp < vertex_attribute_elements[i]; ++comp) { input.attr[i][comp] = float24::FromFloat32(srcdata[comp]); } diff --git a/src/video_core/video_core.cpp b/src/video_core/video_core.cpp index e9bc65f6e..fa68e1d1f 100644 --- a/src/video_core/video_core.cpp +++ b/src/video_core/video_core.cpp @@ -29,8 +29,11 @@ void* g_screenshot_bits; std::function g_screenshot_complete_callback; Layout::FramebufferLayout g_screenshot_framebuffer_layout; +Memory::MemorySystem* g_memory; + /// Initialize the video core -Core::System::ResultStatus Init(EmuWindow& emu_window) { +Core::System::ResultStatus Init(EmuWindow& emu_window, Memory::MemorySystem& memory) { + g_memory = &memory; Pica::Init(); g_renderer = std::make_unique(emu_window); diff --git a/src/video_core/video_core.h b/src/video_core/video_core.h index 0c582f1fc..f8aba0fbe 100644 --- a/src/video_core/video_core.h +++ b/src/video_core/video_core.h @@ -12,6 +12,10 @@ class EmuWindow; class RendererBase; +namespace Memory { +class MemorySystem; +} + //////////////////////////////////////////////////////////////////////////////////////////////////// // Video Core namespace @@ -33,8 +37,10 @@ extern void* g_screenshot_bits; extern std::function g_screenshot_complete_callback; extern Layout::FramebufferLayout g_screenshot_framebuffer_layout; +extern Memory::MemorySystem* g_memory; + /// Initialize the video core -Core::System::ResultStatus Init(EmuWindow& emu_window); +Core::System::ResultStatus Init(EmuWindow& emu_window, Memory::MemorySystem& memory); /// Shutdown the video core void Shutdown();