Merge branch 'master' into wxw3-update

Conflicts:
	Source/Core/DolphinWX/Src/LogWindow.cpp
This commit is contained in:
Shawn Hoffman
2012-03-22 17:57:38 -07:00
186 changed files with 1193 additions and 483 deletions
+21 -2
View File
@@ -18,6 +18,7 @@
#include "Common.h"
#include "DebugInterface.h"
#include "BreakPoints.h"
#include "../../Core/Src/PowerPC/JitCommon/JitBase.h"
#include <sstream>
bool BreakPoints::IsAddressBreakPoint(u32 _iAddress)
@@ -70,7 +71,11 @@ void BreakPoints::AddFromStrings(const TBreakPointsStr& bps)
void BreakPoints::Add(const TBreakPoint& bp)
{
if (!IsAddressBreakPoint(bp.iAddress))
{
m_BreakPoints.push_back(bp);
if (jit)
jit->GetBlockCache()->InvalidateICache(bp.iAddress, 4);
}
}
void BreakPoints::Add(u32 em_address, bool temp)
@@ -83,21 +88,35 @@ void BreakPoints::Add(u32 em_address, bool temp)
pt.iAddress = em_address;
m_BreakPoints.push_back(pt);
if (jit)
jit->GetBlockCache()->InvalidateICache(em_address, 4);
}
}
void BreakPoints::Remove(u32 _iAddress)
void BreakPoints::Remove(u32 em_address)
{
for (TBreakPoints::iterator i = m_BreakPoints.begin(); i != m_BreakPoints.end(); ++i)
{
if (i->iAddress == _iAddress)
if (i->iAddress == em_address)
{
m_BreakPoints.erase(i);
if (jit)
jit->GetBlockCache()->InvalidateICache(em_address, 4);
return;
}
}
}
void BreakPoints::Clear()
{
for (TBreakPoints::iterator i = m_BreakPoints.begin(); i != m_BreakPoints.end(); ++i)
{
if (jit)
jit->GetBlockCache()->InvalidateICache(i->iAddress, 4);
m_BreakPoints.erase(i);
}
}
MemChecks::TMemChecksStr MemChecks::GetStrings() const
{
+1 -1
View File
@@ -78,7 +78,7 @@ public:
// Remove Breakpoint
void Remove(u32 _iAddress);
void Clear() { m_BreakPoints.clear(); };
void Clear();
void DeleteByAddress(u32 _Address);
@@ -119,6 +119,7 @@ public:
virtual void Video_GatherPipeBursted() = 0;
virtual bool Video_IsPossibleWaitingSetDrawDone() = 0;
virtual bool Video_IsHiWatermarkActive() = 0;
virtual void Video_AbortFrame() = 0;
virtual readFn16 Video_CPRead16() = 0;
@@ -159,6 +160,7 @@ class VideoBackendHardware : public VideoBackend
void Video_GatherPipeBursted();
bool Video_IsPossibleWaitingSetDrawDone();
bool Video_IsHiWatermarkActive();
void Video_AbortFrame();
readFn16 Video_CPRead16();
+11 -2
View File
@@ -19,9 +19,9 @@
#include "ChunkFile.h"
#include "ProcessorInterface.h"
#include "Memmap.h"
#include "../PowerPC/PowerPC.h"
#include "VideoBackendBase.h"
#include "../PowerPC/JitCommon/JitBase.h"
#include "../PowerPC/PowerPC.h"
#include "GPFifo.h"
@@ -96,6 +96,15 @@ void STACKALIGN CheckGatherPipe()
// move back the spill bytes
memmove(m_gatherPipe, m_gatherPipe + cnt, m_gatherPipeCount);
// Profile where the FIFO writes are occurring.
if (jit && (jit->js.fifoWriteAddresses.find(PC)) == (jit->js.fifoWriteAddresses.end()))
{
jit->js.fifoWriteAddresses.insert(PC);
// Invalidate the JIT block so that it gets recompiled with the external exception check included.
jit->GetBlockCache()->InvalidateICache(PC, 4);
}
}
}
+252 -137
View File
@@ -68,8 +68,13 @@ TDeviceMap g_DeviceMap;
// STATE_TO_SAVE
typedef std::map<u32, std::string> TFileNameMap;
TFileNameMap g_FileNameMap;
u32 g_LastDeviceID;
#define IPC_MAX_FDS 0x18
#define ES_MAX_COUNT 2
IWII_IPC_HLE_Device* g_FdMap[IPC_MAX_FDS];
bool es_inuse[ES_MAX_COUNT];
IWII_IPC_HLE_Device* es_handles[ES_MAX_COUNT];
typedef std::deque<u32> ipc_msg_queue;
static ipc_msg_queue request_queue; // ppc -> arm
@@ -78,14 +83,28 @@ static ipc_msg_queue reply_queue; // arm -> ppc
void Init()
{
_dbg_assert_msg_(WII_IPC_HLE, g_DeviceMap.empty(), "DeviceMap isnt empty on init");
u32 i;
for (i=0; i<IPC_MAX_FDS; i++)
{
g_FdMap[i] = NULL;
}
u32 i = IPC_FIRST_HARDWARE_ID;
i = 0;
// Build hardware devices
g_DeviceMap[i] = new CWII_IPC_HLE_Device_usb_oh1_57e_305(i, std::string("/dev/usb/oh1/57e/305")); i++;
g_DeviceMap[i] = new CWII_IPC_HLE_Device_stm_immediate(i, std::string("/dev/stm/immediate")); i++;
g_DeviceMap[i] = new CWII_IPC_HLE_Device_stm_eventhook(i, std::string("/dev/stm/eventhook")); i++;
g_DeviceMap[i] = new CWII_IPC_HLE_Device_fs(i, std::string("/dev/fs")); i++;
g_DeviceMap[i] = new CWII_IPC_HLE_Device_es(i, std::string("/dev/es")); i++;
// IOS allows two ES devices at a time<
u32 j;
for (j=0; j<ES_MAX_COUNT; j++)
{
g_DeviceMap[i] = es_handles[j] = new CWII_IPC_HLE_Device_es(i, std::string("/dev/es")); i++;
es_inuse[j] = false;
}
g_DeviceMap[i] = new CWII_IPC_HLE_Device_di(i, std::string("/dev/di")); i++;
g_DeviceMap[i] = new CWII_IPC_HLE_Device_net_kd_request(i, std::string("/dev/net/kd/request")); i++;
g_DeviceMap[i] = new CWII_IPC_HLE_Device_net_kd_time(i, std::string("/dev/net/kd/time")); i++;
@@ -96,13 +115,24 @@ void Init()
g_DeviceMap[i] = new CWII_IPC_HLE_Device_stub(i, std::string("/dev/sdio/slot1")); i++;
g_DeviceMap[i] = new CWII_IPC_HLE_Device_stub(i, std::string("/dev/usb/hid")); i++;
g_DeviceMap[i] = new CWII_IPC_HLE_Device_stub(i, std::string("/dev/usb/oh1")); i++;
g_DeviceMap[i] = new IWII_IPC_HLE_Device(i, std::string("_Unimplemented_Device_"));
g_LastDeviceID = IPC_FIRST_FILEIO_ID;
g_DeviceMap[i] = new IWII_IPC_HLE_Device(i, std::string("_Unimplemented_Device_")); i++;
}
void Reset(bool _bHard)
{
u32 i;
for (i=0; i<IPC_MAX_FDS; i++)
{
if (g_FdMap[i] != NULL && !g_FdMap[i]->IsHardware())
{
// close all files and delete their resources
g_FdMap[i]->Close(0, true);
delete g_FdMap[i];
}
g_FdMap[i] = NULL;
}
TDeviceMap::iterator itr = g_DeviceMap.begin();
while (itr != g_DeviceMap.end())
{
@@ -111,21 +141,17 @@ void Reset(bool _bHard)
// Force close
itr->second->Close(0, true);
// Hardware should not be deleted unless it is a hard reset
if (_bHard || !itr->second->IsHardware())
if (_bHard)
delete itr->second;
}
++itr;
}
// Skip hardware devices if not a hard reset
itr = (_bHard) ? g_DeviceMap.begin() : g_DeviceMap.lower_bound(IPC_FIRST_FILEIO_ID);
// Erase devices
g_DeviceMap.erase(itr, g_DeviceMap.end());
g_FileNameMap.clear();
if (_bHard)
{
g_DeviceMap.erase(g_DeviceMap.begin(), g_DeviceMap.end());
}
request_queue.clear();
reply_queue.clear();
g_LastDeviceID = IPC_FIRST_FILEIO_ID;
}
void Shutdown()
@@ -135,41 +161,53 @@ void Shutdown()
void SetDefaultContentFile(const std::string& _rFilename)
{
CWII_IPC_HLE_Device_es* pDevice =
(CWII_IPC_HLE_Device_es*)AccessDeviceByID(GetDeviceIDByName(std::string("/dev/es")));
if (pDevice)
pDevice->LoadWAD(_rFilename);
TDeviceMap::const_iterator itr = g_DeviceMap.begin();
while (itr != g_DeviceMap.end())
{
if (itr->second && itr->second->GetDeviceName().find(std::string("/dev/es")) == 0)
{
((CWII_IPC_HLE_Device_es*)itr->second)->LoadWAD(_rFilename);
}
++itr;
}
}
void ES_DIVerify(u8 *_pTMD, u32 _sz)
{
CWII_IPC_HLE_Device_es* pDevice =
(CWII_IPC_HLE_Device_es*)AccessDeviceByID(GetDeviceIDByName(std::string("/dev/es")));
if (pDevice)
pDevice->ES_DIVerify(_pTMD, _sz);
else
ERROR_LOG(WII_IPC_ES, "DIVerify called but /dev/es is not available");
CWII_IPC_HLE_Device_es::ES_DIVerify(_pTMD, _sz);
}
void SDIO_EventNotify()
{
CWII_IPC_HLE_Device_sdio_slot0 *pDevice =
(CWII_IPC_HLE_Device_sdio_slot0*)AccessDeviceByID(GetDeviceIDByName(std::string("/dev/sdio/slot0")));
(CWII_IPC_HLE_Device_sdio_slot0*)GetDeviceByName(std::string("/dev/sdio/slot0"));
if (pDevice)
pDevice->EventNotify();
}
int getFreeDeviceId()
{
u32 i;
for (i=0; i<IPC_MAX_FDS; i++)
{
if (g_FdMap[i] == NULL)
{
return i;
}
}
return -1;
}
int GetDeviceIDByName(const std::string& _rDeviceName)
IWII_IPC_HLE_Device* GetDeviceByName(const std::string& _rDeviceName)
{
TDeviceMap::const_iterator itr = g_DeviceMap.begin();
while(itr != g_DeviceMap.end())
while (itr != g_DeviceMap.end())
{
if (itr->second->GetDeviceName() == _rDeviceName)
return itr->first;
if (itr->second && itr->second->GetDeviceName() == _rDeviceName)
return itr->second;
++itr;
}
return -1;
return NULL;
}
IWII_IPC_HLE_Device* AccessDeviceByID(u32 _ID)
@@ -177,17 +215,7 @@ IWII_IPC_HLE_Device* AccessDeviceByID(u32 _ID)
if (g_DeviceMap.find(_ID) != g_DeviceMap.end())
return g_DeviceMap[_ID];
return NULL;
}
void DeleteDeviceByID(u32 ID)
{
IWII_IPC_HLE_Device* pDevice = AccessDeviceByID(ID);
if (pDevice)
delete pDevice;
g_DeviceMap.erase(ID);
g_FileNameMap.erase(ID);
return NULL;
}
// This is called from ExecuteCommand() COMMAND_OPEN_DEVICE
@@ -205,60 +233,86 @@ IWII_IPC_HLE_Device* CreateFileIO(u32 _DeviceID, const std::string& _rDeviceName
void DoState(PointerWrap &p)
{
p.Do(g_LastDeviceID);
p.Do(request_queue);
p.Do(reply_queue);
if (p.GetMode() == PointerWrap::MODE_READ)
{
TFileNameMap::const_iterator itr;
// Delete file Handles
itr = g_FileNameMap.begin();
while (itr != g_FileNameMap.end())
{
TDeviceMap::const_iterator devitr = g_DeviceMap.find(itr->first);
if (devitr != g_DeviceMap.end())
TDeviceMap::const_iterator itr;
itr = g_DeviceMap.begin();
while (itr != g_DeviceMap.end())
{
if (itr->second->IsHardware())
{
if (devitr->second)
delete devitr->second;
g_DeviceMap.erase(itr->first);
itr->second->DoState(p);
}
++itr;
}
// Load file names
p.Do(g_FileNameMap);
// Rebuild file handles
itr = g_FileNameMap.begin();
while (itr != g_FileNameMap.end())
}
if (p.GetMode() == PointerWrap::MODE_READ)
{
u32 i;
for (i=0; i<IPC_MAX_FDS; i++)
{
g_DeviceMap[itr->first] = new CWII_IPC_HLE_Device_FileIO(itr->first, itr->second);
++itr;
u32 exists;
p.Do(exists);
if (exists)
{
u32 isHw;
p.Do(isHw);
if (isHw)
{
u32 hwId;
p.Do(hwId);
g_FdMap[i] = AccessDeviceByID(hwId);
}
else
{
g_FdMap[i] = new CWII_IPC_HLE_Device_FileIO(i, "");
g_FdMap[i]->DoState(p);
}
}
else
{
g_FdMap[i] = NULL;
}
}
for (i=0; i<ES_MAX_COUNT; i++)
{
p.Do(es_inuse[i]);
u32 handleID = es_handles[i]->GetDeviceID();
p.Do(handleID);
es_handles[i] = AccessDeviceByID(handleID);
}
}
else
{
p.Do(g_FileNameMap);
}
p.Do(request_queue);
p.Do(reply_queue);
TDeviceMap::const_iterator itr;
//first, all the real devices
//(because we need fs to be deserialized first)
itr = g_DeviceMap.begin();
while (itr != g_DeviceMap.end())
{
if (itr->second->IsHardware())
itr->second->DoState(p);
++itr;
}
//then all the files
itr = g_DeviceMap.begin();
while (itr != g_DeviceMap.end())
{
if (!itr->second->IsHardware())
itr->second->DoState(p);
++itr;
u32 i;
for (i=0; i<IPC_MAX_FDS; i++)
{
u32 exists = g_FdMap[i] ? 1 : 0;
p.Do(exists);
if (exists)
{
u32 isHw = g_FdMap[i]->IsHardware() ? 1 : 0;
p.Do(isHw);
if (isHw)
{
u32 hwId = g_FdMap[i]->GetDeviceID();
p.Do(hwId);
}
else
{
g_FdMap[i]->DoState(p);
}
}
}
for (i=0; i<ES_MAX_COUNT; i++)
{
p.Do(es_inuse[i]);
u32 handleID = es_handles[i]->GetDeviceID();
p.Do(handleID);
}
}
}
@@ -267,67 +321,110 @@ void ExecuteCommand(u32 _Address)
bool CmdSuccess = false;
ECommandType Command = static_cast<ECommandType>(Memory::Read_U32(_Address));
int DeviceID = Memory::Read_U32(_Address + 8);
IWII_IPC_HLE_Device* pDevice = AccessDeviceByID(DeviceID);
volatile int DeviceID = Memory::Read_U32(_Address + 8);
INFO_LOG(WII_IPC_HLE, "-->> Execute Command Address: 0x%08x (code: %x, device: %x) ", _Address, Command, DeviceID);
IWII_IPC_HLE_Device* pDevice = (DeviceID >= 0 && DeviceID < IPC_MAX_FDS) ? g_FdMap[DeviceID] : NULL;
INFO_LOG(WII_IPC_HLE, "-->> Execute Command Address: 0x%08x (code: %x, device: %x) %p", _Address, Command, DeviceID, pDevice);
switch (Command)
{
case COMMAND_OPEN_DEVICE:
{
// Create a new HLE device. The Mode and DeviceName is given to us but we
// generate a DeviceID to be used for access to this device until it is Closed.
std::string DeviceName;
Memory::GetString(DeviceName, Memory::Read_U32(_Address + 0xC));
{
u32 Mode = Memory::Read_U32(_Address + 0x10);
DeviceID = getFreeDeviceId();
std::string DeviceName;
Memory::GetString(DeviceName, Memory::Read_U32(_Address + 0xC));
u32 Mode = Memory::Read_U32(_Address + 0x10);
DeviceID = GetDeviceIDByName(DeviceName);
// check if a device with this name has been created already
if (DeviceName.find("/dev/") == std::string::npos || DeviceID == -1)
{
if (DeviceName.find("/dev/") == 0)
WARN_LOG(WII_IPC_HLE, "Tried to open %s as %d", DeviceName.c_str(), DeviceID);
if (DeviceID >= 0)
{
if (DeviceName.find("/dev/es") == 0)
{
u32 j;
for (j=0; j<ES_MAX_COUNT; j++)
{
WARN_LOG(WII_IPC_HLE, "Unimplemented device: %s", DeviceName.c_str());
if (!es_inuse[j])
{
es_inuse[j] = true;
g_FdMap[DeviceID] = es_handles[j];
CmdSuccess = es_handles[j]->Open(_Address, Mode);
Memory::Write_U32(DeviceID, _Address+4);
break;
}
}
if (j == ES_MAX_COUNT)
{
Memory::Write_U32(FS_EESEXHAUSTED, _Address + 4);
CmdSuccess = true;
}
pDevice = AccessDeviceByID(GetDeviceIDByName(std::string("_Unimplemented_Device_")));
}
else if (DeviceName.find("/dev/") == 0)
{
pDevice = GetDeviceByName(DeviceName);
if (pDevice)
{
g_FdMap[DeviceID] = pDevice;
CmdSuccess = pDevice->Open(_Address, Mode);
INFO_LOG(WII_IPC_FILEIO, "IOP: ReOpen (Device=%s, DeviceID=%08x, Mode=%i)",
pDevice->GetDeviceName().c_str(), DeviceID, Mode);
Memory::Write_U32(DeviceID, _Address+4);
}
else
{
// create new file handle
u32 CurrentDeviceID = g_LastDeviceID;
pDevice = CreateFileIO(CurrentDeviceID, DeviceName);
g_DeviceMap[CurrentDeviceID] = pDevice;
g_FileNameMap[CurrentDeviceID] = DeviceName;
g_LastDeviceID++;
CmdSuccess = pDevice->Open(_Address, Mode);
INFO_LOG(WII_IPC_FILEIO, "IOP: Open File (Device=%s, ID=%08x, Mode=%i)",
pDevice->GetDeviceName().c_str(), CurrentDeviceID, Mode);
WARN_LOG(WII_IPC_HLE, "Unimplemented device: %s", DeviceName.c_str());
Memory::Write_U32(FS_ENOENT, _Address+4);
CmdSuccess = true;
}
}
else
{
// F|RES: prolly the re-open is just a mode change
pDevice = AccessDeviceByID(DeviceID);
}
else
{
IWII_IPC_HLE_Device* pDevice = CreateFileIO(DeviceID, DeviceName);
CmdSuccess = pDevice->Open(_Address, Mode);
INFO_LOG(WII_IPC_FILEIO, "IOP: ReOpen (Device=%s, DeviceID=%08x, Mode=%i)",
pDevice->GetDeviceName().c_str(), DeviceID, Mode);
}
}
break;
INFO_LOG(WII_IPC_FILEIO, "IOP: Open File (Device=%s, ID=%08x, Mode=%i)",
pDevice->GetDeviceName().c_str(), DeviceID, Mode);
if (Memory::Read_U32(_Address + 4) == DeviceID)
{
g_FdMap[DeviceID] = pDevice;
}
else
{
delete pDevice;
}
}
}
else
{
Memory::Write_U32(FS_EFDEXHAUSTED, _Address + 4);
CmdSuccess = true;
}
break;
}
case COMMAND_CLOSE_DEVICE:
if (pDevice)
{
if (pDevice)
{
CmdSuccess = pDevice->Close(_Address);
u32 j;
for (j=0; j<ES_MAX_COUNT; j++)
{
if (es_handles[j] == g_FdMap[DeviceID])
{
es_inuse[j] = false;
}
}
g_FdMap[DeviceID] = NULL;
// Don't delete hardware
if (!pDevice->IsHardware())
DeleteDeviceByID(DeviceID);
delete pDevice;
}
else
{
@@ -335,50 +432,67 @@ void ExecuteCommand(u32 _Address)
CmdSuccess = true;
}
break;
}
case COMMAND_READ:
{
if (pDevice)
{
CmdSuccess = pDevice->Read(_Address);
}
else
{
Memory::Write_U32(FS_EINVAL, _Address + 4);
CmdSuccess = true;
}
break;
}
case COMMAND_WRITE:
{
if (pDevice)
{
CmdSuccess = pDevice->Write(_Address);
}
else
{
Memory::Write_U32(FS_EINVAL, _Address + 4);
CmdSuccess = true;
}
break;
}
case COMMAND_SEEK:
{
if (pDevice)
{
CmdSuccess = pDevice->Seek(_Address);
}
else
{
Memory::Write_U32(FS_EINVAL, _Address + 4);
CmdSuccess = true;
}
break;
}
case COMMAND_IOCTL:
{
if (pDevice)
{
CmdSuccess = pDevice->IOCtl(_Address);
}
break;
}
case COMMAND_IOCTLV:
{
if (pDevice)
{
CmdSuccess = pDevice->IOCtlV(_Address);
}
break;
}
default:
{
_dbg_assert_msg_(WII_IPC_HLE, 0, "Unknown IPC Command %i (0x%08x)", Command, _Address);
break;
}
}
// It seems that the original hardware overwrites the command after it has been
@@ -450,9 +564,10 @@ void Update()
void UpdateDevices()
{
// Check if a hardware device must be updated
TDeviceMap::const_iterator itrEnd = g_DeviceMap.lower_bound(IPC_FIRST_FILEIO_ID);
for (TDeviceMap::const_iterator itr = g_DeviceMap.begin(); itr != itrEnd; ++itr) {
if (itr->second->IsOpened() && itr->second->Update()) {
for (TDeviceMap::const_iterator itr = g_DeviceMap.begin(); itr != g_DeviceMap.end(); ++itr)
{
if (itr->second->IsOpened() && itr->second->Update())
{
break;
}
}
+7 -8
View File
@@ -25,9 +25,9 @@ class IWII_IPC_HLE_Device;
namespace WII_IPC_HLE_Interface
{
#define IPC_FIRST_HARDWARE_ID 0 // first IPC device ID
#define IPC_FIRST_FILEIO_ID 33 // first IPC file ID
#define IPC_FIRST_ID 0x00 // first IPC device ID
#define IPC_MAX_FILES 0x10 // first IPC file ID
// Init
void Init();
@@ -46,14 +46,13 @@ void ES_DIVerify(u8 *_pTMD, u32 _sz);
void SDIO_EventNotify();
int GetDeviceIDByName(const std::string& _rDeviceName);
IWII_IPC_HLE_Device* AccessDeviceByID(u32 _ID);
void DeleteDeviceByID(u32 _ID);
IWII_IPC_HLE_Device* CreateFileIO(u32 _DeviceID, const std::string& _rDeviceName);
IWII_IPC_HLE_Device* GetDeviceByName(const std::string& _rDeviceName);
IWII_IPC_HLE_Device* AccessDeviceByID(u32 _ID);
int getFreeDeviceId();
// Update
void Update();
@@ -39,7 +39,7 @@ class PointerWrap;
#define FS_ENOENT2 (u32)-106 // File not found
#define FS_ENFILE (u32)-107 // Too many fds open
#define FS_EFBIG (u32)-108 // max block count reached?
#define FS_ENFILE2 (u32)-109 // Too many fds open
#define FS_EFDEXHAUSTED (u32)-109 // Too many fds open
#define FS_ENAMELEN (u32)-110 // pathname is too long
#define FS_EFDOPEN (u32)-111 // FD is already open
#define FS_EIO2 (u32)-114 // returned on ECC error
@@ -47,6 +47,7 @@ class PointerWrap;
#define FS_EDIRDEPTH (u32)-116 // max directory depth exceeded
#define FS_EBUSY2 (u32)-118 // Resource busy
//#define FS_EFATAL (u32)-119 // fatal error not used by IOS as fatal ERROR
#define FS_EESEXHAUSTED (u32)-1016 // Max of 2 ES handles at a time
class IWII_IPC_HLE_Device
{
@@ -28,7 +28,7 @@
static Common::replace_v replacements;
// This is used by several of the FileIO and /dev/fs/ functions
// This is used by several of the FileIO and /dev/fs functions
std::string HLE_IPC_BuildFilename(const char* _pFilename, int _size)
{
std::string path_full = File::GetUserPath(D_WIIROOT_IDX);
@@ -128,7 +128,7 @@ bool CWII_IPC_HLE_Device_FileIO::Open(u32 _CommandAddress, u32 _Mode)
// The file must exist before we can open it
// It should be created by ISFS_CreateFile, not here
if(File::Exists(m_Filename))
if (File::Exists(m_Filename))
{
INFO_LOG(WII_IPC_FILEIO, "FileIO: Open %s (%s == %08X)", m_Name.c_str(), Modes[_Mode], _Mode);
ReturnValue = m_DeviceID;
@@ -149,25 +149,29 @@ bool CWII_IPC_HLE_Device_FileIO::Open(u32 _CommandAddress, u32 _Mode)
bool CWII_IPC_HLE_Device_FileIO::OpenFile()
{
switch(m_Mode)
switch (m_Mode)
{
case ISFS_OPEN_READ:
{
m_pFileHandle.Open(m_Filename, "rb");
break;
// "r+b" is technically wrong, but OPEN_WRITE should not truncate the file as "wb" does.
}
case ISFS_OPEN_WRITE:
{
m_pFileHandle.Open(m_Filename, "r+b");
break;
}
case ISFS_OPEN_RW:
{
m_pFileHandle.Open(m_Filename, "r+b");
break;
}
default:
{
PanicAlertT("FileIO: Unknown open mode : 0x%02x", m_Mode);
break;
}
}
return m_pFileHandle.IsOpen();
}
@@ -178,21 +182,21 @@ void CWII_IPC_HLE_Device_FileIO::CloseFile()
bool CWII_IPC_HLE_Device_FileIO::Seek(u32 _CommandAddress)
{
u32 ReturnValue = FS_RESULT_FATAL;
const s32 SeekPosition = Memory::Read_U32(_CommandAddress + 0xC);
const s32 Mode = Memory::Read_U32(_CommandAddress + 0x10);
u32 ReturnValue = FS_RESULT_FATAL;
const s32 SeekPosition = Memory::Read_U32(_CommandAddress + 0xC);
const s32 Mode = Memory::Read_U32(_CommandAddress + 0x10);
if(OpenFile())
if (OpenFile())
{
ReturnValue = FS_RESULT_FATAL;
const u64 fileSize = m_pFileHandle.GetSize();
const u64 fileSize = m_pFileHandle.GetSize();
INFO_LOG(WII_IPC_FILEIO, "FileIO: Seek Pos: 0x%08x, Mode: %i (%s, Length=0x%08llx)", SeekPosition, Mode, m_Name.c_str(), fileSize);
switch(Mode){
switch (Mode){
case 0:
{
if(SeekPosition >=0 && SeekPosition <= fileSize)
if (SeekPosition >=0 && SeekPosition <= fileSize)
{
m_SeekPos = SeekPosition;
ReturnValue = m_SeekPos;
@@ -202,7 +206,7 @@ bool CWII_IPC_HLE_Device_FileIO::Seek(u32 _CommandAddress)
case 1:
{
s32 wantedPos = SeekPosition+m_SeekPos;
if(wantedPos >=0 && wantedPos <= fileSize)
if (wantedPos >=0 && wantedPos <= fileSize)
{
m_SeekPos = wantedPos;
ReturnValue = m_SeekPos;
@@ -212,7 +216,7 @@ bool CWII_IPC_HLE_Device_FileIO::Seek(u32 _CommandAddress)
case 2:
{
s32 wantedPos = fileSize+m_SeekPos;
if(wantedPos >=0 && wantedPos <= fileSize)
if (wantedPos >=0 && wantedPos <= fileSize)
{
m_SeekPos = wantedPos;
ReturnValue = m_SeekPos;
@@ -244,7 +248,7 @@ bool CWII_IPC_HLE_Device_FileIO::Read(u32 _CommandAddress)
const u32 Size = Memory::Read_U32(_CommandAddress + 0x10);
if(OpenFile())
if (OpenFile())
{
if (m_Mode == ISFS_OPEN_WRITE)
{
@@ -284,7 +288,7 @@ bool CWII_IPC_HLE_Device_FileIO::Write(u32 _CommandAddress)
const u32 Size = Memory::Read_U32(_CommandAddress + 0x10);
if(OpenFile())
if (OpenFile())
{
if (m_Mode == ISFS_OPEN_READ)
{
@@ -318,21 +322,14 @@ bool CWII_IPC_HLE_Device_FileIO::IOCtl(u32 _CommandAddress)
#if defined(_DEBUG) || defined(DEBUGFAST)
DumpCommands(_CommandAddress);
#endif
const u32 Parameter = Memory::Read_U32(_CommandAddress + 0xC);
const u32 Parameter = Memory::Read_U32(_CommandAddress + 0xC);
u32 ReturnValue = 0;
//u32 BufferIn = Memory::Read_U32(_CommandAddress + 0x10);
//u32 BufferInSize = Memory::Read_U32(_CommandAddress + 0x14);
//u32 BufferOut = Memory::Read_U32(_CommandAddress + 0x18);
//u32 BufferOutSize = Memory::Read_U32(_CommandAddress + 0x1C);
// Return Value
u32 ReturnValue = 0; // no error
switch(Parameter)
switch (Parameter)
{
case ISFS_IOCTL_GETFILESTATS:
{
if(OpenFile())
if (OpenFile())
{
u32 m_FileLength = (u32)m_pFileHandle.GetSize();
@@ -37,7 +37,7 @@ public:
virtual bool Close(u32 _CommandAddress, bool _bForce);
virtual bool IOCtlV(u32 _CommandAddress);
u32 ES_DIVerify(u8 *_pTMD, u32 _sz);
static u32 ES_DIVerify(u8 *_pTMD, u32 _sz);
private:
enum
@@ -42,10 +42,6 @@ using namespace MathUtil;
void UpdateSSEState();
#ifdef _MSC_VER
#pragma float_control(precise, on, push)
#endif
// Extremely rare - actually, never seen.
// Star Wars : Rogue Leader spams that at some point :|
void Interpreter::Helper_UpdateCR1(double _fValue)
@@ -518,8 +514,4 @@ void Interpreter::fsqrtx(UGeckoInstruction _inst)
rPS0(_inst.FD) = sqrt(b);
UpdateFPRF(rPS0(_inst.FD));
if (_inst.Rc) Helper_UpdateCR1(rPS0(_inst.FD));
}
#ifdef _MSC_VER
#pragma float_control(pop)
#endif
}
@@ -367,7 +367,7 @@ void Interpreter::dcbf(UGeckoInstruction _inst)
if (jit)
{
u32 address = Helper_Get_EA_X(_inst);
jit->GetBlockCache()->InvalidateICache(address & ~0x1f);
jit->GetBlockCache()->InvalidateICache(address & ~0x1f, 32);
}
}
@@ -378,7 +378,7 @@ void Interpreter::dcbi(UGeckoInstruction _inst)
if (jit)
{
u32 address = Helper_Get_EA_X(_inst);
jit->GetBlockCache()->InvalidateICache(address & ~0x1f);
jit->GetBlockCache()->InvalidateICache(address & ~0x1f, 32);
}
}
+44 -2
View File
@@ -41,6 +41,10 @@
#include "JitAsm.h"
#include "JitRegCache.h"
#include "Jit64_Tables.h"
#include "HW/ProcessorInterface.h"
#if defined(_DEBUG) || defined(DEBUGFAST)
#include "PowerPCDisasm.h"
#endif
using namespace Gen;
using namespace PowerPC;
@@ -414,8 +418,8 @@ const u8* Jit64::DoJit(u32 em_address, PPCAnalyst::CodeBuffer *code_buf, JitBloc
// Comment out the following to disable breakpoints (speed-up)
if (!Profiler::g_ProfileBlocks)
{
blockSize = 1;
broken_block = true;
if (GetState() == CPU_STEPPING)
blockSize = 1;
Trace();
}
}
@@ -572,6 +576,44 @@ const u8* Jit64::DoJit(u32 em_address, PPCAnalyst::CodeBuffer *code_buf, JitBloc
SetJumpTarget(b1);
}
// Add an external exception check if the instruction writes to the FIFO.
if (jit->js.fifoWriteAddresses.find(ops[i].address) != jit->js.fifoWriteAddresses.end())
{
gpr.Flush(FLUSH_ALL);
fpr.Flush(FLUSH_ALL);
TEST(32, M((void *)&PowerPC::ppcState.Exceptions), Imm32(EXCEPTION_ISI | EXCEPTION_PROGRAM | EXCEPTION_SYSCALL | EXCEPTION_FPU_UNAVAILABLE | EXCEPTION_DSI | EXCEPTION_ALIGNMENT | EXCEPTION_DECREMENTER));
FixupBranch clearInt = J_CC(CC_NZ);
TEST(32, M((void *)&PowerPC::ppcState.Exceptions), Imm32(EXCEPTION_EXTERNAL_INT));
FixupBranch noExtException = J_CC(CC_Z);
TEST(32, M((void *)&PowerPC::ppcState.msr), Imm32(0x0008000));
FixupBranch noExtIntEnable = J_CC(CC_Z);
TEST(32, M((void *)&ProcessorInterface::m_InterruptCause), Imm32(ProcessorInterface::INT_CAUSE_CP | ProcessorInterface::INT_CAUSE_PE_TOKEN | ProcessorInterface::INT_CAUSE_PE_FINISH));
FixupBranch noCPInt = J_CC(CC_Z);
MOV(32, M(&PC), Imm32(ops[i].address));
WriteExceptionExit();
SetJumpTarget(noCPInt);
SetJumpTarget(noExtIntEnable);
SetJumpTarget(noExtException);
SetJumpTarget(clearInt);
}
if (Core::g_CoreStartupParameter.bEnableDebugging && breakpoints.IsAddressBreakPoint(ops[i].address) && GetState() != CPU_STEPPING)
{
MOV(32, M(&PC), Imm32(ops[i].address));
ABI_CallFunction(reinterpret_cast<void *>(&PowerPC::CheckBreakPoints));
TEST(32, M((void*)PowerPC::GetStatePtr()), Imm32(0xFFFFFFFF));
FixupBranch noBreakpoint = J_CC(CC_Z);
gpr.Flush(FLUSH_ALL);
fpr.Flush(FLUSH_ALL);
WriteExit(ops[i].address, 0);
SetJumpTarget(noBreakpoint);
}
Jit64Tables::CompileInstruction(ops[i]);
if (js.memcheck && (opinfo->flags & FL_LOADSTORE))
@@ -100,8 +100,8 @@ static GekkoOPTemplate primarytable[] =
{50, &Jit64::lfd}, //"lfd", OPTYPE_LOADFP, FL_IN_A}},
{51, &Jit64::Default}, //"lfdu", OPTYPE_LOADFP, FL_OUT_A | FL_IN_A}},
{52, &Jit64::Default}, //"stfs", OPTYPE_STOREFP, FL_IN_A}},
{53, &Jit64::Default}, //"stfsu", OPTYPE_STOREFP, FL_OUT_A | FL_IN_A}},
{52, &Jit64::stfs}, //"stfs", OPTYPE_STOREFP, FL_IN_A}},
{53, &Jit64::stfs}, //"stfsu", OPTYPE_STOREFP, FL_OUT_A | FL_IN_A}},
{54, &Jit64::stfd}, //"stfd", OPTYPE_STOREFP, FL_IN_A}},
{55, &Jit64::Default}, //"stfdu", OPTYPE_STOREFP, FL_OUT_A | FL_IN_A}},
@@ -81,12 +81,15 @@ void Jit64AsmRoutineManager::Generate()
if (Core::g_CoreStartupParameter.bEnableDebugging)
{
TEST(32, M((void*)PowerPC::GetStatePtr()), Imm32(PowerPC::CPU_STEPPING));
FixupBranch notStepping = J_CC(CC_Z);
ABI_CallFunction(reinterpret_cast<void *>(&PowerPC::CheckBreakPoints));
TEST(32, M((void*)PowerPC::GetStatePtr()), Imm32(0xFFFFFFFF));
FixupBranch noBreakpoint = J_CC(CC_Z);
ABI_PopAllCalleeSavedRegsAndAdjustStack();
RET();
SetJumpTarget(noBreakpoint);
SetJumpTarget(notStepping);
}
SetJumpTarget(skipToRealDispatch);
@@ -266,7 +266,7 @@ void Jit64::reg_imm(UGeckoInstruction inst)
case 15:
if (a == 0) { // lis
// Merge with next instruction if loading a 32-bits immediate value (lis + addi, lis + ori)
if (!js.isLastInstruction) {
if (!js.isLastInstruction && !Core::g_CoreStartupParameter.bEnableDebugging) {
if ((js.next_inst.OPCD == 14) && (js.next_inst.RD == d) && (js.next_inst.RA == d)) { // addi
gpr.SetImmediate32(d, ((u32)inst.SIMM_16 << 16) + (u32)(s32)js.next_inst.SIMM_16);
js.downcountAmount++;
+4 -3
View File
@@ -1260,8 +1260,8 @@ static const std::string opcodeNames[] = {
"FResult_End", "StorePaired", "StoreSingle", "StoreDouble", "StoreFReg",
"FDCmpCR", "CInt16", "CInt32", "SystemCall", "RFIExit",
"InterpreterBranch", "IdleBranch", "ShortIdleLoop",
"FPExceptionCheckStart", "FPExceptionCheckEnd", "ISIException", "Tramp",
"BlockStart", "BlockEnd", "Int3",
"FPExceptionCheckStart", "FPExceptionCheckEnd", "ISIException", "ExtExceptionCheck",
"Tramp", "BlockStart", "BlockEnd", "Int3",
};
static const unsigned alwaysUsedList[] = {
InterpreterFallback, StoreGReg, StoreCR, StoreLink, StoreCTR, StoreMSR,
@@ -1269,7 +1269,8 @@ static const unsigned alwaysUsedList[] = {
Store16, Store32, StoreSingle, StoreDouble, StorePaired, StoreFReg, FDCmpCR,
BlockStart, BlockEnd, IdleBranch, BranchCond, BranchUncond, ShortIdleLoop,
SystemCall, InterpreterBranch, RFIExit, FPExceptionCheckStart,
FPExceptionCheckEnd, ISIException, Int3, Tramp, Nop
FPExceptionCheckEnd, ISIException, ExtExceptionCheck, BreakPointCheck,
Int3, Tramp, Nop
};
static const unsigned extra8RegList[] = {
LoadGReg, LoadCR, LoadGQR, LoadFReg, LoadFRegDENToZero,
+8 -2
View File
@@ -165,10 +165,10 @@ enum Opcode {
ShortIdleLoop, // Idle loop seen in homebrew like wii mahjong,
// just a branch
// used for MMU, at least until someone
// used for exception checking, at least until someone
// has a better idea of integrating it
FPExceptionCheckStart, FPExceptionCheckEnd,
ISIException,
ISIException, ExtExceptionCheck, BreakPointCheck,
// "Opcode" representing a register too far away to
// reference directly; this is a size optimization
Tramp,
@@ -411,6 +411,12 @@ public:
InstLoc EmitISIException(InstLoc dest) {
return EmitUOp(ISIException, dest);
}
InstLoc EmitExtExceptionCheck(InstLoc pc) {
return EmitUOp(ExtExceptionCheck, pc);
}
InstLoc EmitBreakPointCheck(InstLoc pc) {
return EmitUOp(BreakPointCheck, pc);
}
InstLoc EmitRFIExit() {
return FoldZeroOp(RFIExit, 0);
}
@@ -50,6 +50,7 @@ The register allocation is linear scan allocation.
#include "../../../../Common/Src/CPUDetect.h"
#include "MathUtil.h"
#include "../../Core.h"
#include "HW/ProcessorInterface.h"
static ThunkManager thunks;
@@ -761,6 +762,8 @@ static void DoWriteCode(IRBuilder* ibuild, JitIL* Jit, bool UseProfile, bool Mak
case FPExceptionCheckStart:
case FPExceptionCheckEnd:
case ISIException:
case ExtExceptionCheck:
case BreakPointCheck:
case Int3:
case Tramp:
// No liveness effects
@@ -1920,6 +1923,38 @@ static void DoWriteCode(IRBuilder* ibuild, JitIL* Jit, bool UseProfile, bool Mak
Jit->WriteExceptionExit();
break;
}
case ExtExceptionCheck: {
unsigned InstLoc = ibuild->GetImmValue(getOp1(I));
Jit->TEST(32, M((void *)&PowerPC::ppcState.Exceptions), Imm32(EXCEPTION_ISI | EXCEPTION_PROGRAM | EXCEPTION_SYSCALL | EXCEPTION_FPU_UNAVAILABLE | EXCEPTION_DSI | EXCEPTION_ALIGNMENT | EXCEPTION_DECREMENTER));
FixupBranch clearInt = Jit->J_CC(CC_NZ);
Jit->TEST(32, M((void *)&PowerPC::ppcState.Exceptions), Imm32(EXCEPTION_EXTERNAL_INT));
FixupBranch noExtException = Jit->J_CC(CC_Z);
Jit->TEST(32, M((void *)&PowerPC::ppcState.msr), Imm32(0x0008000));
FixupBranch noExtIntEnable = Jit->J_CC(CC_Z);
Jit->TEST(32, M((void *)&ProcessorInterface::m_InterruptCause), Imm32(ProcessorInterface::INT_CAUSE_CP || ProcessorInterface::INT_CAUSE_PE_TOKEN || ProcessorInterface::INT_CAUSE_PE_FINISH));
FixupBranch noCPInt = Jit->J_CC(CC_Z);
Jit->MOV(32, M(&PC), Imm32(InstLoc));
Jit->WriteExceptionExit();
Jit->SetJumpTarget(noCPInt);
Jit->SetJumpTarget(noExtIntEnable);
Jit->SetJumpTarget(noExtException);
Jit->SetJumpTarget(clearInt);
break;
}
case BreakPointCheck: {
unsigned InstLoc = ibuild->GetImmValue(getOp1(I));
Jit->MOV(32, M(&PC), Imm32(InstLoc));
Jit->ABI_CallFunction(reinterpret_cast<void *>(&PowerPC::CheckBreakPoints));
Jit->TEST(32, M((void*)PowerPC::GetStatePtr()), Imm32(0xFFFFFFFF));
FixupBranch noBreakpoint = Jit->J_CC(CC_Z);
Jit->WriteExit(InstLoc, 0);
Jit->SetJumpTarget(noBreakpoint);
break;
}
case Int3: {
Jit->INT3();
break;
+12 -1
View File
@@ -526,7 +526,8 @@ const u8* JitIL::DoJit(u32 em_address, PPCAnalyst::CodeBuffer *code_buf, JitBloc
// Comment out the following to disable breakpoints (speed-up)
if (!Profiler::g_ProfileBlocks)
{
blockSize = 1;
if (GetState() == CPU_STEPPING)
blockSize = 1;
Trace();
}
}
@@ -651,6 +652,16 @@ const u8* JitIL::DoJit(u32 em_address, PPCAnalyst::CodeBuffer *code_buf, JitBloc
{
ibuild.EmitFPExceptionCheckStart(ibuild.EmitIntConst(ops[i].address));
}
if (jit->js.fifoWriteAddresses.find(js.compilerPC) != jit->js.fifoWriteAddresses.end())
{
ibuild.EmitExtExceptionCheck(ibuild.EmitIntConst(ops[i].address));
}
if (Core::g_CoreStartupParameter.bEnableDebugging && breakpoints.IsAddressBreakPoint(ops[i].address) && GetState() != CPU_STEPPING)
{
ibuild.EmitBreakPointCheck(ibuild.EmitIntConst(ops[i].address));
}
JitILTables::CompileInstruction(ops[i]);
@@ -83,12 +83,15 @@ void JitILAsmRoutineManager::Generate()
if (Core::g_CoreStartupParameter.bEnableDebugging)
{
TEST(32, M((void*)PowerPC::GetStatePtr()), Imm32(PowerPC::CPU_STEPPING));
FixupBranch notStepping = J_CC(CC_Z);
ABI_CallFunction(reinterpret_cast<void *>(&PowerPC::CheckBreakPoints));
TEST(32, M((void*)PowerPC::GetStatePtr()), Imm32(0xFFFFFFFF));
FixupBranch noBreakpoint = J_CC(CC_Z);
ABI_PopAllCalleeSavedRegsAndAdjustStack();
RET();
SetJumpTarget(noBreakpoint);
SetJumpTarget(notStepping);
}
SetJumpTarget(skipToRealDispatch);
@@ -493,6 +493,9 @@ void JitIL::srawx(UGeckoInstruction inst)
test = ibuild.EmitOr(val, mask2);
test = ibuild.EmitICmpUgt(test, mask);
ibuild.EmitStoreCarry(test);
if (inst.Rc)
ComputeRC(ibuild, val);
}
void JitIL::srawix(UGeckoInstruction inst)
@@ -13,6 +13,8 @@
// If not, see http://www.gnu.org/licenses/
#include "JitBase.h"
#include "PowerPCDisasm.h"
#include "disasm.h"
JitBase *jit;
@@ -28,8 +28,7 @@
#include "JitBackpatch.h" // for EmuCodeBlock
#include "JitAsmCommon.h"
#include "PowerPCDisasm.h"
#include "disasm.h"
#include <set>
#define JIT_OPCODE 0
@@ -75,6 +74,8 @@ protected:
u8* rewriteStart;
JitBlock *curBlock;
std::set<u32> fifoWriteAddresses;
};
public:
@@ -353,6 +353,24 @@ bool JitBlock::ContainsAddress(u32 em_address)
}
}
void JitBlockCache::UnlinkBlock(int i)
{
JitBlock &b = blocks[i];
std::map<u32, int>::iterator iter;
pair<multimap<u32, int>::iterator, multimap<u32, int>::iterator> ppp;
ppp = links_to.equal_range(b.originalAddress);
if (ppp.first == ppp.second)
return;
for (multimap<u32, int>::iterator iter2 = ppp.first; iter2 != ppp.second; ++iter2) {
JitBlock &sourceBlock = blocks[iter2->second];
for (int e = 0; e < 2; e++)
{
if (sourceBlock.exitAddress[e] == b.originalAddress)
sourceBlock.linkStatus[e] = false;
}
}
}
void JitBlockCache::DestroyBlock(int block_num, bool invalidate)
{
if (block_num < 0 || block_num >= num_blocks)
@@ -375,7 +393,9 @@ bool JitBlock::ContainsAddress(u32 em_address)
Memory::WriteUnchecked_U32(b.originalFirstOpcode, b.originalAddress);
#endif
// We don't unlink blocks, we just send anyone who tries to run them back to the dispatcher.
UnlinkBlock(block_num);
// Send anyone who tries to run this block back to the dispatcher.
// Not entirely ideal, but .. pretty good.
// Spurious entrances from previously linked blocks can only come through checkedEntry
XEmitter emit((u8 *)b.checkedEntry);
@@ -390,14 +410,31 @@ bool JitBlock::ContainsAddress(u32 em_address)
}
void JitBlockCache::InvalidateICache(u32 address)
void JitBlockCache::InvalidateICache(u32 address, const u32 length)
{
address &= ~0x1f;
// destroy JIT blocks
// !! this works correctly under assumption that any two overlapping blocks end at the same address
std::map<pair<u32,u32>, u32>::iterator it1 = block_map.lower_bound(std::make_pair(address, 0)), it2 = it1, it;
while (it2 != block_map.end() && it2->first.second < address + 0x20)
while (it2 != block_map.end() && it2->first.second < address + length)
{
#ifdef JIT_UNLIMITED_ICACHE
JitBlock &b = blocks[it2->second];
if (b.originalAddress & JIT_ICACHE_VMEM_BIT)
{
u32 cacheaddr = b.originalAddress & JIT_ICACHE_MASK;
memset(iCacheVMEM + cacheaddr, JIT_ICACHE_INVALID_BYTE, 4);
}
else if (b.originalAddress & JIT_ICACHE_EXRAM_BIT)
{
u32 cacheaddr = b.originalAddress & JIT_ICACHEEX_MASK;
memset(iCacheEx + cacheaddr, JIT_ICACHE_INVALID_BYTE, 4);
}
else
{
u32 cacheaddr = b.originalAddress & JIT_ICACHE_MASK;
memset(iCache + cacheaddr, JIT_ICACHE_INVALID_BYTE, 4);
}
#endif
DestroyBlock(it2->second, true);
it2++;
}
@@ -418,17 +455,17 @@ bool JitBlock::ContainsAddress(u32 em_address)
if (address & JIT_ICACHE_VMEM_BIT)
{
u32 cacheaddr = address & JIT_ICACHE_MASK;
memset(iCacheVMEM + cacheaddr, JIT_ICACHE_INVALID_BYTE, 32);
memset(iCacheVMEM + cacheaddr, JIT_ICACHE_INVALID_BYTE, length);
}
else if (address & JIT_ICACHE_EXRAM_BIT)
{
u32 cacheaddr = address & JIT_ICACHEEX_MASK;
memset(iCacheEx + cacheaddr, JIT_ICACHE_INVALID_BYTE, 32);
memset(iCacheEx + cacheaddr, JIT_ICACHE_INVALID_BYTE, length);
}
else
{
u32 cacheaddr = address & JIT_ICACHE_MASK;
memset(iCache + cacheaddr, JIT_ICACHE_INVALID_BYTE, 32);
memset(iCache + cacheaddr, JIT_ICACHE_INVALID_BYTE, length);
}
#endif
}
@@ -87,6 +87,7 @@ class JitBlockCache
bool RangeIntersect(int s1, int e1, int s2, int e2) const;
void LinkBlockExits(int i);
void LinkBlock(int i);
void UnlinkBlock(int i);
public:
JitBlockCache() :
@@ -129,7 +130,7 @@ public:
CompiledCode GetCompiledCodeFromBlock(int block_num);
// DOES NOT WORK CORRECTLY WITH INLINING
void InvalidateICache(u32 em_address);
void InvalidateICache(u32 address, const u32 length);
void DestroyBlock(int block_num, bool invalidate);
// Not currently used
+1 -1
View File
@@ -110,7 +110,7 @@ namespace PowerPC
#endif
valid[set] = 0;
if (jit)
jit->GetBlockCache()->InvalidateICache(addr);
jit->GetBlockCache()->InvalidateICache(addr & ~0x1f, 32);
}
u32 InstructionCache::ReadInstruction(u32 addr)
+2 -2
View File
@@ -389,8 +389,8 @@ void CVolumeDirectory::BuildFST()
// write FST size and location
_dbg_assert_(DVDINTERFACE, m_diskHeader);
Write32((u32)(FST_ADDRESS >> m_addressShift), 0x0424, m_diskHeader);
Write32((u32)m_fstSize, 0x0428, m_diskHeader);
Write32((u32)m_fstSize, 0x042c, m_diskHeader);
Write32((u32)(m_fstSize >> m_addressShift), 0x0428, m_diskHeader);
Write32((u32)(m_fstSize >> m_addressShift), 0x042c, m_diskHeader);
}
void CVolumeDirectory::WriteToBuffer(u64 _SrcStartAddress, u64 _SrcLength, u8* _Src,
+15 -15
View File
@@ -90,7 +90,7 @@ static const wxLanguage langIds[] =
#define EXIDEV_GECKO_STR "USBGecko"
#define CSTR_TRANS(a) wxString(wxGetTranslation(wxT(a))).mb_str()
#define WXSTR_TRANS(a) wxString(wxGetTranslation(wxT(a)))
#ifdef WIN32
//only used with xgettext to be picked up as translatable string.
//win32 does not have wx on its path, the provided wxALL_FILES
@@ -979,7 +979,7 @@ void CConfigMain::GCSettingsChanged(wxCommandEvent& event)
case ID_GC_EXIDEVICE_SLOTB:
exidevice++;
case ID_GC_EXIDEVICE_SLOTA:
ChooseEXIDevice(std::string(event.GetString().mb_str()), exidevice);
ChooseEXIDevice(event.GetString(), exidevice);
break;
case ID_GC_EXIDEVICE_SLOTA_PATH:
ChooseMemcardPath(SConfig::GetInstance().m_strMemoryCardA, true);
@@ -994,7 +994,7 @@ void CConfigMain::GCSettingsChanged(wxCommandEvent& event)
case ID_GC_SIDEVICE1:
sidevice++;
case ID_GC_SIDEVICE0:
ChooseSIDevice(std::string(event.GetString().mb_str()), sidevice);
ChooseSIDevice(event.GetString(), sidevice);
break;
}
}
@@ -1044,16 +1044,16 @@ void CConfigMain::ChooseMemcardPath(std::string& strMemcard, bool isSlotA)
}
}
void CConfigMain::ChooseSIDevice(std::string deviceName, int deviceNum)
void CConfigMain::ChooseSIDevice(wxString deviceName, int deviceNum)
{
SIDevices tempType;
if (!deviceName.compare(CSTR_TRANS(SIDEV_STDCONT_STR)))
if (!deviceName.compare(WXSTR_TRANS(SIDEV_STDCONT_STR)))
tempType = SIDEVICE_GC_CONTROLLER;
else if (!deviceName.compare(CSTR_TRANS(SIDEV_BONGO_STR)))
else if (!deviceName.compare(WXSTR_TRANS(SIDEV_BONGO_STR)))
tempType = SIDEVICE_GC_TARUKONGA;
else if (!deviceName.compare(SIDEV_GBA_STR))
else if (!deviceName.compare(wxT(SIDEV_GBA_STR)))
tempType = SIDEVICE_GC_GBA;
else if (!deviceName.compare(CSTR_TRANS(SIDEV_AM_BB_STR)))
else if (!deviceName.compare(WXSTR_TRANS(SIDEV_AM_BB_STR)))
tempType = SIDEVICE_AM_BASEBOARD;
else
tempType = SIDEVICE_NONE;
@@ -1067,21 +1067,21 @@ void CConfigMain::ChooseSIDevice(std::string deviceName, int deviceNum)
}
}
void CConfigMain::ChooseEXIDevice(std::string deviceName, int deviceNum)
void CConfigMain::ChooseEXIDevice(wxString deviceName, int deviceNum)
{
TEXIDevices tempType;
if (!deviceName.compare(CSTR_TRANS(EXIDEV_MEMCARD_STR)))
if (!deviceName.compare(WXSTR_TRANS(EXIDEV_MEMCARD_STR)))
tempType = EXIDEVICE_MEMORYCARD;
else if (!deviceName.compare(CSTR_TRANS(EXIDEV_MIC_STR)))
else if (!deviceName.compare(WXSTR_TRANS(EXIDEV_MIC_STR)))
tempType = EXIDEVICE_MIC;
else if (!deviceName.compare(EXIDEV_BBA_STR))
else if (!deviceName.compare(wxT(EXIDEV_BBA_STR)))
tempType = EXIDEVICE_ETH;
else if (!deviceName.compare(CSTR_TRANS(EXIDEV_AM_BB_STR)))
else if (!deviceName.compare(WXSTR_TRANS(EXIDEV_AM_BB_STR)))
tempType = EXIDEVICE_AM_BASEBOARD;
else if (!deviceName.compare(EXIDEV_GECKO_STR))
else if (!deviceName.compare(wxT(EXIDEV_GECKO_STR)))
tempType = EXIDEVICE_GECKO;
else if (!deviceName.compare(CSTR_TRANS(DEV_NONE_STR)))
else if (!deviceName.compare(WXSTR_TRANS(DEV_NONE_STR)))
tempType = EXIDEVICE_NONE;
else
tempType = EXIDEVICE_DUMMY;
+2 -2
View File
@@ -253,8 +253,8 @@ private:
void GCSettingsChanged(wxCommandEvent& event);
void ChooseMemcardPath(std::string& strMemcard, bool isSlotA);
void ChooseSIDevice(std::string deviceName, int deviceNum);
void ChooseEXIDevice(std::string deviceName, int deviceNum);
void ChooseSIDevice(wxString deviceName, int deviceNum);
void ChooseEXIDevice(wxString deviceName, int deviceNum);
void WiiSettingsChanged(wxCommandEvent& event);
// Change from IPL.LNG value to country code
@@ -263,6 +263,8 @@ void CCodeWindow::SingleStep()
{
if (CCPU::IsStepping())
{
if (jit)
jit->GetBlockCache()->InvalidateICache(PC, 4);
CCPU::StepOpcode(&sync_event);
wxThread::Sleep(20);
// need a short wait here
+2 -1
View File
@@ -41,7 +41,7 @@ CLogWindow::CLogWindow(CFrame *parent, wxWindowID id, const wxPoint& pos,
, x(0), y(0), winpos(0)
, Parent(parent), m_ignoreLogTimer(false), m_LogAccess(true)
, m_Log(NULL), m_cmdline(NULL), m_FontChoice(NULL)
, m_SJISConv(wxConvLocal)
, m_SJISConv(wxT(""))
{
#ifdef _WIN32
static bool validCP932 = ::IsValidCodePage(932) != 0;
@@ -52,6 +52,7 @@ CLogWindow::CLogWindow(CFrame *parent, wxWindowID id, const wxPoint& pos,
else
{
WARN_LOG(COMMON, "Cannot Convert from Charset Windows Japanese cp 932");
m_SJISConv = *(wxCSConv*)wxConvCurrent;
}
#else
// on linux the wrong string is returned from wxFontMapper::GetEncodingName(wxFONTENCODING_SHIFT_JIS)
@@ -56,11 +56,12 @@ static bool bProcessFifoToLoWatermark = false;
static bool bProcessFifoAllDistance = false;
volatile bool isPossibleWaitingSetDrawDone = false;
volatile bool isHiWatermarkActive = false;
volatile bool interruptSet= false;
volatile bool interruptWaiting= false;
volatile bool interruptTokenWaiting = false;
volatile bool interruptFinishWaiting = false;
volatile bool OnOverflow = false;
volatile bool waitingForPEInterruptDisable = false;
bool IsOnThread()
{
@@ -86,13 +87,12 @@ void DoState(PointerWrap &p)
p.Do(bProcessFifoToLoWatermark);
p.Do(bProcessFifoAllDistance);
p.Do(isHiWatermarkActive);
p.Do(isPossibleWaitingSetDrawDone);
p.Do(interruptSet);
p.Do(interruptWaiting);
p.Do(interruptTokenWaiting);
p.Do(interruptFinishWaiting);
p.Do(OnOverflow);
}
inline void WriteLow (volatile u32& _reg, u16 lowbits) {Common::AtomicStore(_reg,(_reg & 0xFFFF0000) | lowbits);}
@@ -135,16 +135,14 @@ void Init()
bProcessFifoToLoWatermark = false;
bProcessFifoAllDistance = false;
isPossibleWaitingSetDrawDone = false;
OnOverflow = false;
isHiWatermarkActive = false;
et_UpdateInterrupts = CoreTiming::RegisterEvent("UpdateInterrupts", UpdateInterrupts_Wrapper);
}
void Read16(u16& _rReturnValue, const u32 _Address)
{
INFO_LOG(COMMANDPROCESSOR, "(r): 0x%08x", _Address);
ProcessFifoEvents();
switch (_Address & 0xFFF)
{
case STATUS_REGISTER:
@@ -173,11 +171,23 @@ void Read16(u16& _rReturnValue, const u32 _Address)
case FIFO_LO_WATERMARK_HI: _rReturnValue = ReadHigh(fifo.CPLoWatermark); return;
case FIFO_RW_DISTANCE_LO:
_rReturnValue = ReadLow (fifo.CPReadWriteDistance);
if (IsOnThread())
if(fifo.CPWritePointer >= fifo.SafeCPReadPointer)
_rReturnValue = ReadLow (fifo.CPWritePointer - fifo.SafeCPReadPointer);
else
_rReturnValue = ReadLow (fifo.CPEnd - fifo.SafeCPReadPointer + fifo.CPWritePointer - fifo.CPBase + 32);
else
_rReturnValue = ReadLow (fifo.CPReadWriteDistance);
DEBUG_LOG(COMMANDPROCESSOR, "read FIFO_RW_DISTANCE_LO : %04x", _rReturnValue);
return;
case FIFO_RW_DISTANCE_HI:
_rReturnValue = ReadHigh(fifo.CPReadWriteDistance);
if (IsOnThread())
if(fifo.CPWritePointer >= fifo.SafeCPReadPointer)
_rReturnValue = ReadHigh (fifo.CPWritePointer - fifo.SafeCPReadPointer);
else
_rReturnValue = ReadHigh (fifo.CPEnd - fifo.SafeCPReadPointer + fifo.CPWritePointer - fifo.CPBase + 32);
else
_rReturnValue = ReadHigh(fifo.CPReadWriteDistance);
DEBUG_LOG(COMMANDPROCESSOR, "read FIFO_RW_DISTANCE_HI : %04x", _rReturnValue);
return;
case FIFO_WRITE_POINTER_LO:
@@ -358,6 +368,7 @@ void Write16(const u16 _Value, const u32 _Address)
break;
case FIFO_READ_POINTER_HI:
WriteHigh((u32 &)fifo.CPReadPointer, _Value);
fifo.SafeCPReadPointer = fifo.CPReadPointer;
DEBUG_LOG(COMMANDPROCESSOR,"\t write to FIFO_READ_POINTER_HI : %04x", _Value);
break;
@@ -390,10 +401,6 @@ void Write16(const u16 _Value, const u32 _Address)
case FIFO_RW_DISTANCE_HI:
WriteHigh((u32 &)fifo.CPReadWriteDistance, _Value);
DEBUG_LOG(COMMANDPROCESSOR,"try to write to FIFO_RW_DISTANCE_HI : %04x", _Value);
break;
case FIFO_RW_DISTANCE_LO:
WriteLow((u32 &)fifo.CPReadWriteDistance, _Value & 0xFFE0);
if (fifo.CPReadWriteDistance == 0)
{
GPFifo::ResetGatherPipe();
@@ -403,6 +410,10 @@ void Write16(const u16 _Value, const u32 _Address)
ResetVideoBuffer();
}
IncrementCheckContextId();
DEBUG_LOG(COMMANDPROCESSOR,"try to write to FIFO_RW_DISTANCE_HI : %04x", _Value);
break;
case FIFO_RW_DISTANCE_LO:
WriteLow((u32 &)fifo.CPReadWriteDistance, _Value & 0xFFE0);
DEBUG_LOG(COMMANDPROCESSOR,"try to write to FIFO_RW_DISTANCE_LO : %04x", _Value);
break;
@@ -412,7 +423,6 @@ void Write16(const u16 _Value, const u32 _Address)
if (!IsOnThread())
RunGpu();
ProcessFifoEvents();
}
void Read32(u32& _rReturnValue, const u32 _Address)
@@ -434,6 +444,19 @@ void STACKALIGN GatherPipeBursted()
{
if (!IsOnThread())
RunGpu();
else
{
// In multibuffer mode is not allowed write in the same fifo attached to the GPU.
// Fix Pokemon XD in DC mode.
if((ProcessorInterface::Fifo_CPUEnd == fifo.CPEnd) && (ProcessorInterface::Fifo_CPUBase == fifo.CPBase)
&& fifo.CPReadWriteDistance > 0)
{
waitingForPEInterruptDisable = true;
ProcessFifoAllDistance();
waitingForPEInterruptDisable = false;
}
}
return;
}
@@ -449,26 +472,7 @@ void STACKALIGN GatherPipeBursted()
Common::AtomicAdd(fifo.CPReadWriteDistance, GATHER_PIPE_SIZE);
if (!IsOnThread())
{
RunGpu();
}
else
{
if(fifo.CPReadWriteDistance == fifo.CPEnd - fifo.CPBase - 32)
{
if(!OnOverflow)
NOTICE_LOG(COMMANDPROCESSOR,"FIFO is almost in overflown, BreakPoint: %i", fifo.bFF_Breakpoint);
OnOverflow = true;
while (!CommandProcessor::interruptWaiting && fifo.bFF_GPReadEnable &&
fifo.CPReadWriteDistance > fifo.CPEnd - fifo.CPBase - 64)
Common::YieldCPU();
}
else
{
OnOverflow = false;
}
}
_assert_msg_(COMMANDPROCESSOR, fifo.CPReadWriteDistance <= fifo.CPEnd - fifo.CPBase,
"FIFO is overflown by GatherPipe !\nCPU thread is too fast!");
@@ -509,17 +513,15 @@ void AbortFrame()
void SetOverflowStatusFromGatherPipe()
{
if (!fifo.bFF_HiWatermarkInt) return;
fifo.bFF_HiWatermark = (fifo.CPReadWriteDistance > fifo.CPHiWatermark);
fifo.bFF_LoWatermark = (fifo.CPReadWriteDistance < fifo.CPLoWatermark);
bool interrupt = fifo.bFF_HiWatermark && fifo.bFF_HiWatermarkInt &&
m_CPCtrlReg.GPLinkEnable && m_CPCtrlReg.GPReadEnable;
isHiWatermarkActive = fifo.bFF_HiWatermark && fifo.bFF_HiWatermarkInt && m_CPCtrlReg.GPReadEnable;
if (interrupt != interruptSet && interrupt)
CommandProcessor::UpdateInterrupts(true);
if (isHiWatermarkActive)
{
interruptSet = true;
INFO_LOG(COMMANDPROCESSOR,"Interrupt set");
ProcessorInterface::SetInterrupt(INT_CAUSE_CP, true);
}
}
void SetCpStatus()
@@ -527,14 +529,12 @@ void SetCpStatus()
// overflow & underflow check
fifo.bFF_HiWatermark = (fifo.CPReadWriteDistance > fifo.CPHiWatermark);
fifo.bFF_LoWatermark = (fifo.CPReadWriteDistance < fifo.CPLoWatermark);
// breakpoint
// breakpoint
if (fifo.bFF_BPEnable)
{
if (fifo.CPBreakpoint == fifo.CPReadPointer)
{
{
if (!fifo.bFF_Breakpoint)
{
INFO_LOG(COMMANDPROCESSOR, "Hit breakpoint at %i", fifo.CPReadPointer);
@@ -562,13 +562,18 @@ void SetCpStatus()
bool interrupt = (bpInt || ovfInt || undfInt) && m_CPCtrlReg.GPReadEnable;
isHiWatermarkActive = ovfInt && m_CPCtrlReg.GPReadEnable;
if (interrupt != interruptSet && !interruptWaiting)
{
u64 userdata = interrupt?1:0;
if (IsOnThread())
{
interruptWaiting = true;
CommandProcessor::UpdateInterruptsFromVideoBackend(userdata);
if(!interrupt || bpInt || undfInt)
{
interruptWaiting = true;
CommandProcessor::UpdateInterruptsFromVideoBackend(userdata);
}
}
else
CommandProcessor::UpdateInterrupts(userdata);
@@ -591,7 +596,7 @@ void ProcessFifoAllDistance()
if (IsOnThread())
{
while (!CommandProcessor::interruptWaiting && fifo.bFF_GPReadEnable &&
fifo.CPReadWriteDistance && !AtBreakpoint())
fifo.CPReadWriteDistance && !AtBreakpoint() && !PixelEngine::WaitingForPEInterrupt())
Common::YieldCPU();
}
bProcessFifoAllDistance = false;
@@ -611,13 +616,16 @@ void Shutdown()
void SetCpStatusRegister()
{
// Here always there is one fifo attached to the GPU
m_CPStatusReg.Breakpoint = fifo.bFF_Breakpoint;
m_CPStatusReg.ReadIdle = (fifo.CPReadPointer == fifo.CPWritePointer) || (fifo.CPReadPointer == fifo.CPBreakpoint);
m_CPStatusReg.ReadIdle = !fifo.CPReadWriteDistance || (fifo.CPReadPointer == fifo.CPWritePointer) || (fifo.CPReadPointer == fifo.CPBreakpoint) ;
m_CPStatusReg.CommandIdle = !fifo.CPReadWriteDistance;
m_CPStatusReg.UnderflowLoWatermark = fifo.bFF_LoWatermark;
m_CPStatusReg.OverflowHiWatermark = fifo.bFF_HiWatermark;
// HACK to compensate for slow response to PE interrupts in Time Splitters: Future Perfect
if (IsOnThread())
PixelEngine::ResumeWaitingForPEInterrupt();
INFO_LOG(COMMANDPROCESSOR,"\t Read from STATUS_REGISTER : %04x", m_CPStatusReg.Hex);
DEBUG_LOG(COMMANDPROCESSOR, "(r) status: iBP %s | fReadIdle %s | fCmdIdle %s | iOvF %s | iUndF %s"
, m_CPStatusReg.Breakpoint ? "ON" : "OFF"
@@ -630,14 +638,14 @@ void SetCpStatusRegister()
void SetCpControlRegister()
{
// If the new fifo is being attached We make sure there wont be SetFinish event pending.
// This protection fix eternal darkness booting, because the second SetFinish event when it is booting
// seems invalid or has a bug and hang the game.
if (!fifo.bFF_GPReadEnable && m_CPCtrlReg.GPReadEnable && !m_CPCtrlReg.BPEnable)
{
PixelEngine::ResetSetFinish();
ProcessFifoEvents();
PixelEngine::ResetSetFinish();
}
fifo.bFF_BPInt = m_CPCtrlReg.BPInt;
@@ -652,9 +660,6 @@ void SetCpControlRegister()
ProcessorInterface::Fifo_CPUBase = fifo.CPBase;
ProcessorInterface::Fifo_CPUEnd = fifo.CPEnd;
}
// If overflown happens process the fifo to LoWatemark
if (bProcessFifoToLoWatermark)
ProcessFifoToLoWatermark();
if(fifo.bFF_GPReadEnable && !m_CPCtrlReg.GPReadEnable)
{
@@ -666,7 +671,6 @@ void SetCpControlRegister()
fifo.bFF_GPReadEnable = m_CPCtrlReg.GPReadEnable;
}
DEBUG_LOG(COMMANDPROCESSOR, "\t GPREAD %s | BP %s | Int %s | OvF %s | UndF %s | LINK %s"
, fifo.bFF_GPReadEnable ? "ON" : "OFF"
, fifo.bFF_BPEnable ? "ON" : "OFF"
@@ -25,18 +25,18 @@ class PointerWrap;
extern bool MT;
namespace CommandProcessor
{
extern SCPFifoStruct fifo; //This one is shared between gfx thread and emulator thread.
extern volatile bool isPossibleWaitingSetDrawDone; //This one is used for sync gfx thread and emulator thread.
extern volatile bool isHiWatermarkActive;
extern volatile bool interruptSet;
extern volatile bool interruptWaiting;
extern volatile bool interruptTokenWaiting;
extern volatile bool interruptFinishWaiting;
extern volatile bool OnOverflow;
extern volatile bool waitingForPEInterruptDisable;
// internal hardware addresses
enum
{
+2 -2
View File
@@ -22,6 +22,7 @@
#include "Atomic.h"
#include "OpcodeDecoding.h"
#include "CommandProcessor.h"
#include "PixelEngine.h"
#include "ChunkFile.h"
#include "Fifo.h"
#include "HW/Memmap.h"
@@ -137,8 +138,7 @@ void RunGpuLoop()
CommandProcessor::SetCpStatus();
// check if we are able to run this buffer
while (!CommandProcessor::interruptWaiting && fifo.bFF_GPReadEnable &&
fifo.CPReadWriteDistance && (!AtBreakpoint() || CommandProcessor::OnOverflow))
while (GpuRunningState && !CommandProcessor::interruptWaiting && fifo.bFF_GPReadEnable && fifo.CPReadWriteDistance && !AtBreakpoint() && !PixelEngine::WaitingForPEInterrupt())
{
if (!GpuRunningState) break;
+5
View File
@@ -250,6 +250,11 @@ bool VideoBackendHardware::Video_IsPossibleWaitingSetDrawDone()
return CommandProcessor::isPossibleWaitingSetDrawDone;
}
bool VideoBackendHardware::Video_IsHiWatermarkActive()
{
return CommandProcessor::isHiWatermarkActive;
}
void VideoBackendHardware::Video_AbortFrame()
{
CommandProcessor::AbortFrame();
+13 -11
View File
@@ -180,7 +180,6 @@ void Init()
void Read16(u16& _uReturnValue, const u32 _iAddress)
{
DEBUG_LOG(PIXELENGINE, "(r16) 0x%08x", _iAddress);
CommandProcessor::ProcessFifoEvents();
switch (_iAddress & 0xFFF)
{
// CPU Direct Access EFB Raster State Config
@@ -327,7 +326,6 @@ void Write16(const u16 _iValue, const u32 _iAddress)
break;
case PE_TOKEN_REG:
//LOG(PIXELENGINE,"WEIRD: program wrote token: %i",_iValue);
PanicAlert("(w16) WTF? PowerPC program wrote token: %i", _iValue);
//only the gx pipeline is supposed to be able to write here
//g_token = _iValue;
@@ -338,7 +336,6 @@ void Write16(const u16 _iValue, const u32 _iAddress)
break;
}
CommandProcessor::ProcessFifoEvents();
}
void Write32(const u32 _iValue, const u32 _iAddress)
@@ -362,22 +359,16 @@ void UpdateInterrupts()
void UpdateTokenInterrupt(bool active)
{
if(interruptSetToken != active)
{
ProcessorInterface::SetInterrupt(INT_CAUSE_PE_TOKEN, active);
interruptSetToken = active;
}
}
void UpdateFinishInterrupt(bool active)
{
if(interruptSetFinish != active)
{
ProcessorInterface::SetInterrupt(INT_CAUSE_PE_FINISH, active);
interruptSetFinish = active;
if (active)
State::ProcessRequestedStates(0);
}
}
// TODO(mb2): Refactor SetTokenINT_OnMainThread(u64 userdata, int cyclesLate).
@@ -396,8 +387,6 @@ void SetToken_OnMainThread(u64 userdata, int cyclesLate)
CommandProcessor::interruptTokenWaiting = false;
IncrementCheckContextId();
//}
//else
// LOGV(PIXELENGINE, 1, "VIDEO Backend wrote token: %i", CommandProcessor::fifo.PEToken);
}
void SetFinish_OnMainThread(u64 userdata, int cyclesLate)
@@ -474,4 +463,17 @@ void ResetSetToken()
}
CommandProcessor::interruptTokenWaiting = false;
}
bool WaitingForPEInterrupt()
{
return !CommandProcessor::waitingForPEInterruptDisable && (CommandProcessor::interruptFinishWaiting || CommandProcessor::interruptTokenWaiting || interruptSetFinish || interruptSetToken);
}
void ResumeWaitingForPEInterrupt()
{
interruptSetFinish = false;
interruptSetToken = false;
CommandProcessor::interruptFinishWaiting = false;
CommandProcessor::interruptTokenWaiting = false;
}
} // end of namespace PixelEngine
+2 -1
View File
@@ -80,7 +80,8 @@ void SetToken(const u16 _token, const int _bSetTokenAcknowledge);
void SetFinish(void);
void ResetSetFinish(void);
void ResetSetToken(void);
bool AllowIdleSkipping();
bool WaitingForPEInterrupt();
void ResumeWaitingForPEInterrupt();
// Bounding box functionality. Paper Mario (both) are a couple of the few games that use it.
extern u16 bbox[4];
@@ -172,8 +172,10 @@ void TextureCache::ClearRenderTargets()
TexCache::iterator
iter = textures.begin(),
tcend = textures.end();
for (; iter!=tcend; ++iter)
iter->second->type = TCET_NORMAL;
if (iter->second->type != TCET_EC_DYNAMIC)
iter->second->type = TCET_NORMAL;
}
TextureCache::TCacheEntryBase* TextureCache::Load(unsigned int stage,
@@ -238,6 +240,9 @@ TextureCache::TCacheEntryBase* TextureCache::Load(unsigned int stage,
// 2. a) For EFB copies, only the hash and the texture address need to match
if (entry->IsEfbCopy() && tex_hash == entry->hash && address == entry->addr)
{
if (entry->type != TCET_EC_VRAM)
entry->type = TCET_NORMAL;
// TODO: Print a warning if the format changes! In this case, we could reinterpret the internal texture object data to the new pixel format (similiar to what is already being done in Renderer::ReinterpretPixelFormat())
goto return_entry;
}
@@ -318,8 +323,8 @@ TextureCache::TCacheEntryBase* TextureCache::Load(unsigned int stage,
entry->SetGeneralParameters(address, texture_size, full_format, entry->num_mipmaps);
entry->SetDimensions(nativeW, nativeH, width, height);
entry->hash = tex_hash;
if (g_ActiveConfig.bCopyEFBToTexture) entry->type = TCET_NORMAL;
else if (entry->IsEfbCopy()) entry->type = TCET_EC_DYNAMIC;
if (entry->IsEfbCopy() && !g_ActiveConfig.bCopyEFBToTexture) entry->type = TCET_EC_DYNAMIC;
else entry->type = TCET_NORMAL;
// load texture
entry->Load(width, height, expandedWidth, 0, (texLevels == 0));
@@ -647,8 +652,11 @@ void TextureCache::CopyRenderTargetToTexture(u32 dstAddr, unsigned int dstFormat
if ((entry->type == TCET_EC_VRAM && entry->virtual_width == scaled_tex_w && entry->virtual_height == scaled_tex_h)
|| (entry->type == TCET_EC_DYNAMIC && entry->native_width == tex_w && entry->native_height == tex_h))
{
scaled_tex_w = tex_w;
scaled_tex_h = tex_h;
if (entry->type == TCET_EC_DYNAMIC)
{
scaled_tex_w = tex_w;
scaled_tex_h = tex_h;
}
}
else
{
@@ -215,6 +215,12 @@ bool VideoSoftware::Video_IsPossibleWaitingSetDrawDone(void)
return false;
}
bool VideoSoftware::Video_IsHiWatermarkActive(void)
{
return false;
}
void VideoSoftware::Video_AbortFrame(void)
{
}
@@ -36,7 +36,7 @@ class VideoSoftware : public VideoBackend
void Video_SetRendering(bool bEnabled);
void Video_GatherPipeBursted();
bool Video_IsHiWatermarkActive();
bool Video_IsPossibleWaitingSetDrawDone();
void Video_AbortFrame();
-1
View File
@@ -19,7 +19,6 @@
<FunctionLevelLinking>false</FunctionLevelLinking>
<PreprocessorDefinitions>_SECURE_SCL=0;_CRT_SECURE_NO_WARNINGS;_CRT_SECURE_NO_DEPRECATE;%(PreprocessorDefinitions)</PreprocessorDefinitions>
<EnableEnhancedInstructionSet>StreamingSIMDExtensions2</EnableEnhancedInstructionSet>
<FloatingPointModel>Fast</FloatingPointModel>
</ClCompile>
<Link>
<OptimizeReferences>true</OptimizeReferences>