Preserve formatted NAND boot and Wii Remote pairing, add DMA/SRAM conformance tests and a Wii comparison probe. Keep P1 profiling tools and native update A/B evidence; reject the unhelpful targeted SRAM shortcut.
88 lines
3.3 KiB
C++
88 lines
3.3 KiB
C++
// Copyright 2026 Dolphin Emulator Project
|
|
// SPDX-License-Identifier: GPL-2.0-or-later
|
|
// A local, user-mode-only trace for validating the provider without WPR rights.
|
|
#pragma once
|
|
|
|
#include <cstddef>
|
|
#include <cstring>
|
|
#include <filesystem>
|
|
#include <stdexcept>
|
|
#include <string>
|
|
#include <vector>
|
|
|
|
#include <windows.h>
|
|
#include <evntrace.h>
|
|
|
|
#include "Common/PerformanceTrace.h"
|
|
|
|
class PrivateETW
|
|
{
|
|
public:
|
|
explicit PrivateETW(const char* output)
|
|
{
|
|
if (!output)
|
|
return;
|
|
const auto path = std::filesystem::absolute(output);
|
|
if (std::filesystem::exists(path))
|
|
throw std::runtime_error("Private ETL target already exists");
|
|
if (!Common::PerformanceTrace::Requested())
|
|
throw std::runtime_error("Set DOLPHIN_PERF_TRACE=1 for a private trace");
|
|
Common::PerformanceTrace::Enabled(); // Register before starting the session.
|
|
constexpr wchar_t name[] = L"DolphinP1LocalProbe";
|
|
const std::wstring filename = path.wstring();
|
|
const size_t name_size = sizeof(name);
|
|
const size_t filename_size = (filename.size() + 1) * sizeof(wchar_t);
|
|
m_storage.resize(sizeof(EVENT_TRACE_PROPERTIES) + name_size + filename_size);
|
|
m_properties = reinterpret_cast<EVENT_TRACE_PROPERTIES*>(m_storage.data());
|
|
std::memset(m_properties, 0, m_storage.size());
|
|
m_properties->Wnode.BufferSize = static_cast<ULONG>(m_storage.size());
|
|
m_properties->Wnode.Guid = PERF_PROVIDER;
|
|
m_properties->Wnode.Flags = WNODE_FLAG_TRACED_GUID;
|
|
m_properties->Wnode.ClientContext = 1; // QPC
|
|
m_properties->BufferSize = 64;
|
|
m_properties->MinimumBuffers = 2;
|
|
m_properties->MaximumBuffers = 16;
|
|
m_properties->LogFileMode = EVENT_TRACE_FILE_MODE_SEQUENTIAL | EVENT_TRACE_PRIVATE_LOGGER_MODE |
|
|
EVENT_TRACE_PRIVATE_IN_PROC;
|
|
m_properties->LoggerNameOffset = sizeof(EVENT_TRACE_PROPERTIES);
|
|
m_properties->LogFileNameOffset =
|
|
static_cast<ULONG>(sizeof(EVENT_TRACE_PROPERTIES) + name_size);
|
|
std::memcpy(m_storage.data() + m_properties->LoggerNameOffset, name, name_size);
|
|
std::memcpy(m_storage.data() + m_properties->LogFileNameOffset, filename.c_str(),
|
|
filename_size);
|
|
const ULONG started = StartTraceW(&m_handle, name, m_properties);
|
|
if (started != ERROR_SUCCESS)
|
|
throw std::runtime_error("Private ETW StartTrace error " + std::to_string(started));
|
|
m_started = true;
|
|
const ULONG enabled =
|
|
EnableTraceEx2(m_handle, &PERF_PROVIDER, EVENT_CONTROL_CODE_ENABLE_PROVIDER,
|
|
TRACE_LEVEL_VERBOSE, 0, 0, 0, nullptr);
|
|
if (enabled != ERROR_SUCCESS || !Common::PerformanceTrace::Enabled())
|
|
{
|
|
Close();
|
|
throw std::runtime_error("Private ETW enable error " + std::to_string(enabled));
|
|
}
|
|
}
|
|
|
|
~PrivateETW() { Close(); }
|
|
PrivateETW(const PrivateETW&) = delete;
|
|
PrivateETW& operator=(const PrivateETW&) = delete;
|
|
|
|
bool Close()
|
|
{
|
|
if (!m_started)
|
|
return true;
|
|
m_started = false;
|
|
return ControlTraceW(m_handle, L"DolphinP1LocalProbe", m_properties,
|
|
EVENT_TRACE_CONTROL_STOP) == ERROR_SUCCESS;
|
|
}
|
|
|
|
private:
|
|
static constexpr GUID PERF_PROVIDER = {
|
|
0x54ee9231, 0x28be, 0x4ab0, {0x98, 0x1e, 0xb2, 0x6f, 0x97, 0x9c, 0x56, 0xa4}};
|
|
TRACEHANDLE m_handle = 0;
|
|
bool m_started = false;
|
|
EVENT_TRACE_PROPERTIES* m_properties = nullptr;
|
|
std::vector<u8> m_storage;
|
|
};
|