Merge branch 'ipc-hle-hacks'
Thanks skid_au for testing and helping think of the solution! Fixes Issue 4608. Fixes Issue 5050. Fixes Issue 5103.
This commit is contained in:
commit
ca46a34dde
|
@ -55,7 +55,7 @@ namespace BootManager
|
|||
struct ConfigCache
|
||||
{
|
||||
bool valid, bCPUThread, bSkipIdle, bEnableFPRF, bMMU, bDCBZOFF,
|
||||
bVBeam, bFastDiscSpeed, bMergeBlocks, bDSPHLE, bDisableWiimoteSpeaker, bHLE_BS2;
|
||||
bVBeam, bFastDiscSpeed, bMergeBlocks, bDSPHLE, bHLE_BS2;
|
||||
int iTLBHack, iCPUCore;
|
||||
std::string strBackend;
|
||||
};
|
||||
|
@ -98,7 +98,6 @@ bool BootCore(const std::string& _rFilename)
|
|||
config_cache.bFastDiscSpeed = StartUp.bFastDiscSpeed;
|
||||
config_cache.bMergeBlocks = StartUp.bMergeBlocks;
|
||||
config_cache.bDSPHLE = StartUp.bDSPHLE;
|
||||
config_cache.bDisableWiimoteSpeaker = StartUp.bDisableWiimoteSpeaker;
|
||||
config_cache.strBackend = StartUp.m_strVideoBackend;
|
||||
config_cache.bHLE_BS2 = StartUp.bHLE_BS2;
|
||||
|
||||
|
@ -113,7 +112,6 @@ bool BootCore(const std::string& _rFilename)
|
|||
game_ini.Get("Core", "FastDiscSpeed", &StartUp.bFastDiscSpeed, StartUp.bFastDiscSpeed);
|
||||
game_ini.Get("Core", "BlockMerging", &StartUp.bMergeBlocks, StartUp.bMergeBlocks);
|
||||
game_ini.Get("Core", "DSPHLE", &StartUp.bDSPHLE, StartUp.bDSPHLE);
|
||||
game_ini.Get("Wii", "DisableWiimoteSpeaker",&StartUp.bDisableWiimoteSpeaker, StartUp.bDisableWiimoteSpeaker);
|
||||
game_ini.Get("Core", "GFXBackend", &StartUp.m_strVideoBackend, StartUp.m_strVideoBackend.c_str());
|
||||
game_ini.Get("Core", "CPUCore", &StartUp.iCPUCore, StartUp.iCPUCore);
|
||||
game_ini.Get("Core", "HLE_BS2", &StartUp.bHLE_BS2, StartUp.bHLE_BS2);
|
||||
|
@ -173,7 +171,6 @@ void Stop()
|
|||
StartUp.bFastDiscSpeed = config_cache.bFastDiscSpeed;
|
||||
StartUp.bMergeBlocks = config_cache.bMergeBlocks;
|
||||
StartUp.bDSPHLE = config_cache.bDSPHLE;
|
||||
StartUp.bDisableWiimoteSpeaker = config_cache.bDisableWiimoteSpeaker;
|
||||
StartUp.m_strVideoBackend = config_cache.strBackend;
|
||||
VideoBackend::ActivateBackend(StartUp.m_strVideoBackend);
|
||||
StartUp.bHLE_BS2 = config_cache.bHLE_BS2;
|
||||
|
|
|
@ -51,8 +51,8 @@ SCoreStartupParameter::SCoreStartupParameter()
|
|||
bRunCompareServer(false), bRunCompareClient(false),
|
||||
bMMU(false), bDCBZOFF(false), iTLBHack(0), bVBeam(false),
|
||||
bFastDiscSpeed(false),
|
||||
SelectedLanguage(0), bWii(false), bDisableWiimoteSpeaker(false),
|
||||
bConfirmStop(false), bHideCursor(false),
|
||||
SelectedLanguage(0), bWii(false),
|
||||
bConfirmStop(false), bHideCursor(false),
|
||||
bAutoHideCursor(false), bUsePanicHandlers(true), bOnScreenDisplayMessages(true),
|
||||
iRenderWindowXPos(-1), iRenderWindowYPos(-1),
|
||||
iRenderWindowWidth(640), iRenderWindowHeight(480),
|
||||
|
@ -99,8 +99,6 @@ void SCoreStartupParameter::LoadDefaults()
|
|||
bJITPairedOff = false;
|
||||
bJITSystemRegistersOff = false;
|
||||
|
||||
bDisableWiimoteSpeaker = false;
|
||||
|
||||
m_strName = "NONE";
|
||||
m_strUniqueID = "00000000";
|
||||
}
|
||||
|
|
|
@ -121,7 +121,6 @@ struct SCoreStartupParameter
|
|||
int SelectedLanguage;
|
||||
|
||||
bool bWii;
|
||||
bool bDisableWiimoteSpeaker;
|
||||
|
||||
// Interface settings
|
||||
bool bConfirmStop, bHideCursor, bAutoHideCursor, bUsePanicHandlers, bOnScreenDisplayMessages;
|
||||
|
|
|
@ -248,15 +248,13 @@ void Init()
|
|||
DSP_PERIOD = (int)(GetTicksPerSecond() * 0.003f);
|
||||
|
||||
// AyuanX: TO BE TWEAKED
|
||||
// Now the 1500 is a pure assumption
|
||||
// Now the 1500 is (was) a pure assumption
|
||||
// We need to figure out the real frequency though
|
||||
|
||||
// FIXME: does Wiimote Speaker support really require a different interval? (issue 4608)
|
||||
const int interval = SConfig::GetInstance().m_LocalCoreStartupParameter.
|
||||
bDisableWiimoteSpeaker ? 15000 : 4000;
|
||||
const int freq = 8000;
|
||||
const int fields = SConfig::GetInstance().m_LocalCoreStartupParameter.
|
||||
bVBeam ? 2 : 1;
|
||||
IPC_HLE_PERIOD = GetTicksPerSecond() / (interval * fields);
|
||||
IPC_HLE_PERIOD = GetTicksPerSecond() / (freq * fields);
|
||||
}
|
||||
else
|
||||
{
|
||||
|
|
|
@ -58,6 +58,8 @@ They will also generate a true or false return for UpdateInterrupts() in WII_IPC
|
|||
#include "../HW/WII_IPC.h"
|
||||
#include "../Debugger/Debugger_SymbolMap.h"
|
||||
#include "../PowerPC/PowerPC.h"
|
||||
#include "../HW/SystemTimers.h"
|
||||
#include "CoreTiming.h"
|
||||
|
||||
|
||||
namespace WII_IPC_HLE_Interface
|
||||
|
@ -80,8 +82,17 @@ typedef std::deque<u32> ipc_msg_queue;
|
|||
static ipc_msg_queue request_queue; // ppc -> arm
|
||||
static ipc_msg_queue reply_queue; // arm -> ppc
|
||||
|
||||
static int enque_reply;
|
||||
|
||||
void EnqueReplyCallback(u64 userdata, int)
|
||||
{
|
||||
reply_queue.push_back(userdata);
|
||||
}
|
||||
|
||||
void Init()
|
||||
{
|
||||
enque_reply = CoreTiming::RegisterEvent("IPCReply", EnqueReplyCallback);
|
||||
|
||||
_dbg_assert_msg_(WII_IPC_HLE, g_DeviceMap.empty(), "DeviceMap isnt empty on init");
|
||||
CWII_IPC_HLE_Device_es::m_ContentFile = "";
|
||||
u32 i;
|
||||
|
@ -504,7 +515,7 @@ void ExecuteCommand(u32 _Address)
|
|||
if (CmdSuccess)
|
||||
{
|
||||
// Generate a reply to the IPC command
|
||||
EnqReply(_Address);
|
||||
EnqReply(_Address, SystemTimers::GetTicksPerSecond() / 150);
|
||||
}
|
||||
else
|
||||
{
|
||||
|
@ -526,9 +537,9 @@ void EnqRequest(u32 _Address)
|
|||
}
|
||||
|
||||
// Called when IOS module has some reply
|
||||
void EnqReply(u32 _Address)
|
||||
void EnqReply(u32 _Address, int cycles_in_future)
|
||||
{
|
||||
reply_queue.push_back(_Address);
|
||||
CoreTiming::ScheduleEvent(cycles_in_future, enque_reply, _Address);
|
||||
}
|
||||
|
||||
// This is called every IPC_HLE_PERIOD from SystemTimers.cpp
|
||||
|
|
|
@ -62,7 +62,7 @@ void UpdateDevices();
|
|||
void ExecuteCommand(u32 _Address);
|
||||
|
||||
void EnqRequest(u32 _Address);
|
||||
void EnqReply(u32 _Address);
|
||||
void EnqReply(u32 _Address, int cycles_in_future = 0);
|
||||
|
||||
enum ECommandType
|
||||
{
|
||||
|
|
|
@ -336,23 +336,23 @@ void CWII_IPC_HLE_Device_usb_oh1_57e_305::SendToDevice(u16 _ConnectionHandle, u8
|
|||
pWiiMote->ExecuteL2capCmd(_pData, _Size);
|
||||
}
|
||||
|
||||
// Here we send ACL packets to CPU. They will consist of header + data.
|
||||
// The header is for example 07 00 41 00 which means size 0x0007 and channel 0x0041.
|
||||
// ---------------------------------------------------
|
||||
// AyuanX: Basically, our WII_IPC_HLE is efficient enough to send the packet immediately
|
||||
// rather than enqueue it to some other memory
|
||||
// But...the only exception comes from the Wiimote_Plugin
|
||||
void CWII_IPC_HLE_Device_usb_oh1_57e_305::IncDataPacket(u16 _ConnectionHandle)
|
||||
{
|
||||
m_PacketCount[_ConnectionHandle & 0xff]++;
|
||||
|
||||
// I don't think this makes sense or should be necessary
|
||||
// m_PacketCount refers to "completed" packets and is not related to some buffer size, yes?
|
||||
#if 0
|
||||
if (m_PacketCount[_ConnectionHandle & 0xff] > (unsigned int)m_acl_pkts_num)
|
||||
{
|
||||
DEBUG_LOG(WII_IPC_WIIMOTE, "ACL buffer overflow");
|
||||
m_PacketCount[_ConnectionHandle & 0xff] = m_acl_pkts_num;
|
||||
}
|
||||
#endif
|
||||
}
|
||||
|
||||
// Here we send ACL packets to CPU. They will consist of header + data.
|
||||
// The header is for example 07 00 41 00 which means size 0x0007 and channel 0x0041.
|
||||
void CWII_IPC_HLE_Device_usb_oh1_57e_305::SendACLPacket(u16 _ConnectionHandle, u8* _pData, u32 _Size)
|
||||
{
|
||||
DEBUG_LOG(WII_IPC_WIIMOTE, "ACL packet from %x ready to send to stack...", _ConnectionHandle);
|
||||
|
@ -374,8 +374,7 @@ void CWII_IPC_HLE_Device_usb_oh1_57e_305::SendACLPacket(u16 _ConnectionHandle, u
|
|||
}
|
||||
else
|
||||
{
|
||||
DEBUG_LOG(WII_IPC_WIIMOTE, "ACL endpoint not currently valid, "
|
||||
"queueing(%d)...", m_acl_pool.GetWritePos());
|
||||
DEBUG_LOG(WII_IPC_WIIMOTE, "ACL endpoint not currently valid, queueing...");
|
||||
m_acl_pool.Store(_pData, _Size, _ConnectionHandle);
|
||||
}
|
||||
}
|
||||
|
@ -486,18 +485,8 @@ u32 CWII_IPC_HLE_Device_usb_oh1_57e_305::Update()
|
|||
}
|
||||
}
|
||||
|
||||
// The Real Wiimote sends report every ~6.66ms (150 Hz).
|
||||
// However, we don't actually reach here at dependable intervals, so we
|
||||
// instead just timeslice in such a way that makes the stack think we have
|
||||
// perfect "radio quality" (WPADGetRadioSensitivity) and yet still have some
|
||||
// idle time.
|
||||
// Somehow, Dolphin's Wiimote Speaker support requires using an update interval
|
||||
// of 5ms (200 Hz) for its output to work. This increased frequency tends to
|
||||
// fill the ACL queue (even) quicker than it can be processed by Dolphin,
|
||||
// especially during simultaneous requests involving many (emulated) Wiimotes...
|
||||
// Thus, we only use that interval when the option is enabled. See issue 4608.
|
||||
const u64 interval = SystemTimers::GetTicksPerSecond() / (SConfig::GetInstance().
|
||||
m_LocalCoreStartupParameter.bDisableWiimoteSpeaker ? 150 : 200);
|
||||
// The Real Wiimote sends report every ~5ms (200 Hz).
|
||||
const u64 interval = SystemTimers::GetTicksPerSecond() / 200;
|
||||
const u64 each_wiimote_interval = interval / m_WiiMotes.size();
|
||||
const u64 now = CoreTiming::GetTicks();
|
||||
|
||||
|
@ -518,25 +507,47 @@ u32 CWII_IPC_HLE_Device_usb_oh1_57e_305::Update()
|
|||
return packet_transferred;
|
||||
}
|
||||
|
||||
void CWII_IPC_HLE_Device_usb_oh1_57e_305::ACLPool::Store(const u8* data, const u16 size, const u16 conn_handle)
|
||||
{
|
||||
if (m_queue.size() >= 100)
|
||||
{
|
||||
// Many simultaneous exchanges of ACL packets tend to cause the queue to fill up.
|
||||
ERROR_LOG(WII_IPC_WIIMOTE, "ACL queue size reached 100 - current packet will be dropped!");
|
||||
return;
|
||||
}
|
||||
|
||||
_dbg_assert_msg_(WII_IPC_WIIMOTE,
|
||||
size < m_acl_pkt_size, "acl packet too large for pool");
|
||||
|
||||
m_queue.push_back(Packet());
|
||||
auto& packet = m_queue.back();
|
||||
|
||||
std::copy(data, data + size, packet.data);
|
||||
packet.size = size;
|
||||
packet.conn_handle = conn_handle;
|
||||
}
|
||||
|
||||
void CWII_IPC_HLE_Device_usb_oh1_57e_305::ACLPool::WriteToEndpoint(CtrlBuffer& endpoint)
|
||||
{
|
||||
const u8 *data = m_pool + m_acl_pkt_size * m_read_ptr;
|
||||
const u16 size = m_info[m_read_ptr].size;
|
||||
const u16 conn_handle = m_info[m_read_ptr].conn_handle;
|
||||
auto& packet = m_queue.front();
|
||||
|
||||
const u8* const data = packet.data;
|
||||
const u16 size = packet.size;
|
||||
const u16 conn_handle = packet.conn_handle;
|
||||
|
||||
DEBUG_LOG(WII_IPC_WIIMOTE, "ACL packet being written from "
|
||||
"queue(%d) to %08x", GetReadPos(), endpoint.m_address);
|
||||
"queue to %08x", endpoint.m_address);
|
||||
|
||||
hci_acldata_hdr_t* pHeader = (hci_acldata_hdr_t*)Memory::GetPointer(endpoint.m_buffer);
|
||||
pHeader->con_handle = HCI_MK_CON_HANDLE(conn_handle, HCI_PACKET_START, HCI_POINT2POINT);
|
||||
pHeader->length = size;
|
||||
|
||||
// Write the packet to the buffer
|
||||
memcpy((u8*)pHeader + sizeof(hci_acldata_hdr_t), data, pHeader->length);
|
||||
std::copy(data, data + size, (u8*)pHeader + sizeof(hci_acldata_hdr_t));
|
||||
|
||||
endpoint.SetRetVal(sizeof(hci_acldata_hdr_t) + size);
|
||||
|
||||
m_read_ptr = (m_read_ptr + 1) % m_acl_pkts_num;
|
||||
m_queue.pop_front();
|
||||
|
||||
WII_IPC_HLE_Interface::EnqReply(endpoint.m_address);
|
||||
endpoint.Invalidate();
|
||||
|
|
|
@ -17,9 +17,11 @@
|
|||
|
||||
#pragma once
|
||||
|
||||
#include "hci.h"
|
||||
#include <algorithm>
|
||||
#include <vector>
|
||||
#include <queue>
|
||||
|
||||
#include "hci.h"
|
||||
#include "WII_IPC_HLE.h"
|
||||
#include "WII_IPC_HLE_Device.h"
|
||||
#include "WII_IPC_HLE_WiiMote.h"
|
||||
|
@ -168,70 +170,33 @@ private:
|
|||
|
||||
class ACLPool
|
||||
{
|
||||
u8 m_pool[m_acl_pkt_size * m_acl_pkts_num];
|
||||
int m_read_ptr;
|
||||
int m_write_ptr;
|
||||
|
||||
struct
|
||||
struct Packet
|
||||
{
|
||||
u8 data[m_acl_pkt_size];
|
||||
u16 size;
|
||||
u16 conn_handle;
|
||||
} m_info[m_acl_pkts_num];
|
||||
};
|
||||
|
||||
std::deque<Packet> m_queue;
|
||||
|
||||
public:
|
||||
ACLPool()
|
||||
: m_read_ptr(0)
|
||||
, m_write_ptr(0)
|
||||
: m_queue()
|
||||
{}
|
||||
|
||||
void Store(const u8* data, const u16 size, const u16 conn_handle)
|
||||
{
|
||||
_dbg_assert_msg_(WII_IPC_WIIMOTE,
|
||||
size < m_acl_pkt_size, "acl packet too large for pool");
|
||||
|
||||
const int next_write_ptr = (m_write_ptr + 1) % m_acl_pkts_num;
|
||||
if (next_write_ptr == m_read_ptr)
|
||||
{
|
||||
// Many simultaneous exchanges of ACL packets tend to cause the
|
||||
// 10-packet limit to be exceeded. Typically, this occurs when
|
||||
// many emulated Wiimotes are requesting connections at once.
|
||||
// See issue 4608 for more info.
|
||||
ERROR_LOG(WII_IPC_WIIMOTE, "ACL queue is full - current packet will be "
|
||||
"dropped! (m_write_ptr(%d) was about to overlap m_read_ptr(%d))",
|
||||
m_write_ptr, m_read_ptr);
|
||||
return;
|
||||
}
|
||||
|
||||
memcpy(m_pool + m_acl_pkt_size * m_write_ptr, data, size);
|
||||
m_info[m_write_ptr].size = size;
|
||||
m_info[m_write_ptr].conn_handle = conn_handle;
|
||||
m_write_ptr = next_write_ptr;
|
||||
}
|
||||
void Store(const u8* data, const u16 size, const u16 conn_handle);
|
||||
|
||||
void WriteToEndpoint(CtrlBuffer& endpoint);
|
||||
|
||||
bool IsEmpty() const
|
||||
{
|
||||
return m_write_ptr == m_read_ptr;
|
||||
}
|
||||
|
||||
int GetWritePos() const
|
||||
{
|
||||
return m_write_ptr;
|
||||
}
|
||||
|
||||
int GetReadPos() const
|
||||
{
|
||||
return m_read_ptr;
|
||||
return m_queue.empty();
|
||||
}
|
||||
|
||||
// For SaveStates
|
||||
void DoState(PointerWrap &p)
|
||||
{
|
||||
p.Do(m_write_ptr);
|
||||
p.Do(m_read_ptr);
|
||||
p.DoArray((u8 *)m_pool, sizeof(m_pool));
|
||||
p.DoArray((u8 *)m_info, sizeof(m_info));
|
||||
p.Do(m_queue);
|
||||
}
|
||||
} m_acl_pool;
|
||||
|
||||
|
|
|
@ -70,8 +70,8 @@ static Common::Event g_compressAndDumpStateSyncEvent;
|
|||
|
||||
static std::thread g_save_thread;
|
||||
|
||||
// Don't forget to increase this after doing changes on the savestate system
|
||||
static const u32 STATE_VERSION = 10;
|
||||
// Don't forget to increase this after doing changes on the savestate system
|
||||
static const u32 STATE_VERSION = 11;
|
||||
|
||||
struct StateHeader
|
||||
{
|
||||
|
|
|
@ -328,8 +328,6 @@ void CISOProperties::CreateGUIControls(bool IsWad)
|
|||
|
||||
// Wii Console
|
||||
EnableWideScreen = new wxCheckBox(m_GameConfig, ID_ENABLEWIDESCREEN, _("Enable WideScreen"), wxDefaultPosition, wxDefaultSize, wxCHK_3STATE|wxCHK_ALLOW_3RD_STATE_FOR_USER, wxDefaultValidator);
|
||||
DisableWiimoteSpeaker = new wxCheckBox(m_GameConfig, ID_DISABLEWIIMOTESPEAKER, _("Alternate Wiimote Timing"), wxDefaultPosition, wxDefaultSize, wxCHK_3STATE|wxCHK_ALLOW_3RD_STATE_FOR_USER, wxDefaultValidator);
|
||||
DisableWiimoteSpeaker->SetToolTip(_("Mutes the Wiimote speaker. Fixes random disconnections on real wiimotes. No effect on emulated wiimotes."));
|
||||
|
||||
// Video
|
||||
UseBBox = new wxCheckBox(m_GameConfig, ID_USE_BBOX, _("Enable Bounding Box Calculation"), wxDefaultPosition, wxDefaultSize, wxCHK_3STATE|wxCHK_ALLOW_3RD_STATE_FOR_USER);
|
||||
|
@ -377,10 +375,8 @@ void CISOProperties::CreateGUIControls(bool IsWad)
|
|||
{
|
||||
sbWiiOverrides->ShowItems(false);
|
||||
EnableWideScreen->Hide();
|
||||
DisableWiimoteSpeaker->Hide();
|
||||
}
|
||||
sbWiiOverrides->Add(EnableWideScreen, 0, wxLEFT, 5);
|
||||
sbWiiOverrides->Add(DisableWiimoteSpeaker, 0, wxLEFT, 5);
|
||||
|
||||
wxStaticBoxSizer * const sbVideoOverrides =
|
||||
new wxStaticBoxSizer(wxVERTICAL, m_GameConfig, _("Video"));
|
||||
|
@ -966,11 +962,6 @@ void CISOProperties::LoadGameConfig()
|
|||
else
|
||||
EnableWideScreen->Set3StateValue(wxCHK_UNDETERMINED);
|
||||
|
||||
if (GameIni.Get("Wii", "DisableWiimoteSpeaker", &bTemp))
|
||||
DisableWiimoteSpeaker->Set3StateValue((wxCheckBoxState)bTemp);
|
||||
else
|
||||
DisableWiimoteSpeaker->Set3StateValue(wxCHK_UNDETERMINED);
|
||||
|
||||
if (GameIni.Get("Video", "UseBBox", &bTemp))
|
||||
UseBBox->Set3StateValue((wxCheckBoxState)bTemp);
|
||||
else
|
||||
|
@ -1059,11 +1050,6 @@ bool CISOProperties::SaveGameConfig()
|
|||
else
|
||||
GameIni.Set("Wii", "Widescreen", EnableWideScreen->Get3StateValue());
|
||||
|
||||
if (DisableWiimoteSpeaker->Get3StateValue() == wxCHK_UNDETERMINED)
|
||||
GameIni.DeleteKey("Wii", "DisableWiimoteSpeaker");
|
||||
else
|
||||
GameIni.Set("Wii", "DisableWiimoteSpeaker", DisableWiimoteSpeaker->Get3StateValue());
|
||||
|
||||
if (UseBBox->Get3StateValue() == wxCHK_UNDETERMINED)
|
||||
GameIni.DeleteKey("Video", "UseBBox");
|
||||
else
|
||||
|
|
|
@ -72,7 +72,7 @@ private:
|
|||
wxCheckBox *CPUThread, *SkipIdle, *MMU, *DCBZOFF, *TLBHack;
|
||||
wxCheckBox *VBeam, *FastDiscSpeed, *BlockMerging, *DSPHLE;
|
||||
// Wii
|
||||
wxCheckBox *EnableWideScreen, *DisableWiimoteSpeaker;
|
||||
wxCheckBox *EnableWideScreen;
|
||||
// Video
|
||||
wxCheckBox *UseZTPSpeedupHack, *PHackEnable, *UseBBox;
|
||||
wxButton *PHSettings;
|
||||
|
@ -139,7 +139,6 @@ private:
|
|||
ID_PHSETTINGS,
|
||||
ID_ENABLEPROGRESSIVESCAN,
|
||||
ID_ENABLEWIDESCREEN,
|
||||
ID_DISABLEWIIMOTESPEAKER,
|
||||
ID_EDITCONFIG,
|
||||
ID_EMUSTATE,
|
||||
ID_EMU_ISSUES,
|
||||
|
|
Loading…
Reference in New Issue