|
|
|
@ -18,20 +18,15 @@ |
|
|
|
|
|
|
|
namespace Service { |
|
|
|
|
|
|
|
/**
|
|
|
|
* Creates a function string for logging, complete with the name (or header code, depending |
|
|
|
* on what's passed in) the port name, and all the cmd_buff arguments. |
|
|
|
*/ |
|
|
|
[[maybe_unused]] static std::string MakeFunctionString(std::string_view name, |
|
|
|
std::string_view port_name, |
|
|
|
const u32* cmd_buff) { |
|
|
|
/// @brief Creates a function string for logging, complete with the name (or header code, depending
|
|
|
|
/// on what's passed in) the port name, and all the cmd_buff arguments.
|
|
|
|
[[maybe_unused]] static std::string MakeFunctionString(std::string_view name, std::string_view port_name, const u32* cmd_buff) { |
|
|
|
// Number of params == bits 0-5 + bits 6-11
|
|
|
|
int num_params = (cmd_buff[0] & 0x3F) + ((cmd_buff[0] >> 6) & 0x3F); |
|
|
|
|
|
|
|
std::string function_string = fmt::format("function '{}': port={}", name, port_name); |
|
|
|
for (int i = 1; i <= num_params; ++i) { |
|
|
|
for (int i = 1; i <= num_params; ++i) |
|
|
|
function_string += fmt::format(", cmd_buff[{}]={:#X}", i, cmd_buff[i]); |
|
|
|
} |
|
|
|
return function_string; |
|
|
|
} |
|
|
|
|
|
|
|
@ -46,21 +41,17 @@ ServiceFrameworkBase::~ServiceFrameworkBase() { |
|
|
|
} |
|
|
|
|
|
|
|
void ServiceFrameworkBase::RegisterHandlersBase(const FunctionInfoBase* functions, std::size_t n) { |
|
|
|
// Usually this array is sorted by id already, so hint to insert at the end
|
|
|
|
handlers.reserve(handlers.size() + n); |
|
|
|
for (std::size_t i = 0; i < n; ++i) { |
|
|
|
// Usually this array is sorted by id already, so hint to insert at the end
|
|
|
|
for (std::size_t i = 0; i < n; ++i) |
|
|
|
handlers.emplace_hint(handlers.cend(), functions[i].expected_header, functions[i]); |
|
|
|
} |
|
|
|
} |
|
|
|
|
|
|
|
void ServiceFrameworkBase::RegisterHandlersBaseTipc(const FunctionInfoBase* functions, |
|
|
|
std::size_t n) { |
|
|
|
void ServiceFrameworkBase::RegisterHandlersBaseTipc(const FunctionInfoBase* functions, std::size_t n) { |
|
|
|
// Usually this array is sorted by id already, so hint to insert at the end
|
|
|
|
handlers_tipc.reserve(handlers_tipc.size() + n); |
|
|
|
for (std::size_t i = 0; i < n; ++i) { |
|
|
|
// Usually this array is sorted by id already, so hint to insert at the end
|
|
|
|
handlers_tipc.emplace_hint(handlers_tipc.cend(), functions[i].expected_header, |
|
|
|
functions[i]); |
|
|
|
} |
|
|
|
for (std::size_t i = 0; i < n; ++i) |
|
|
|
handlers_tipc.emplace_hint(handlers_tipc.cend(), functions[i].expected_header, functions[i]); |
|
|
|
} |
|
|
|
|
|
|
|
void ServiceFrameworkBase::ReportUnimplementedFunction(HLERequestContext& ctx, |
|
|
|
@ -69,15 +60,12 @@ void ServiceFrameworkBase::ReportUnimplementedFunction(HLERequestContext& ctx, |
|
|
|
std::string function_name = info == nullptr ? "<unknown>" : info->name; |
|
|
|
|
|
|
|
fmt::memory_buffer buf; |
|
|
|
fmt::format_to(std::back_inserter(buf), "function '{}({})': port='{}' cmd_buf={{[0]={:#X}", |
|
|
|
ctx.GetCommand(), function_name, service_name, cmd_buf[0]); |
|
|
|
for (int i = 1; i <= 8; ++i) { |
|
|
|
fmt::format_to(std::back_inserter(buf), "function '{}({})': port='{}' cmd_buf={{[0]={:#X}", ctx.GetCommand(), function_name, service_name, cmd_buf[0]); |
|
|
|
for (int i = 1; i <= 8; ++i) |
|
|
|
fmt::format_to(std::back_inserter(buf), ", [{}]={:#X}", i, cmd_buf[i]); |
|
|
|
} |
|
|
|
buf.push_back('}'); |
|
|
|
|
|
|
|
system.GetReporter().SaveUnimplementedFunctionReport(ctx, ctx.GetCommand(), function_name, |
|
|
|
service_name); |
|
|
|
system.GetReporter().SaveUnimplementedFunctionReport(ctx, ctx.GetCommand(), function_name, service_name); |
|
|
|
UNIMPLEMENTED_MSG("Unknown / unimplemented {}", fmt::to_string(buf)); |
|
|
|
if (Settings::values.use_auto_stub) { |
|
|
|
LOG_WARNING(Service, "Using auto stub fallback!"); |
|
|
|
@ -87,26 +75,19 @@ void ServiceFrameworkBase::ReportUnimplementedFunction(HLERequestContext& ctx, |
|
|
|
} |
|
|
|
|
|
|
|
void ServiceFrameworkBase::InvokeRequest(HLERequestContext& ctx) { |
|
|
|
auto itr = handlers.find(ctx.GetCommand()); |
|
|
|
const FunctionInfoBase* info = itr == handlers.end() ? nullptr : &itr->second; |
|
|
|
if (info == nullptr || info->handler_callback == nullptr) { |
|
|
|
auto it = handlers.find(ctx.GetCommand()); |
|
|
|
FunctionInfoBase const* info = it == handlers.end() ? nullptr : std::adressof(it->second); |
|
|
|
if (info == nullptr || info->handler_callback == nullptr) |
|
|
|
return ReportUnimplementedFunction(ctx, info); |
|
|
|
} |
|
|
|
|
|
|
|
LOG_TRACE(Service, "{}", MakeFunctionString(info->name, GetServiceName(), ctx.CommandBuffer())); |
|
|
|
handler_invoker(this, info->handler_callback, ctx); |
|
|
|
} |
|
|
|
|
|
|
|
void ServiceFrameworkBase::InvokeRequestTipc(HLERequestContext& ctx) { |
|
|
|
boost::container::flat_map<u32, FunctionInfoBase>::iterator itr; |
|
|
|
|
|
|
|
itr = handlers_tipc.find(ctx.GetCommand()); |
|
|
|
|
|
|
|
const FunctionInfoBase* info = itr == handlers_tipc.end() ? nullptr : &itr->second; |
|
|
|
if (info == nullptr || info->handler_callback == nullptr) { |
|
|
|
auto it = handlers_tipc.find(ctx.GetCommand()); |
|
|
|
FunctionInfoBase const* info = it == handlers_tipc.end() ? nullptr : std::adressof(it->second); |
|
|
|
if (info == nullptr || info->handler_callback == nullptr) |
|
|
|
return ReportUnimplementedFunction(ctx, info); |
|
|
|
} |
|
|
|
|
|
|
|
LOG_TRACE(Service, "{}", MakeFunctionString(info->name, GetServiceName(), ctx.CommandBuffer())); |
|
|
|
handler_invoker(this, info->handler_callback, ctx); |
|
|
|
} |
|
|
|
|