Compare commits

...

4 Commits

Author SHA1 Message Date
Dentomologist
1547b813bc
Merge 5dede61af7 into 80ea68b13c 2024-11-11 13:07:54 -06:00
JMC47
80ea68b13c
Merge pull request #13183 from Tilka/sync_on_fifo_reset
ProcessorInterface: sync GPU just before PI_FIFO_RESET
2024-11-11 00:38:26 -05:00
Tillmann Karras
fbce737415 ProcessorInterface: sync GPU just before PI_FIFO_RESET
GXAbortFrame() is problematic for Dolphin because it first writes
PI_FIFO_RESET (for which we discard our internal fifo), then disables CP
reads (for which we execute pending commands in the GP fifo in emulated
memory). I don't know whether there is a race condition on hardware, but
there is one for us. Avoid this by also doing a GPU sync here.
2024-11-09 03:29:05 +00:00
Dentomologist
5dede61af7 WiimoteWindows: Rework IsWiimote check to avoid Log spam
Only send requests for a status report if the device either has a valid
device name or a valid vendor_id/product_id combination.

This prevents Log spam of "Error on Writefile: Incorrect Function" or
"The parameter is incorrect" from other types of devices.
2023-09-07 14:38:18 -07:00
2 changed files with 54 additions and 0 deletions

View File

@ -98,6 +98,10 @@ void ProcessorInterfaceManager::RegisterMMIO(MMIO::Mapping* mmio, u32 base)
{
system.GetGPFifo().ResetGatherPipe();
// Assume that all bytes that made it into the GPU fifo did in fact execute
// before this MMIO write takes effect.
system.GetFifo().SyncGPUForRegisterAccess();
// Call Fifo::ResetVideoBuffer() from the video thread. Since that function
// resets various pointers used by the video thread, we can't call it directly
// from the CPU thread, so queue a task to do it instead. In single-core mode,

View File

@ -4,9 +4,12 @@
#include "Core/HW/WiimoteReal/IOWin.h"
#include <algorithm>
#include <array>
#include <cstdio>
#include <cstdlib>
#include <ctime>
#include <optional>
#include <string>
#include <unordered_map>
#include <unordered_set>
@ -424,6 +427,23 @@ WinWriteMethod GetInitialWriteMethod(bool IsUsingToshibaStack)
WWM_WRITE_FILE_ACTUAL_REPORT_SIZE);
}
std::optional<std::string> TryGetDeviceName(HANDLE handle)
{
// Buffers larger than 4093 bytes may cause HidD_GetProductString to fail according to
// https://learn.microsoft.com/en-us/windows-hardware/drivers/ddi/hidsdi/nf-hidsdi-hidd_getproductstring
// USB devices have a maximum string length of 127 (with null terminator) but the maximum length
// for Bluetooth or SPI devices isn't listed, so use the biggest valid buffer to be safe.
static constexpr auto PRODUCT_STRING_BUFFER_SIZE = 4093;
std::array<WCHAR, PRODUCT_STRING_BUFFER_SIZE> product_string_buffer;
const bool read_successful = pHidD_GetProductString(
handle, static_cast<PVOID>(product_string_buffer.data()), PRODUCT_STRING_BUFFER_SIZE);
if (!read_successful)
return std::nullopt;
return WStringToUTF8(product_string_buffer.data());
}
int WriteToHandle(HANDLE& dev_handle, WinWriteMethod& method, const u8* buf, size_t size)
{
OVERLAPPED hid_overlap_write = OVERLAPPED();
@ -454,6 +474,13 @@ int ReadFromHandle(HANDLE& dev_handle, u8* buf)
return read;
}
bool IsValidVendorIDAndProductID(const u16 vendor_id, const u16 product_id)
{
if (vendor_id != 0x057e)
return false;
return product_id == 0x0306 || product_id == 0x0330;
}
bool IsWiimote(const std::basic_string<TCHAR>& device_path, WinWriteMethod& method)
{
using namespace WiimoteCommon;
@ -466,6 +493,29 @@ bool IsWiimote(const std::basic_string<TCHAR>& device_path, WinWriteMethod& meth
Common::ScopeGuard handle_guard{[&dev_handle] { CloseHandle(dev_handle); }};
const std::optional<std::string> device_name_opt = TryGetDeviceName(dev_handle);
const std::string name = device_name_opt ? *device_name_opt : "NO_NAME";
const bool name_is_valid = device_name_opt && IsValidDeviceName(name);
HIDD_ATTRIBUTES attributes;
const bool read_successful = pHidD_GetAttributes(dev_handle, &attributes);
const u16 vendor_id = read_successful ? attributes.VendorID : 0;
const u16 product_id = read_successful ? attributes.ProductID : 0;
const bool is_valid_vendor_and_product = IsValidVendorIDAndProductID(vendor_id, product_id);
DEBUG_LOG_FMT(WIIMOTE, "IsWiimote() vendor_id: {:04x} product_id: {:04x} name: {}", vendor_id,
product_id, name);
if (!name_is_valid && !is_valid_vendor_and_product)
return false;
// The rest of this function is unnecessary but harmless for official Wii Remotes, but the
// DolphinBar doesn't properly sync until it responds correctly to a status request (which
// sometimes takes more than one attempt). We could return early if the name, vendor_id, and
// product_id all match those of an official Wii Remote, but it's possible some third party remote
// appears identical to an official one but also requires the following behavior. To be safe, go
// ahead and do it regardless.
u8 buf[MAX_PAYLOAD];
u8 const req_status_report[] = {WR_SET_REPORT | BT_OUTPUT, u8(OutputReportID::RequestStatus), 0};
int invalid_report_count = 0;