Bug fixes

This commit is contained in:
ergo720 2022-01-03 11:12:45 +01:00
parent 114be1b7c9
commit b664488274
13 changed files with 72 additions and 73 deletions

View File

@ -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;
}

View File

@ -16,9 +16,6 @@
namespace xbox
{
#define PsGetCurrentThread() (CONTAINING_RECORD((KeGetCurrentThread()),ETHREAD,Tcb))
// ******************************************************************
// * PsCreateSystemThread
// ******************************************************************

View File

@ -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

View File

@ -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();
}

View File

@ -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()

View File

@ -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();

View File

@ -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);

View File

@ -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;

View File

@ -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--;

View File

@ -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

View File

@ -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;

View File

@ -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];

View File

@ -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