Bug fixes
This commit is contained in:
parent
114be1b7c9
commit
b664488274
|
@ -1867,8 +1867,6 @@ extern IMGUI_IMPL_API LRESULT ImGui_ImplWin32_WndProcHandler(HWND hWnd, UINT msg
|
|||
// rendering window message procedure
|
||||
static LRESULT WINAPI EmuMsgProc(HWND hWnd, UINT msg, WPARAM wParam, LPARAM lParam)
|
||||
{
|
||||
static bool bAutoPaused = false;
|
||||
|
||||
const LRESULT imguiResult = ImGui_ImplWin32_WndProcHandler(hWnd, msg, wParam, lParam);
|
||||
if (imguiResult != 0) return imguiResult;
|
||||
|
||||
|
@ -2035,27 +2033,10 @@ static LRESULT WINAPI EmuMsgProc(HWND hWnd, UINT msg, WPARAM wParam, LPARAM lPar
|
|||
{
|
||||
switch(wParam)
|
||||
{
|
||||
case SIZE_RESTORED:
|
||||
case SIZE_MAXIMIZED:
|
||||
{
|
||||
if(bAutoPaused)
|
||||
{
|
||||
bAutoPaused = false;
|
||||
CxbxKrnlResume();
|
||||
}
|
||||
}
|
||||
break;
|
||||
|
||||
case SIZE_MINIMIZED:
|
||||
{
|
||||
if(g_XBVideo.bFullScreen)
|
||||
CxbxrKrnlAbort(nullptr);
|
||||
|
||||
if(!g_bEmuSuspended)
|
||||
{
|
||||
bAutoPaused = true;
|
||||
CxbxKrnlSuspend();
|
||||
}
|
||||
}
|
||||
break;
|
||||
}
|
||||
|
|
|
@ -16,9 +16,6 @@
|
|||
|
||||
namespace xbox
|
||||
{
|
||||
|
||||
#define PsGetCurrentThread() (CONTAINING_RECORD((KeGetCurrentThread()),ETHREAD,Tcb))
|
||||
|
||||
// ******************************************************************
|
||||
// * PsCreateSystemThread
|
||||
// ******************************************************************
|
||||
|
|
|
@ -263,6 +263,26 @@ xbox::void_xt NTAPI xbox::KeInitializeTimer
|
|||
KeInitializeTimerEx(Timer, NotificationTimer);
|
||||
}
|
||||
|
||||
// ******************************************************************
|
||||
// * KeEmptyQueueApc()
|
||||
// ******************************************************************
|
||||
xbox::void_xt xbox::KeEmptyQueueApc()
|
||||
{
|
||||
PKTHREAD kThread = KeGetCurrentThread();
|
||||
kThread->ApcState.ApcQueueable = FALSE;
|
||||
|
||||
KiApcListMtx.lock();
|
||||
for (int Mode = KernelMode; Mode < MaximumMode; ++Mode) {
|
||||
while (!IsListEmpty(&kThread->ApcState.ApcListHead[Mode])) {
|
||||
PLIST_ENTRY Entry = kThread->ApcState.ApcListHead[Mode].Flink;
|
||||
PKAPC Apc = CONTAINING_RECORD(Entry, KAPC, ApcListEntry);
|
||||
RemoveEntryList(Entry);
|
||||
ExFreePool(Apc);
|
||||
}
|
||||
}
|
||||
KiApcListMtx.unlock();
|
||||
}
|
||||
|
||||
// Forward KeLowerIrql() to KfLowerIrql()
|
||||
#define KeLowerIrql(NewIrql) \
|
||||
KfLowerIrql(NewIrql)
|
||||
|
@ -1027,9 +1047,9 @@ XBSYSAPI EXPORTNUM(118) xbox::boolean_xt NTAPI xbox::KeInsertQueueApc
|
|||
RETURN(FALSE);
|
||||
}
|
||||
else {
|
||||
g_ApcListMtx.lock();
|
||||
KiApcListMtx.lock();
|
||||
InsertTailList(&kThread->ApcState.ApcListHead[Apc->ApcMode], &Apc->ApcListEntry);
|
||||
g_ApcListMtx.unlock();
|
||||
KiApcListMtx.unlock();
|
||||
Apc->Inserted = TRUE;
|
||||
|
||||
// We can only attempt to execute the queued apc right away if it is been inserted in the current thread, because otherwise the KTHREAD
|
||||
|
|
|
@ -27,14 +27,16 @@
|
|||
|
||||
namespace xbox
|
||||
{
|
||||
xbox::void_xt NTAPI KeSetSystemTime
|
||||
void_xt NTAPI KeSetSystemTime
|
||||
(
|
||||
IN PLARGE_INTEGER NewTime,
|
||||
OUT PLARGE_INTEGER OldTime
|
||||
);
|
||||
|
||||
xbox::void_xt NTAPI KeInitializeTimer
|
||||
void_xt NTAPI KeInitializeTimer
|
||||
(
|
||||
IN PKTIMER Timer
|
||||
);
|
||||
|
||||
void_xt KeEmptyQueueApc();
|
||||
}
|
||||
|
|
|
@ -95,6 +95,7 @@ xbox::KDPC KiTimerExpireDpc;
|
|||
xbox::KI_TIMER_LOCK KiTimerMtx;
|
||||
xbox::KTIMER_TABLE_ENTRY KiTimerTableListHead[TIMER_TABLE_SIZE];
|
||||
xbox::LIST_ENTRY KiWaitInListHead;
|
||||
std::mutex xbox::KiApcListMtx;
|
||||
|
||||
|
||||
xbox::void_xt xbox::KiInitSystem()
|
||||
|
@ -895,16 +896,16 @@ static xbox::void_xt KiExecuteApc()
|
|||
}
|
||||
|
||||
// Even though the apc list is per-thread, it's still possible that another thread will access it while we are processing it below
|
||||
xbox::g_ApcListMtx.lock();
|
||||
xbox::KiApcListMtx.lock();
|
||||
while (!IsListEmpty(&kThread->ApcState.ApcListHead[ApcMode])) {
|
||||
if (KernelApc && (kThread->KernelApcDisable != 0)) {
|
||||
xbox::g_ApcListMtx.unlock();
|
||||
xbox::KiApcListMtx.unlock();
|
||||
return;
|
||||
}
|
||||
xbox::PLIST_ENTRY Entry = kThread->ApcState.ApcListHead[ApcMode].Flink;
|
||||
xbox::PKAPC Apc = CONTAINING_RECORD(Entry, xbox::KAPC, ApcListEntry);
|
||||
RemoveEntryList(Entry);
|
||||
xbox::g_ApcListMtx.unlock();
|
||||
xbox::KiApcListMtx.unlock();
|
||||
Apc->Inserted = FALSE;
|
||||
|
||||
// NOTE: we never use KernelRoutine
|
||||
|
@ -913,10 +914,10 @@ static xbox::void_xt KiExecuteApc()
|
|||
}
|
||||
|
||||
xbox::ExFreePool(Apc);
|
||||
xbox::g_ApcListMtx.lock();
|
||||
xbox::KiApcListMtx.lock();
|
||||
}
|
||||
|
||||
xbox::g_ApcListMtx.unlock();
|
||||
xbox::KiApcListMtx.unlock();
|
||||
}
|
||||
|
||||
xbox::void_xt xbox::KiExecuteKernelApc()
|
||||
|
|
|
@ -48,7 +48,7 @@ namespace xbox
|
|||
} KI_TIMER_LOCK;
|
||||
|
||||
// NOTE: since the apc list is per-thread, we could also create a different mutex for each kthread
|
||||
std::mutex g_ApcListMtx;
|
||||
extern std::mutex KiApcListMtx;
|
||||
|
||||
void_xt KiInitSystem();
|
||||
|
||||
|
|
|
@ -716,18 +716,28 @@ XBSYSAPI EXPORTNUM(197) xbox::ntstatus_xt NTAPI xbox::NtDuplicateObject
|
|||
// On the xbox, the duplicated handle always has the same access rigths of the source handle
|
||||
const ACCESS_MASK DesiredAccess = 0;
|
||||
const ULONG Attributes = 0;
|
||||
dword_xt nativeOptions = (Options | DUPLICATE_SAME_ATTRIBUTES | DUPLICATE_SAME_ACCESS);
|
||||
const ULONG nativeOptions = (Options | DUPLICATE_SAME_ATTRIBUTES | DUPLICATE_SAME_ACCESS);
|
||||
|
||||
if (const auto &nativeHandle = GetNativeHandle(SourceHandle)) {
|
||||
// If SourceHandle is -2 = NtCurrentThread, then we need to duplicate the handle of this thread
|
||||
// Test case: Metal Slug 3
|
||||
std::optional<HANDLE> nativeHandle;
|
||||
if (SourceHandle == NtCurrentThread()) {
|
||||
nativeHandle = GetNativeHandle(PspGetCurrentThread()->UniqueThread);
|
||||
}
|
||||
else {
|
||||
nativeHandle = GetNativeHandle(SourceHandle);
|
||||
}
|
||||
|
||||
if (nativeHandle) {
|
||||
// This was a handle created by Ob
|
||||
PVOID Object;
|
||||
status = ObReferenceObjectByHandle(SourceHandle, /*ObjectType=*/nullptr, &Object);
|
||||
status = ObReferenceObjectByHandle(SourceHandle, zeroptr, &Object);
|
||||
if (X_NT_SUCCESS(status)) {
|
||||
if (ObpIsFlagSet(Options, DUPLICATE_CLOSE_SOURCE)) {
|
||||
NtClose(SourceHandle);
|
||||
}
|
||||
|
||||
status = ObOpenObjectByPointer(Object, OBJECT_TO_OBJECT_HEADER(Object)->Type, /*OUT*/TargetHandle);
|
||||
status = ObOpenObjectByPointer(Object, OBJECT_TO_OBJECT_HEADER(Object)->Type, TargetHandle);
|
||||
if (!X_NT_SUCCESS(status)) {
|
||||
*TargetHandle = NULL;
|
||||
RETURN(status);
|
||||
|
@ -2208,16 +2218,17 @@ XBSYSAPI EXPORTNUM(235) xbox::ntstatus_xt NTAPI xbox::NtWaitForMultipleObjectsEx
|
|||
if (Alertable && (WaitMode == UserMode)) {
|
||||
bool Exit = false;
|
||||
PETHREAD eThread = PspGetCurrentThread();
|
||||
|
||||
auto &fut = std::async(std::launch::async, [eThread, &Exit]() {
|
||||
while (true) {
|
||||
xbox::g_ApcListMtx.lock();
|
||||
xbox::KiApcListMtx.lock();
|
||||
bool Empty = IsListEmpty(&eThread->Tcb.ApcState.ApcListHead[UserMode]);
|
||||
xbox::g_ApcListMtx.unlock();
|
||||
xbox::KiApcListMtx.unlock();
|
||||
if (Empty == false) {
|
||||
KiExecuteUserApc();
|
||||
// Queue a native APC to the calling thread to forcefully terminate the wait in NtDll::NtWaitForMultipleObjects,
|
||||
// in the case it didn't terminate already
|
||||
QueueUserAPC(EndWait, *GetNativeHandle(eThread->UniqueThread), 0);
|
||||
BOOL t = QueueUserAPC(EndWait, *GetNativeHandle(eThread->UniqueThread), 0);
|
||||
return true;
|
||||
}
|
||||
Sleep(0);
|
||||
|
|
|
@ -1019,7 +1019,7 @@ XBSYSAPI EXPORTNUM(246) xbox::ntstatus_xt NTAPI xbox::ObReferenceObjectByHandle
|
|||
|
||||
if (Handle == NtCurrentThread()) {
|
||||
if ((ObjectType == &PsThreadObjectType) || (ObjectType == NULL)) {
|
||||
Object = PsGetCurrentThread();
|
||||
Object = PspGetCurrentThread();
|
||||
ObjectHeader = OBJECT_TO_OBJECT_HEADER(Object);
|
||||
InterlockedIncrement((::PLONG)(&ObjectHeader->PointerCount));
|
||||
*ReturnedObject = Object;
|
||||
|
|
|
@ -32,6 +32,7 @@
|
|||
|
||||
#include <core\kernel\exports\xboxkrnl.h> // For PsCreateSystemThreadEx, etc.
|
||||
#include "core\kernel\exports\EmuKrnlKi.h"
|
||||
#include "core\kernel\exports\EmuKrnlKe.h"
|
||||
#include <process.h> // For __beginthreadex(), etc.
|
||||
#include <float.h> // For _controlfp constants
|
||||
|
||||
|
@ -291,7 +292,8 @@ XBSYSAPI EXPORTNUM(255) xbox::ntstatus_xt NTAPI xbox::PsCreateSystemThreadEx
|
|||
}
|
||||
}*/
|
||||
|
||||
HANDLE handle = reinterpret_cast<HANDLE>(_beginthreadex(NULL, KernelStackSize, PCSTProxy, iPCSTProxyParam, CREATE_SUSPENDED, nullptr));
|
||||
unsigned int ThreadId;
|
||||
HANDLE handle = reinterpret_cast<HANDLE>(_beginthreadex(NULL, KernelStackSize, PCSTProxy, iPCSTProxyParam, CREATE_SUSPENDED, &ThreadId));
|
||||
if (handle == NULL) {
|
||||
delete iPCSTProxyParam;
|
||||
ObpClose(eThread->UniqueThread);
|
||||
|
@ -300,7 +302,7 @@ XBSYSAPI EXPORTNUM(255) xbox::ntstatus_xt NTAPI xbox::PsCreateSystemThreadEx
|
|||
}
|
||||
|
||||
KiUniqueProcess.StackCount++;
|
||||
RegisterXboxHandle(ThreadHandle, handle);
|
||||
RegisterXboxHandle(*ThreadHandle, handle);
|
||||
RegisterXboxHandle(eThread->UniqueThread, handle);
|
||||
|
||||
g_AffinityPolicy->SetAffinityXbox(handle);
|
||||
|
@ -311,7 +313,8 @@ XBSYSAPI EXPORTNUM(255) xbox::ntstatus_xt NTAPI xbox::PsCreateSystemThreadEx
|
|||
}
|
||||
|
||||
// Log ThreadID identical to how GetCurrentThreadID() is rendered :
|
||||
EmuLog(LOG_LEVEL::DEBUG, "Created Xbox proxy thread. Handle : 0x%X, ThreadId : [0x%.4X]", *ThreadHandle, eThread->UniqueThread);
|
||||
EmuLog(LOG_LEVEL::DEBUG, "Created Xbox proxy thread. Handle : 0x%X, ThreadId : [0x%.4X], Native ThreadId : [0x%.4X]",
|
||||
*ThreadHandle, eThread->UniqueThread, ThreadId);
|
||||
}
|
||||
|
||||
RETURN(X_STATUS_SUCCESS);
|
||||
|
@ -405,20 +408,6 @@ XBSYSAPI EXPORTNUM(258) xbox::void_xt NTAPI xbox::PsTerminateSystemThread
|
|||
}
|
||||
}*/
|
||||
|
||||
PKTHREAD kThread = KeGetCurrentThread();
|
||||
kThread->ApcState.ApcQueueable = FALSE;
|
||||
|
||||
g_ApcListMtx.lock();
|
||||
for (int Mode = KernelMode; Mode < MaximumMode; ++Mode) {
|
||||
while (!IsListEmpty(&kThread->ApcState.ApcListHead[Mode])) {
|
||||
PLIST_ENTRY Entry = kThread->ApcState.ApcListHead[Mode].Flink;
|
||||
PKAPC Apc = CONTAINING_RECORD(Entry, KAPC, ApcListEntry);
|
||||
RemoveEntryList(Entry);
|
||||
ExFreePool(Apc);
|
||||
}
|
||||
}
|
||||
g_ApcListMtx.unlock();
|
||||
|
||||
EmuKeFreeThread();
|
||||
KiUniqueProcess.StackCount--;
|
||||
|
||||
|
|
|
@ -42,6 +42,7 @@
|
|||
#include "EmuEEPROM.h" // For CxbxRestoreEEPROM, EEPROM, XboxFactoryGameRegion
|
||||
#include "core\kernel\exports\EmuKrnl.h"
|
||||
#include "core\kernel\exports\EmuKrnlKi.h"
|
||||
#include "core\kernel\exports\EmuKrnlKe.h"
|
||||
#include "EmuShared.h"
|
||||
#include "core\hle\D3D8\Direct3D9\Direct3D9.h" // For CxbxInitWindow, EmuD3DInit
|
||||
#include "core\hle\DSOUND\DirectSound\DirectSound.hpp" // For CxbxInitAudio
|
||||
|
|
|
@ -45,7 +45,6 @@ CRITICAL_SECTION dbgCritical;
|
|||
// Global Variable(s)
|
||||
volatile thread_local bool g_bEmuException = false;
|
||||
static thread_local bool bOverrideEmuException;
|
||||
volatile bool g_bEmuSuspended = false;
|
||||
volatile bool g_bPrintfOn = true;
|
||||
bool g_DisablePixelShaders = false;
|
||||
bool g_UseAllCores = false;
|
||||
|
|
|
@ -58,7 +58,6 @@ void EmuPrintStackTrace(PCONTEXT ContextRecord);
|
|||
|
||||
// global flags specifying current emulation state
|
||||
extern volatile thread_local bool g_bEmuException;
|
||||
extern volatile bool g_bEmuSuspended;
|
||||
|
||||
// global exception patching address
|
||||
extern void * funcExclude[2048];
|
||||
|
|
|
@ -213,6 +213,8 @@ void EmuKeFreeThread()
|
|||
// This functions is to be used for cxbxr threads that execute xbox code. We can't just call PsTerminateSystemThread because some additional
|
||||
// xbox state is not created for this kind of threads
|
||||
|
||||
xbox::KeEmptyQueueApc();
|
||||
|
||||
xbox::PETHREAD eThread = xbox::PspGetCurrentThread();
|
||||
if (eThread->UniqueThread != NULL) {
|
||||
xbox::NtClose(eThread->UniqueThread);
|
||||
|
@ -782,27 +784,24 @@ void EmuGenerateFS(Xbe::TLS *pTLS, void *pTLSData, xbox::PVOID Ethread)
|
|||
|
||||
// Initialize a fake PrcbData.CurrentThread
|
||||
{
|
||||
// If it is nullptr, it means we are creating this thread from cxbxr, otherwise we were created from PsCreateSystemThreadEx
|
||||
xbox::PETHREAD EThread = static_cast<xbox::PETHREAD>(Ethread);
|
||||
if (EThread == xbox::zeroptr) {
|
||||
// If it is nullptr, it means we are creating this thread from cxbxr, otherwise we were created from PsCreateSystemThreadEx
|
||||
xbox::PETHREAD eThread;
|
||||
xbox::ntstatus_xt result = xbox::ObCreateObject(&xbox::PsThreadObjectType, xbox::zeroptr, sizeof(xbox::ETHREAD), reinterpret_cast<PVOID *>(&eThread));
|
||||
if (!X_NT_SUCCESS(result)) {
|
||||
// We can't recover from here, abort execution
|
||||
CxbxrKrnlAbort("ObCreateObject: failed to create new xbox thread!");
|
||||
}
|
||||
std::memset(eThread, 0, sizeof(xbox::ETHREAD));
|
||||
EThread = eThread;
|
||||
result = xbox::ObInsertObject(eThread, xbox::zeroptr, 0, &eThread->UniqueThread);
|
||||
if (!X_NT_SUCCESS(result)) {
|
||||
// We can't recover from here, abort execution
|
||||
CxbxrKrnlAbort("ObInsertObject: failed to create new xbox thread!");
|
||||
}
|
||||
// Since this a host thread that we use to execute xbox code, we do not need to create ob handles for this thread
|
||||
base = xbox::zeroptr;
|
||||
size = sizeof(xbox::ETHREAD);
|
||||
xbox::NtAllocateVirtualMemory(&base, 0, &size, XBOX_MEM_RESERVE | XBOX_MEM_COMMIT, XBOX_PAGE_READWRITE);
|
||||
EThread = (xbox::ETHREAD *)base; // Clear, to prevent side-effects on random contents
|
||||
xbox::RtlZeroMemory(EThread, sizeof(xbox::ETHREAD));
|
||||
EThread->UniqueThread = reinterpret_cast<HANDLE>(GetCurrentThreadId());
|
||||
}
|
||||
|
||||
EThread->Tcb.TlsData = pNewTLS;
|
||||
// Set PrcbData.CurrentThread
|
||||
Prcb->CurrentThread = (xbox::KTHREAD*)EThread;
|
||||
// Initialize APC stuff
|
||||
InitializeListHead(&Prcb->CurrentThread->ApcState.ApcListHead[xbox::KernelMode]);
|
||||
InitializeListHead(&Prcb->CurrentThread->ApcState.ApcListHead[xbox::UserMode]);
|
||||
Prcb->CurrentThread->KernelApcDisable = 0;
|
||||
Prcb->CurrentThread->ApcState.ApcQueueable = TRUE;
|
||||
// Initialize the thread header and its wait list
|
||||
|
|
Loading…
Reference in New Issue