Merge pull request #1504 from LukeUsher/lets-fix-some-exclusives

Various bug-fixes (TLS, Vertex Shaders, X86)
This commit is contained in:
Luke Usher 2018-11-18 09:18:14 +00:00 committed by GitHub
commit b594f04214
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
14 changed files with 426 additions and 21 deletions

View File

@ -250,6 +250,7 @@ void InputDeviceManager::StartInputThread()
void InputDeviceManager::InputThread(InputDeviceManager* pVoid)
{
SetThreadAffinityMask(GetCurrentThread(), g_CPUOthers);
bool bContinue = true;
SDL_Event event;

View File

@ -2366,7 +2366,6 @@ DWORD WINAPI WndMain::DebuggerMonitor(LPVOID lpVoid)
}
void WndMain::DebuggerMonitorClose()
{
if (m_hDebuggerProc != nullptr) {
HANDLE hDebuggerProcTemp = m_hDebuggerProc;
std::thread hDebuggerMonitorThreadTemp = std::thread(std::move(m_hDebuggerMonitorThread));

View File

@ -602,8 +602,10 @@ void EmuGenerateFS(Xbe::TLS *pTLS, void *pTLSData)
}
// prepare TLS
{
*(xbaddr*)pTLS->dwTLSIndexAddr = xbnull;
{
if (pTLS->dwTLSIndexAddr != 0) {
*(xbaddr*)pTLS->dwTLSIndexAddr = xbnull;
}
// dword @ pTLSData := pTLSData
if (pNewTLS != nullptr)

View File

@ -2942,8 +2942,11 @@ bool EmuX86_DecodeException(LPEXCEPTION_POINTERS e)
}
// Execute op-codes until we hit an unhandled instruction, or an error occurs
while (true)
//for (int x=0;x<3;x++)
//while (true)
// TODO: Find where the weird memory addresses come from when using the above case
// There is obviously something wrong with one or more of our instruction implementations
// For now, we only execute one instruction at a time...
for (int x=0;x<1;x++)
{
if (!EmuX86_DecodeOpcode((uint8_t*)e->ContextRecord->Eip, info)) {
EmuLog(LOG_LEVEL::WARNING, "Error decoding opcode at 0x%08X", e->ContextRecord->Eip);
@ -3294,10 +3297,10 @@ bool EmuX86_DecodeException(LPEXCEPTION_POINTERS e)
if (EmuX86_Opcode_XOR(e, info)) break;
goto opcode_error;
default:
EmuLog(LOG_LEVEL::WARNING, "Unhandled instruction : %s (%u)", Distorm_OpcodeString(info.opcode), info.opcode);
// Fail if the first hit instruction couldn't be emulated,
// but let host CPU execute following (unhandled) instructions :
return (StartingEip != e->ContextRecord->Eip);
EmuLog(LOG_LEVEL::WARNING, "Unhandled instruction : %s (%u)", Distorm_OpcodeString(info.opcode), info.opcode);
// HACK: If we hit an unhandled instruction, log and skip it
e->ContextRecord->Eip += info.size;
return true;
} // switch info.opcode
e->ContextRecord->Eip += info.size;

View File

@ -515,11 +515,6 @@ VOID XTL::CxbxInitWindow(bool bFullInit)
ExitProcess(0);
}
// Ported from Dxbx :
// If possible, assign this thread to another core than the one that runs Xbox1 code :
if (bFullInit)
SetThreadAffinityMask(hRenderWindowThread, g_CPUOthers);
while(!g_bRenderWindowActive)
Sleep(0);
@ -1384,6 +1379,7 @@ static BOOL WINAPI EmuEnumDisplayDevices(GUID FAR *lpGUID, LPSTR lpDriverDescrip
static DWORD WINAPI EmuRenderWindow(LPVOID lpVoid)
{
CxbxSetThreadName("Cxbx Render Window");
SetThreadAffinityMask(GetCurrentThread(), g_CPUOthers);
// register window class
{

View File

@ -1465,6 +1465,21 @@ static void VshRemoveScreenSpaceInstructions(VSH_XBOX_SHADER *pShader)
}
}
static void VshRemoveUnsupportedObRegisters(VSH_XBOX_SHADER *pShader)
{
int deleted = 0;
for (int i = 0; i < pShader->IntermediateCount; i++) {
VSH_INTERMEDIATE_FORMAT* pIntermediate = &pShader->Intermediate[i];
if (pIntermediate->Output.Type == IMD_OUTPUT_O && (pIntermediate->Output.Address == OREG_OB0 || pIntermediate->Output.Address == OREG_OB1)) {
DbgVshPrintf("Deleted unsupported write to %s\n", OReg_Name[pIntermediate->Output.Address]);
VshDeleteIntermediate(pShader, i);
i--;
}
}
}
// Converts the intermediate format vertex shader to DirectX 8 format
static boolean VshConvertShader(VSH_XBOX_SHADER *pShader,
boolean bNoReservedConstants,
@ -1487,6 +1502,10 @@ static boolean VshConvertShader(VSH_XBOX_SHADER *pShader,
VshRemoveScreenSpaceInstructions(pShader);
}
// Windows does not support back-facing colours, so we remove them from the shaders
// Test Case: Panzer Dragoon Orta
VshRemoveUnsupportedObRegisters(pShader);
// TODO: Add routine for compacting r register usage so that at least one is freed (two if dph and r12)
for (int i = 0; i < pShader->IntermediateCount; i++)
@ -1498,7 +1517,21 @@ static boolean VshConvertShader(VSH_XBOX_SHADER *pShader,
if(pIntermediate->Output.Type == IMD_OUTPUT_O && (pIntermediate->Output.Address == OREG_OPTS || pIntermediate->Output.Address == OREG_OFOG))
{
// The PC shader assembler doesn't like masks on scalar registers
VshSetOutputMask(&pIntermediate->Output, TRUE, TRUE, TRUE, TRUE);
VshSetOutputMask(&pIntermediate->Output, TRUE, TRUE, TRUE, TRUE);
// Fix when mad or mov to a scaler input does not use a replicate swizzle
// MAD Test case: Panzer Dragoon Orta
// MOV Test case: DOA3
if ((pIntermediate->InstructionType == IMD_MAC && pIntermediate->MAC == MAC_MAD) ||
(pIntermediate->InstructionType == IMD_MAC && pIntermediate->MAC == MAC_MOV)) {
// Clear all but the first swizzle for each parameter
// TODO: Is this sufficient? Perhaps we need to be smart about which swizzle to select
for (int param = 0; param < 3; param++) {
pIntermediate->Parameters[param].Parameter.Swizzle[1] = pIntermediate->Parameters[param].Parameter.Swizzle[0];
pIntermediate->Parameters[param].Parameter.Swizzle[2] = pIntermediate->Parameters[param].Parameter.Swizzle[0];
pIntermediate->Parameters[param].Parameter.Swizzle[3] = pIntermediate->Parameters[param].Parameter.Swizzle[0];
}
}
}
if(pIntermediate->InstructionType == IMD_ILU && pIntermediate->ILU == ILU_RCC)
@ -1813,11 +1846,11 @@ XTL::D3DDECLUSAGE Xb2PCRegisterType
break;
case X_D3DVSDE_BACKDIFFUSE: // 7
DbgVshPrintf("D3DVSDE_BACKDIFFUSE /* xbox ext. */");
PCRegisterType = D3DDECLUSAGE_UNSUPPORTED;
PCRegisterType = D3DDECLUSAGE_COLOR; PCUsageIndex = 2;
break;
case X_D3DVSDE_BACKSPECULAR: // 8
DbgVshPrintf("D3DVSDE_BACKSPECULAR /* xbox ext. */");
PCRegisterType = D3DDECLUSAGE_UNSUPPORTED;
PCRegisterType = D3DDECLUSAGE_COLOR; PCUsageIndex = 3;
break;
case X_D3DVSDE_TEXCOORD0: // 9
DbgVshPrintf("D3DVSDE_TEXCOORD0");

View File

@ -556,10 +556,11 @@ VOID WINAPI XTL::EMUPATCH(DirectSoundDoWork)()
}
// For Async process purpose only
static void dsound_thread_worker(LPVOID nullPtr)
{
while (true) {
Sleep(0);
{
SetThreadAffinityMask(GetCurrentThread(), g_CPUOthers);
while (true) {
Sleep(0);
enterCriticalSection;
vector_ds_stream::iterator ppDSStream = g_pDSoundStreamCache.begin();

View File

@ -138,7 +138,7 @@ void InitXboxControllerHostBridge(void)
//disconnect to host if the host port of xinput exceeds the total xinput controller connected to host.
if (g_XboxControllerHostBridge[port].dwHostPort >= total_xinput_gamepad) {
g_XboxControllerHostBridge[port].dwHostType = X_XONTROLLER_HOST_BRIDGE_HOSTTYPE_NOTCONNECT;
printf("InitXboxControllerHostBridge: Host XInput port greater then total xinut controller connected. disconnect xbox port from host!\n");
printf("InitXboxControllerHostBridge: Host XInput port greater then total xinput controller connected. disconnect xbox port from host!\n");
}
break;
case X_XONTROLLER_HOST_BRIDGE_HOSTTYPE_DINPUT:

View File

@ -0,0 +1,77 @@
// This is an open source non-commercial project. Dear PVS-Studio, please check it.
// PVS-Studio Static Code Analyzer for C, C++ and C#: http://www.viva64.com
// ******************************************************************
// *
// * .,-::::: .,:: .::::::::. .,:: .:
// * ,;;;'````' `;;;, .,;; ;;;'';;' `;;;, .,;;
// * [[[ '[[,,[[' [[[__[[\. '[[,,[['
// * $$$ Y$$$P $$""""Y$$ Y$$$P
// * `88bo,__,o, oP"``"Yo, _88o,,od8P oP"``"Yo,
// * "YUMMMMMP",m" "Mm,""YUMMMP" ,m" "Mm,
// *
// * src->devices->AC97Device.cpp
// *
// * This file is part of the Cxbx project.
// *
// * Cxbx and Cxbe are free software; you can redistribute them
// * and/or modify them under the terms of the GNU General Public
// * License as published by the Free Software Foundation; either
// * version 2 of the license, or (at your option) any later version.
// *
// * This program is distributed in the hope that it will be useful,
// * but WITHOUT ANY WARRANTY; without even the implied warranty of
// * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
// * GNU General Public License for more details.
// *
// * You should have recieved a copy of the GNU General Public License
// * along with this program; see the file COPYING.
// * If not, write to the Free Software Foundation, Inc.,
// * 59 Temple Place - Suite 330, Bostom, MA 02111-1307, USA.
// *
// * (c) 2018 Luke Usher <luke.usher@outlook.coM>
// *
// * All rights reserved
// *
// ******************************************************************
#include <cstdio>
#include "AC97Device.h"
void AC97Device::Init()
{
PCIBarRegister r;
r.Raw.type = PCI_BAR_TYPE_MEMORY;
r.Memory.address = AC97_BASE >> 4;
RegisterBAR(0, AC97_SIZE, r.value);
m_DeviceId = 0x01B1;
m_VendorId = PCI_VENDOR_ID_NVIDIA;
}
void AC97Device::Reset()
{
}
uint32_t AC97Device::IORead(int barIndex, uint32_t addr, unsigned size)
{
printf("AC97Device: Unimplemented IORead %X\n", addr);
return 0;
}
void AC97Device::IOWrite(int barIndex, uint32_t addr, uint32_t value, unsigned size)
{
printf("AC97Device: Unimplemented IOWrite %X\n", addr);
}
uint32_t AC97Device::MMIORead(int barIndex, uint32_t addr, unsigned size)
{
printf("AC97Device: Unimplemented MMIORead %X\n", addr);
return 0;
}
void AC97Device::MMIOWrite(int barIndex, uint32_t addr, uint32_t value, unsigned size)
{
printf("AC97Device: Unimplemented MMIOWrite %X\n", addr);
}

View File

@ -0,0 +1,57 @@
// This is an open source non-commercial project. Dear PVS-Studio, please check it.
// PVS-Studio Static Code Analyzer for C, C++ and C#: http://www.viva64.com
// ******************************************************************
// *
// * .,-::::: .,:: .::::::::. .,:: .:
// * ,;;;'````' `;;;, .,;; ;;;'';;' `;;;, .,;;
// * [[[ '[[,,[[' [[[__[[\. '[[,,[['
// * $$$ Y$$$P $$""""Y$$ Y$$$P
// * `88bo,__,o, oP"``"Yo, _88o,,od8P oP"``"Yo,
// * "YUMMMMMP",m" "Mm,""YUMMMP" ,m" "Mm,
// *
// * src->devices->AC97Device.h
// *
// * This file is part of the Cxbx project.
// *
// * Cxbx and Cxbe are free software; you can redistribute them
// * and/or modify them under the terms of the GNU General Public
// * License as published by the Free Software Foundation; either
// * version 2 of the license, or (at your option) any later version.
// *
// * This program is distributed in the hope that it will be useful,
// * but WITHOUT ANY WARRANTY; without even the implied warranty of
// * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
// * GNU General Public License for more details.
// *
// * You should have recieved a copy of the GNU General Public License
// * along with this program; see the file COPYING.
// * If not, write to the Free Software Foundation, Inc.,
// * 59 Temple Place - Suite 330, Bostom, MA 02111-1307, USA.
// *
// * (c) 2018 Luke Usher <luke.usher@outlook.com>
// *
// * All rights reserved
// *
// ******************************************************************
#ifndef _AC97_H_
#define _AC97_H_
#include "../PCIDevice.h"
class AC97Device : public PCIDevice {
public:
using PCIDevice::PCIDevice;
// PCI Functions
void Init();
void Reset();
uint32_t IORead(int barIndex, uint32_t addr, unsigned size = sizeof(uint8_t));
void IOWrite(int barIndex, uint32_t addr, uint32_t data, unsigned size = sizeof(uint8_t));
uint32_t MMIORead(int barIndex, uint32_t addr, unsigned size);
void MMIOWrite(int barIndex, uint32_t addr, uint32_t value, unsigned size);
private:
};
#endif

View File

@ -0,0 +1,170 @@
// This is an open source non-commercial project. Dear PVS-Studio, please check it.
// PVS-Studio Static Code Analyzer for C, C++ and C#: http://www.viva64.com
// ******************************************************************
// *
// * .,-::::: .,:: .::::::::. .,:: .:
// * ,;;;'````' `;;;, .,;; ;;;'';;' `;;;, .,;;
// * [[[ '[[,,[[' [[[__[[\. '[[,,[['
// * $$$ Y$$$P $$""""Y$$ Y$$$P
// * `88bo,__,o, oP"``"Yo, _88o,,od8P oP"``"Yo,
// * "YUMMMMMP",m" "Mm,""YUMMMP" ,m" "Mm,
// *
// * src->devices->APUDevice.cpp
// *
// * This file is part of the Cxbx project.
// *
// * Cxbx and Cxbe are free software; you can redistribute them
// * and/or modify them under the terms of the GNU General Public
// * License as published by the Free Software Foundation; either
// * version 2 of the license, or (at your option) any later version.
// *
// * This program is distributed in the hope that it will be useful,
// * but WITHOUT ANY WARRANTY; without even the implied warranty of
// * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
// * GNU General Public License for more details.
// *
// * You should have recieved a copy of the GNU General Public License
// * along with this program; see the file COPYING.
// * If not, write to the Free Software Foundation, Inc.,
// * 59 Temple Place - Suite 330, Bostom, MA 02111-1307, USA.
// *
// * (c) 2018 Luke Usher <luke.usher@outlook.coM>
// *
// * All rights reserved
// *
// ******************************************************************
#include <cstdio>
#include "APUDevice.h"
extern uint32_t GetAPUTime();
// TODO: Everything :P
// TODO: Audio Processing/Thread
#define APU_VP_BASE 0x20000
#define APU_VP_SIZE 0x10000
#define APU_GP_BASE 0x30000
#define APU_GP_SIZE 0x10000
#define APU_EP_BASE 0x50000
#define APU_EP_SIZE 0x10000
void APUDevice::Init()
{
PCIBarRegister r;
r.Raw.type = PCI_BAR_TYPE_IO;
r.IO.address = 0xD000 >> 4;
RegisterBAR(0, 256, r.value);
r.Raw.type = PCI_BAR_TYPE_IO;
r.IO.address = 0xD200 >> 4;
RegisterBAR(0, 128, r.value);
r.Raw.type = PCI_BAR_TYPE_MEMORY;
r.Memory.address = APU_BASE >> 4;
RegisterBAR(2, APU_SIZE, r.value);
m_DeviceId = 0x01B0;
m_VendorId = PCI_VENDOR_ID_NVIDIA;
}
void APUDevice::Reset()
{
}
uint32_t APUDevice::IORead(int barIndex, uint32_t addr, unsigned size)
{
printf("APUDevice: Unimplemented IORead %X\n", addr);
return 0;
}
void APUDevice::IOWrite(int barIndex, uint32_t addr, uint32_t value, unsigned size)
{
printf("APUDevice: Unimplemented IOWrite %X\n", addr);
}
uint32_t APUDevice::MMIORead(int barIndex, uint32_t addr, unsigned size)
{
if (addr >= APU_VP_BASE && addr < APU_VP_BASE + APU_VP_SIZE) {
return VPRead(addr - APU_VP_BASE, size);
}
if (addr >= APU_GP_BASE && addr < APU_GP_BASE + APU_GP_SIZE) {
return GPRead(addr - APU_GP_BASE, size);
}
if (addr >= APU_EP_BASE && addr < APU_EP_BASE + APU_EP_SIZE) {
return EPRead(addr - APU_EP_BASE, size);
}
switch (addr) {
case 0x200C: return GetAPUTime();
}
printf("APUDevice: Unimplemented MMIORead %X\n", addr);
return 0;
}
void APUDevice::MMIOWrite(int barIndex, uint32_t addr, uint32_t value, unsigned size)
{
if (addr >= APU_VP_BASE && addr < APU_VP_BASE + APU_VP_SIZE) {
VPWrite(addr - APU_VP_BASE, value, size);
return;
}
if (addr >= APU_GP_BASE && addr < APU_GP_BASE + APU_GP_SIZE) {
GPWrite(addr - APU_GP_BASE, value, size);
return;
}
if (addr >= APU_EP_BASE && addr < APU_EP_BASE + APU_EP_SIZE) {
EPWrite(addr - APU_EP_BASE, value, size);
return;
}
printf("APUDevice: Unimplemented MMIOWrite %X\n", addr);
}
uint32_t APUDevice::GPRead(uint32_t addr, unsigned size)
{
printf("APUDevice: Unimplemented GP MMIORead %X\n", addr);
return 0;
}
void APUDevice::GPWrite(uint32_t addr, uint32_t value, unsigned size)
{
printf("APUDevice: Unimplemented GP MMIOWrite %X\n", addr);
}
uint32_t APUDevice::VPRead(uint32_t addr, unsigned size)
{
switch (addr) {
case 0x10: return 0x80; // HACK: Pretend the FIFO is always empty, bypasses hangs when APU isn't fully implemented
}
printf("APUDevice: Unimplemented VP MMIORead %X\n", addr);
return 0;
}
void APUDevice::VPWrite(uint32_t addr, uint32_t value, unsigned size)
{
printf("APUDevice: Unimplemented VP MMIOWrite %X\n", addr);
}
uint32_t APUDevice::EPRead(uint32_t addr, unsigned size)
{
printf("APUDevice: Unimplemented EP MMIORead %X\n", addr);
return 0;
}
void APUDevice::EPWrite(uint32_t addr, uint32_t value, unsigned size)
{
printf("APUDevice: Unimplemented EP MMIOWrite %X\n", addr);
}

View File

@ -0,0 +1,63 @@
// This is an open source non-commercial project. Dear PVS-Studio, please check it.
// PVS-Studio Static Code Analyzer for C, C++ and C#: http://www.viva64.com
// ******************************************************************
// *
// * .,-::::: .,:: .::::::::. .,:: .:
// * ,;;;'````' `;;;, .,;; ;;;'';;' `;;;, .,;;
// * [[[ '[[,,[[' [[[__[[\. '[[,,[['
// * $$$ Y$$$P $$""""Y$$ Y$$$P
// * `88bo,__,o, oP"``"Yo, _88o,,od8P oP"``"Yo,
// * "YUMMMMMP",m" "Mm,""YUMMMP" ,m" "Mm,
// *
// * src->devices->APUDevice.h
// *
// * This file is part of the Cxbx project.
// *
// * Cxbx and Cxbe are free software; you can redistribute them
// * and/or modify them under the terms of the GNU General Public
// * License as published by the Free Software Foundation; either
// * version 2 of the license, or (at your option) any later version.
// *
// * This program is distributed in the hope that it will be useful,
// * but WITHOUT ANY WARRANTY; without even the implied warranty of
// * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
// * GNU General Public License for more details.
// *
// * You should have recieved a copy of the GNU General Public License
// * along with this program; see the file COPYING.
// * If not, write to the Free Software Foundation, Inc.,
// * 59 Temple Place - Suite 330, Bostom, MA 02111-1307, USA.
// *
// * (c) 2018 Luke Usher <luke.usher@outlook.com>
// *
// * All rights reserved
// *
// ******************************************************************
#ifndef _APU_H_
#define _APU_H_
#include "../PCIDevice.h"
class APUDevice : public PCIDevice {
public:
using PCIDevice::PCIDevice;
// PCI Functions
void Init();
void Reset();
uint32_t IORead(int barIndex, uint32_t addr, unsigned size = sizeof(uint8_t));
void IOWrite(int barIndex, uint32_t addr, uint32_t data, unsigned size = sizeof(uint8_t));
uint32_t MMIORead(int barIndex, uint32_t addr, unsigned size);
void MMIOWrite(int barIndex, uint32_t addr, uint32_t value, unsigned size);
private:
uint32_t GPRead(uint32_t addr, unsigned size);
void GPWrite(uint32_t addr, uint32_t value, unsigned size);
uint32_t EPRead(uint32_t addr, unsigned size);
void EPWrite(uint32_t addr, uint32_t value, unsigned size);
uint32_t VPRead(uint32_t addr, unsigned size);
void VPWrite(uint32_t addr, uint32_t value, unsigned size);
};
#endif

View File

@ -227,6 +227,7 @@ static void pfifo_run_puller(NV2AState *d)
int pfifo_puller_thread(NV2AState *d)
{
SetThreadAffinityMask(GetCurrentThread(), g_CPUOthers);
CxbxSetThreadName("Cxbx NV2A FIFO puller");
glo_set_current(d->pgraph.gl_context);
@ -461,6 +462,7 @@ static void pfifo_run_pusher(NV2AState *d)
int pfifo_pusher_thread(NV2AState *d)
{
SetThreadAffinityMask(GetCurrentThread(), g_CPUOthers);
CxbxSetThreadName("Cxbx NV2A FIFO pusher");
qemu_mutex_lock(&d->pfifo.pfifo_lock);

View File

@ -1113,6 +1113,7 @@ void NV2ADevice::UpdateHostDisplay(NV2AState *d)
// TODO: Fix this properly
static void nv2a_vblank_thread(NV2AState *d)
{
SetThreadAffinityMask(GetCurrentThread(), g_CPUOthers);
CxbxSetThreadName("Cxbx NV2A VBLANK");
auto nextVBlankTime = GetNextVBlankTime();