suyu/src/core/hle/service/lm/lm.cpp
Lioncash b05bfc6036 core/memory: Migrate over Read{8, 16, 32, 64, Block} to the Memory class
With all of the trivial parts of the memory interface moved over, we can
get right into moving over the bits that are used.

Note that this does require the use of GetInstance from the global
system instance to be used within hle_ipc.cpp and the gdbstub. This is
fine for the time being, as they both already rely on the global system
instance in other functions. These will be removed in a change directed
at both of these respectively.

For now, it's sufficient, as it still accomplishes the goal of
de-globalizing the memory code.
2019-11-26 21:55:39 -05:00

112 lines
3.3 KiB
C++

// Copyright 2018 yuzu emulator team
// Licensed under GPLv2 or any later version
// Refer to the license.txt file included.
#include <sstream>
#include <string>
#include "common/logging/log.h"
#include "common/scope_exit.h"
#include "core/hle/ipc_helpers.h"
#include "core/hle/service/lm/lm.h"
#include "core/hle/service/lm/manager.h"
#include "core/hle/service/service.h"
#include "core/memory.h"
namespace Service::LM {
class ILogger final : public ServiceFramework<ILogger> {
public:
explicit ILogger(Manager& manager_, Memory::Memory& memory_)
: ServiceFramework("ILogger"), manager{manager_}, memory{memory_} {
static const FunctionInfo functions[] = {
{0, &ILogger::Log, "Log"},
{1, &ILogger::SetDestination, "SetDestination"},
};
RegisterHandlers(functions);
}
private:
void Log(Kernel::HLERequestContext& ctx) {
// This function only succeeds - Get that out of the way
IPC::ResponseBuilder rb{ctx, 2};
rb.Push(RESULT_SUCCESS);
// Read MessageHeader, despite not doing anything with it right now
MessageHeader header{};
VAddr addr{ctx.BufferDescriptorX()[0].Address()};
const VAddr end_addr{addr + ctx.BufferDescriptorX()[0].size};
memory.ReadBlock(addr, &header, sizeof(MessageHeader));
addr += sizeof(MessageHeader);
FieldMap fields;
while (addr < end_addr) {
const auto field = static_cast<Field>(memory.Read8(addr++));
const auto length = memory.Read8(addr++);
if (static_cast<Field>(memory.Read8(addr)) == Field::Skip) {
++addr;
}
SCOPE_EXIT({ addr += length; });
if (field == Field::Skip) {
continue;
}
std::vector<u8> data(length);
memory.ReadBlock(addr, data.data(), length);
fields.emplace(field, std::move(data));
}
manager.Log({header, std::move(fields)});
}
void SetDestination(Kernel::HLERequestContext& ctx) {
IPC::RequestParser rp{ctx};
const auto destination = rp.PopEnum<DestinationFlag>();
LOG_DEBUG(Service_LM, "called, destination={:08X}", static_cast<u32>(destination));
manager.SetDestination(destination);
IPC::ResponseBuilder rb{ctx, 2};
rb.Push(RESULT_SUCCESS);
}
Manager& manager;
Memory::Memory& memory;
};
class LM final : public ServiceFramework<LM> {
public:
explicit LM(Manager& manager_, Memory::Memory& memory_)
: ServiceFramework{"lm"}, manager{manager_}, memory{memory_} {
// clang-format off
static const FunctionInfo functions[] = {
{0, &LM::OpenLogger, "OpenLogger"},
};
// clang-format on
RegisterHandlers(functions);
}
private:
void OpenLogger(Kernel::HLERequestContext& ctx) {
LOG_DEBUG(Service_LM, "called");
IPC::ResponseBuilder rb{ctx, 2, 0, 1};
rb.Push(RESULT_SUCCESS);
rb.PushIpcInterface<ILogger>(manager, memory);
}
Manager& manager;
Memory::Memory& memory;
};
void InstallInterfaces(Core::System& system) {
std::make_shared<LM>(system.GetLogManager(), system.Memory())
->InstallAsService(system.ServiceManager());
}
} // namespace Service::LM