From 8b908c4d684291920b9403a85a96d1abd085ac5e Mon Sep 17 00:00:00 2001 From: x1nixmzeng Date: Sat, 13 Jan 2018 00:40:34 +0000 Subject: [PATCH 01/21] Catch exceptions with experimental filesystem library --- src/CxbxKrnl/EmuFile.cpp | 12 ++++++++++-- 1 file changed, 10 insertions(+), 2 deletions(-) diff --git a/src/CxbxKrnl/EmuFile.cpp b/src/CxbxKrnl/EmuFile.cpp index 2b2c25cf8..2c95382c7 100644 --- a/src/CxbxKrnl/EmuFile.cpp +++ b/src/CxbxKrnl/EmuFile.cpp @@ -188,8 +188,16 @@ void CxbxFormatPartitionByHandle(HANDLE hFile) // In this case, experimental means that these functions work and are safe // but not officially in the C++ standard yet // Requires a compiler with C++17 support - std::experimental::filesystem::remove_all(partitionPath); - std::experimental::filesystem::create_directory(partitionPath); + try + { + std::experimental::filesystem::remove_all(partitionPath); + std::experimental::filesystem::create_directory(partitionPath); + } + catch (std::experimental::filesystem::filesystem_error fsException) + { + printf("std::experimental::filesystem failed with message: %s\n", fsException.what()); + } + printf("Formatted EmuDisk Partition%d\n", CxbxGetPartitionNumberFromHandle(hFile)); } From a433ee91c60cec196f7ce141ae398a36091ffbd9 Mon Sep 17 00:00:00 2001 From: jarupxx Date: Sat, 13 Jan 2018 16:33:18 +0900 Subject: [PATCH 02/21] Add XRefSaveIndex into #ifndef WIP_LessVertexPatching --- src/CxbxKrnl/HLEDataBase/D3D8.1.0.4627.inl | 10 ++++++++-- 1 file changed, 8 insertions(+), 2 deletions(-) diff --git a/src/CxbxKrnl/HLEDataBase/D3D8.1.0.4627.inl b/src/CxbxKrnl/HLEDataBase/D3D8.1.0.4627.inl index e1a961f1c..677eecc6a 100644 --- a/src/CxbxKrnl/HLEDataBase/D3D8.1.0.4627.inl +++ b/src/CxbxKrnl/HLEDataBase/D3D8.1.0.4627.inl @@ -176,7 +176,10 @@ OOVPA_END; // * D3D_CommonSetRenderTarget // ****************************************************************** #ifndef WIP_LessVertexPatching -OOVPA_NO_XREF(D3D_CommonSetRenderTarget, 4627, 12) +OOVPA_XREF(D3D_CommonSetRenderTarget, 4627, 12, + + XREF_D3D_CommonSetRenderTarget, + XRefZero) #else OOVPA_XREF(D3D_CommonSetRenderTarget, 4627, 1+12, @@ -498,7 +501,10 @@ OOVPA_END; // * D3DDevice_GetDepthStencilSurface2 // ****************************************************************** #ifndef WIP_LessVertexPatching -OOVPA_NO_XREF(D3DDevice_GetDepthStencilSurface2, 4627, 20) +OOVPA_XREF(D3DDevice_GetDepthStencilSurface2, 4627, 20, + + XREF_D3DDevice_GetDepthStencilSurface2, + XRefZero) #else OOVPA_XREF(D3DDevice_GetDepthStencilSurface2, 4627, 1+20, From 6eca7d5d0b5b521b75668f2ff6d70701f7702ba7 Mon Sep 17 00:00:00 2001 From: patrickvl Date: Sat, 13 Jan 2018 16:33:40 +0100 Subject: [PATCH 03/21] PsCreateSystemThreadEx : Waiting for thread-creation updated, so it waits for the correct handle, avoids access-violations, releases resources correctly and logs additional details on waiting errors. --- src/CxbxKrnl/CxbxKrnl.h | 3 +++ src/CxbxKrnl/EmuKrnlPs.cpp | 41 +++++++++++++++++++++----------------- 2 files changed, 26 insertions(+), 18 deletions(-) diff --git a/src/CxbxKrnl/CxbxKrnl.h b/src/CxbxKrnl/CxbxKrnl.h index 3cbb27740..359125796 100644 --- a/src/CxbxKrnl/CxbxKrnl.h +++ b/src/CxbxKrnl/CxbxKrnl.h @@ -232,4 +232,7 @@ extern char szFilePath_EEPROM_bin[MAX_PATH]; } #endif +// Returns the last Win32 error, in string format. Returns an empty string if there is no error. +extern std::string CxbxGetLastErrorString(char * lpszFunction); + #endif diff --git a/src/CxbxKrnl/EmuKrnlPs.cpp b/src/CxbxKrnl/EmuKrnlPs.cpp index 2641125cc..d24786b6a 100644 --- a/src/CxbxKrnl/EmuKrnlPs.cpp +++ b/src/CxbxKrnl/EmuKrnlPs.cpp @@ -135,6 +135,8 @@ static unsigned int WINAPI PCSTProxy // Do minimal thread initialization InitXboxThread(g_CPUXbox); + SetEvent(hStartedEvent); + if (StartSuspended == TRUE) // Suspend right before calling the thread notification routines SuspendThread(GetCurrentThread()); @@ -159,8 +161,6 @@ static unsigned int WINAPI PCSTProxy // use the special calling convention __try { - SetEvent(hStartedEvent); - // Given the non-standard calling convention (requiring // the first argument in ebp+4) we need the below __asm. // @@ -186,9 +186,6 @@ static unsigned int WINAPI PCSTProxy callComplete: - if (hStartedEvent != NULL) { - CloseHandle(hStartedEvent); - } // This will also handle thread notification : xboxkrnl::PsTerminateSystemThread(STATUS_SUCCESS); @@ -301,6 +298,7 @@ XBSYSAPI EXPORTNUM(255) xboxkrnl::NTSTATUS NTAPI xboxkrnl::PsCreateSystemThreadE { DWORD dwThreadId = 0, dwThreadWait; bool bWait = true; + HANDLE hStartedEvent = CreateEvent(NULL, FALSE, FALSE, TEXT("PCSTProxyEvent")); // PCSTProxy is responsible for cleaning up this pointer ::PCSTProxyParam *iPCSTProxyParam = new ::PCSTProxyParam(); @@ -309,34 +307,41 @@ XBSYSAPI EXPORTNUM(255) xboxkrnl::NTSTATUS NTAPI xboxkrnl::PsCreateSystemThreadE iPCSTProxyParam->StartContext = StartContext; iPCSTProxyParam->SystemRoutine = SystemRoutine; // NULL, XapiThreadStartup or unknown? iPCSTProxyParam->StartSuspended = CreateSuspended; - iPCSTProxyParam->hStartedEvent = CreateEvent(NULL, FALSE, FALSE, TEXT("PCSTProxyEvent")); + iPCSTProxyParam->hStartedEvent = hStartedEvent; *ThreadHandle = (HANDLE)_beginthreadex(NULL, NULL, PCSTProxy, iPCSTProxyParam, NULL, (uint*)&dwThreadId); + // Note : DO NOT use iPCSTProxyParam anymore, since ownership is transferred to the proxy (which frees it too) DbgPrintf("KRNL: Waiting for Xbox proxy thread to start...\n"); while (bWait) { - dwThreadWait = WaitForSingleObject(*ThreadHandle, 300); + dwThreadWait = WaitForSingleObject(hStartedEvent, 300); switch (dwThreadWait) { - // Thread is running - case WAIT_TIMEOUT: - // Thread is complete - case WAIT_OBJECT_0: { - // if either of two above is true, don't need to wait. + case WAIT_TIMEOUT: { // The time-out interval elapsed, and the object's state is nonsignaled. + DbgPrintf("KRNL: Timeout while waiting for Xbox proxy thread to start...\n"); bWait = false; break; } - // A problem has occurred, what should we do? - case WAIT_FAILED: { - break; - } - // Unknown wait - default: + case WAIT_OBJECT_0: { // The state of the specified object is signaled. + DbgPrintf("KRNL: Xbox proxy thread is started.\n"); bWait = false; break; + } + default: { + if (dwThreadWait == WAIT_FAILED) // The function has failed + bWait = false; + + std::string ErrorStr = CxbxGetLastErrorString("KRNL: While waiting for Xbox proxy thread to start"); + DbgPrintf("%s\n", ErrorStr.c_str()); + break; + } } } + // Release the event + CloseHandle(hStartedEvent); + hStartedEvent = NULL; + // Log ThreadID identical to how GetCurrentThreadID() is rendered : DbgPrintf("KRNL: Created Xbox proxy thread. Handle : 0x%X, ThreadId : [0x%.4X]\n", *ThreadHandle, dwThreadId); From eae87ba5f7f3eee11e9ec75f99b629ba40aaba72 Mon Sep 17 00:00:00 2001 From: patrickvl Date: Sat, 13 Jan 2018 17:07:33 +0100 Subject: [PATCH 04/21] Xbe flags are now dumped correctly (only the first bitfield was shown, now the entire value) --- src/Common/Xbe.cpp | 12 ++++++------ src/Common/Xbe.h | 30 +++++++++++++++++++++--------- 2 files changed, 27 insertions(+), 15 deletions(-) diff --git a/src/Common/Xbe.cpp b/src/Common/Xbe.cpp index bce7acffd..dee7364c1 100644 --- a/src/Common/Xbe.cpp +++ b/src/Common/Xbe.cpp @@ -585,7 +585,7 @@ void Xbe::DumpInformation(FILE *x_file) // print init flags { - fprintf(x_file, "Init Flags : 0x%.08X ", m_Header.dwInitFlags.bMountUtilityDrive); + fprintf(x_file, "Init Flags : 0x%.08X ", m_Header.dwInitFlags_value); if(m_Header.dwInitFlags.bMountUtilityDrive) fprintf(x_file, "[Mount Utility Drive] "); @@ -703,7 +703,7 @@ void Xbe::DumpInformation(FILE *x_file) // print flags { - fprintf(x_file, "Flags : 0x%.08X ", m_SectionHeader[v].dwFlags.bWritable); + fprintf(x_file, "Flags : 0x%.08X ", m_SectionHeader[v].dwFlags_value); if(m_SectionHeader[v].dwFlags.bWritable) fprintf(x_file, "(Writable) "); @@ -773,16 +773,16 @@ void Xbe::DumpInformation(FILE *x_file) // print flags { - fprintf(x_file, "Flags : "); + fprintf(x_file, "Flags : 0x%.04X ", m_LibraryVersion[v].wFlags_value); - fprintf(x_file, "QFEVersion : 0x%.04X, ", m_LibraryVersion[v].dwFlags.QFEVersion); + fprintf(x_file, "QFEVersion : 0x%.04X, ", m_LibraryVersion[v].wFlags.QFEVersion); - if(m_LibraryVersion[v].dwFlags.bDebugBuild) + if(m_LibraryVersion[v].wFlags.bDebugBuild) fprintf(x_file, "Debug, "); else fprintf(x_file, "Retail, "); - switch(m_LibraryVersion[v].dwFlags.Approved) + switch(m_LibraryVersion[v].wFlags.Approved) { case 0: fprintf(x_file, "Unapproved"); diff --git a/src/Common/Xbe.h b/src/Common/Xbe.h index 6a5dbc577..344ee4a49 100644 --- a/src/Common/Xbe.h +++ b/src/Common/Xbe.h @@ -92,7 +92,7 @@ class Xbe : public Error uint32 dwSections; // 0x011C - number of sections uint32 dwSectionHeadersAddr; // 0x0120 - section headers address - struct InitFlags // 0x0124 - initialization flags + typedef struct { uint32 bMountUtilityDrive : 1; // mount utility drive flag uint32 bFormatUtilityDrive : 1; // format utility drive flag @@ -102,8 +102,12 @@ class Xbe : public Error uint32 Unused_b1 : 8; // unused (or unknown) uint32 Unused_b2 : 8; // unused (or unknown) uint32 Unused_b3 : 8; // unused (or unknown) - } - dwInitFlags; + } InitFlags; + + union { // 0x0124 - initialization flags + InitFlags dwInitFlags; + uint32 dwInitFlags_value; + }; uint32 dwEntryAddr; // 0x0128 - entry point address uint32 dwTLSAddr; // 0x012C - thread local storage directory address @@ -162,7 +166,7 @@ class Xbe : public Error #include "AlignPrefix1.h" struct SectionHeader { - struct _Flags + typedef struct { uint32 bWritable : 1; // writable flag uint32 bPreload : 1; // preload flag @@ -175,8 +179,12 @@ class Xbe : public Error uint32 Unused_b1 : 8; // unused (or unknown) uint32 Unused_b2 : 8; // unused (or unknown) uint32 Unused_b3 : 8; // unused (or unknown) - } - dwFlags; + } _Flags; + + union { + _Flags dwFlags; + uint32 dwFlags_value; + }; uint32 dwVirtualAddr; // virtual address uint32 dwVirtualSize; // virtual size @@ -200,13 +208,17 @@ class Xbe : public Error uint16 wMinorVersion; // minor version uint16 wBuildVersion; // build version - struct Flags + typedef struct { uint16 QFEVersion : 13; // QFE Version uint16 Approved : 2; // Approved? (0:no, 1:possibly, 2:yes) uint16 bDebugBuild : 1; // Is this a debug build? - } - dwFlags; + } Flags; + + union { + Flags wFlags; + uint16 wFlags_value; + }; } #include "AlignPosfix1.h" *m_LibraryVersion, *m_KernelLibraryVersion, *m_XAPILibraryVersion; From a81a8819497b940168a62a3ef67b4393b8fcf0f6 Mon Sep 17 00:00:00 2001 From: Luke Usher Date: Sat, 13 Jan 2018 23:05:11 +0000 Subject: [PATCH 05/21] Fix an issue where some software was using the wrong memory address for surface/texture resources --- src/CxbxKrnl/EmuD3D8.cpp | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/src/CxbxKrnl/EmuD3D8.cpp b/src/CxbxKrnl/EmuD3D8.cpp index 431a2d936..efa40f640 100644 --- a/src/CxbxKrnl/EmuD3D8.cpp +++ b/src/CxbxKrnl/EmuD3D8.cpp @@ -5311,7 +5311,9 @@ VOID WINAPI XTL::EMUPATCH(D3DResource_Register) DbgPrintf("EmuIDirect3DResource8_Register :-> Texture...\n"); } - X_D3DPixelContainer *pPixelContainer = (X_D3DPixelContainer*)pResource; + pBase = (void*)((xbaddr)pBase | MM_SYSTEM_PHYSICAL_MAP); + + X_D3DPixelContainer *pPixelContainer = (X_D3DPixelContainer*)pResource; X_D3DFORMAT X_Format = GetXboxPixelContainerFormat(pPixelContainer); D3DFORMAT PCFormat = EmuXB2PC_D3DFormat(X_Format); From a46992394ac4c66df2bcd1115cf1f6080d61fda0 Mon Sep 17 00:00:00 2001 From: Luke Usher Date: Sun, 14 Jan 2018 10:52:08 +0000 Subject: [PATCH 06/21] Wait betweeen CreateThread and WaitForSingleObject --- src/CxbxKrnl/EmuKrnlPs.cpp | 16 ++++++++++++---- 1 file changed, 12 insertions(+), 4 deletions(-) diff --git a/src/CxbxKrnl/EmuKrnlPs.cpp b/src/CxbxKrnl/EmuKrnlPs.cpp index d24786b6a..3a8f77f72 100644 --- a/src/CxbxKrnl/EmuKrnlPs.cpp +++ b/src/CxbxKrnl/EmuKrnlPs.cpp @@ -132,6 +132,7 @@ static unsigned int WINAPI PCSTProxy StartSuspended, hStartedEvent); + // Do minimal thread initialization InitXboxThread(g_CPUXbox); @@ -299,6 +300,10 @@ XBSYSAPI EXPORTNUM(255) xboxkrnl::NTSTATUS NTAPI xboxkrnl::PsCreateSystemThreadE DWORD dwThreadId = 0, dwThreadWait; bool bWait = true; HANDLE hStartedEvent = CreateEvent(NULL, FALSE, FALSE, TEXT("PCSTProxyEvent")); + if (hStartedEvent == NULL) { + std::string errorMessage = CxbxGetLastErrorString("PsCreateSystemThreadEx could not create PCSTProxyEvent"); + CxbxKrnlCleanup(errorMessage.c_str()); + } // PCSTProxy is responsible for cleaning up this pointer ::PCSTProxyParam *iPCSTProxyParam = new ::PCSTProxyParam(); @@ -312,13 +317,16 @@ XBSYSAPI EXPORTNUM(255) xboxkrnl::NTSTATUS NTAPI xboxkrnl::PsCreateSystemThreadE *ThreadHandle = (HANDLE)_beginthreadex(NULL, NULL, PCSTProxy, iPCSTProxyParam, NULL, (uint*)&dwThreadId); // Note : DO NOT use iPCSTProxyParam anymore, since ownership is transferred to the proxy (which frees it too) - DbgPrintf("KRNL: Waiting for Xbox proxy thread to start...\n"); + // Give the thread chance to start + Sleep(100); + + EmuWarning("KRNL: Waiting for Xbox proxy thread to start...\n"); while (bWait) { dwThreadWait = WaitForSingleObject(hStartedEvent, 300); switch (dwThreadWait) { case WAIT_TIMEOUT: { // The time-out interval elapsed, and the object's state is nonsignaled. - DbgPrintf("KRNL: Timeout while waiting for Xbox proxy thread to start...\n"); + EmuWarning("KRNL: Timeout while waiting for Xbox proxy thread to start...\n"); bWait = false; break; } @@ -332,7 +340,7 @@ XBSYSAPI EXPORTNUM(255) xboxkrnl::NTSTATUS NTAPI xboxkrnl::PsCreateSystemThreadE bWait = false; std::string ErrorStr = CxbxGetLastErrorString("KRNL: While waiting for Xbox proxy thread to start"); - DbgPrintf("%s\n", ErrorStr.c_str()); + EmuWarning("%s\n", ErrorStr.c_str()); break; } } @@ -343,7 +351,7 @@ XBSYSAPI EXPORTNUM(255) xboxkrnl::NTSTATUS NTAPI xboxkrnl::PsCreateSystemThreadE hStartedEvent = NULL; // Log ThreadID identical to how GetCurrentThreadID() is rendered : - DbgPrintf("KRNL: Created Xbox proxy thread. Handle : 0x%X, ThreadId : [0x%.4X]\n", *ThreadHandle, dwThreadId); + EmuWarning("KRNL: Created Xbox proxy thread. Handle : 0x%X, ThreadId : [0x%.4X]\n", *ThreadHandle, dwThreadId); // we must duplicate this handle in order to retain Suspend/Resume thread rights from a remote thread { From b076e6caabe7a9094ebdcfd489a517fd78f7f7c0 Mon Sep 17 00:00:00 2001 From: Luke Usher Date: Fri, 12 Jan 2018 16:08:22 +0000 Subject: [PATCH 07/21] Move CxbxRestorePersistentMemoryRegions to after CxbxRestoreContigousMemory --- src/CxbxKrnl/CxbxKrnl.cpp | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/src/CxbxKrnl/CxbxKrnl.cpp b/src/CxbxKrnl/CxbxKrnl.cpp index 3126b7e4c..05af8741c 100644 --- a/src/CxbxKrnl/CxbxKrnl.cpp +++ b/src/CxbxKrnl/CxbxKrnl.cpp @@ -650,6 +650,7 @@ void CxbxKrnlMain(int argc, char* argv[]) } CxbxRestoreContiguousMemory(szFilePath_memory_bin); + CxbxRestorePersistentMemoryRegions(); EEPROM = CxbxRestoreEEPROM(szFilePath_EEPROM_bin); if (EEPROM == nullptr) @@ -686,8 +687,6 @@ void CxbxKrnlMain(int argc, char* argv[]) g_VMManager.InitializeChihiroDebug(); } - CxbxRestorePersistentMemoryRegions(); - // Copy over loaded Xbe Headers to specified base address memcpy((void*)CxbxKrnl_Xbe->m_Header.dwBaseAddr, &CxbxKrnl_Xbe->m_Header, sizeof(Xbe::Header)); memcpy((void*)(CxbxKrnl_Xbe->m_Header.dwBaseAddr + sizeof(Xbe::Header)), CxbxKrnl_Xbe->m_HeaderEx, CxbxKrnl_Xbe->m_ExSize); From 2723bef3d976c4667ad20dccf2a4c6a5e6a16b18 Mon Sep 17 00:00:00 2001 From: PatrickvL Date: Mon, 15 Jan 2018 09:49:42 +0100 Subject: [PATCH 08/21] CxbxRestoreLaunchDataPage : Fixed a pointer-arithmetic bug, spotted by hotzenplotz3000 --- src/CxbxKrnl/CxbxKrnl.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/CxbxKrnl/CxbxKrnl.cpp b/src/CxbxKrnl/CxbxKrnl.cpp index 05af8741c..99d78ca7f 100644 --- a/src/CxbxKrnl/CxbxKrnl.cpp +++ b/src/CxbxKrnl/CxbxKrnl.cpp @@ -1111,7 +1111,7 @@ void CxbxRestoreLaunchDataPage() if (LaunchDataPAddr) { - xboxkrnl::LaunchDataPage = (xboxkrnl::LAUNCH_DATA_PAGE*)CONTIGUOUS_MEMORY_BASE + LaunchDataPAddr; + xboxkrnl::LaunchDataPage = (xboxkrnl::LAUNCH_DATA_PAGE*)(CONTIGUOUS_MEMORY_BASE + LaunchDataPAddr); // Mark the launch page as allocated to prevent other allocations from overwriting it xboxkrnl::MmAllocateContiguousMemoryEx(PAGE_SIZE, LaunchDataPAddr, LaunchDataPAddr + PAGE_SIZE - 1, PAGE_SIZE, PAGE_READWRITE); LaunchDataPAddr = NULL; From 8f22515b7da24bc01f68e949d4b122d2b9e6ad56 Mon Sep 17 00:00:00 2001 From: patrickvl Date: Sun, 14 Jan 2018 18:00:25 +0100 Subject: [PATCH 09/21] CxbxKrnlRegisterThread refactoring; All callers first called DuplicateHandle. Now this is part of CxbxKrnlRegisterThread itself. Also, a possible failure of DuplicateHandle is logged. --- src/CxbxKrnl/CxbxKrnl.cpp | 21 ++++++++++++++------- src/CxbxKrnl/EmuD3D8.cpp | 9 +-------- src/CxbxKrnl/EmuKrnlPs.cpp | 9 +-------- 3 files changed, 16 insertions(+), 23 deletions(-) diff --git a/src/CxbxKrnl/CxbxKrnl.cpp b/src/CxbxKrnl/CxbxKrnl.cpp index 99d78ca7f..422b4107a 100644 --- a/src/CxbxKrnl/CxbxKrnl.cpp +++ b/src/CxbxKrnl/CxbxKrnl.cpp @@ -983,13 +983,7 @@ __declspec(noreturn) void CxbxKrnlInit } } - // duplicate handle in order to retain Suspend/Resume thread rights from a remote thread - { - HANDLE hDupHandle = NULL; - - DuplicateHandle(g_CurrentProcessHandle, GetCurrentThread(), g_CurrentProcessHandle, &hDupHandle, 0, FALSE, DUPLICATE_SAME_ACCESS); - CxbxKrnlRegisterThread(hDupHandle); - } + CxbxKrnlRegisterThread(GetCurrentThread()); // Clear critical section list //extern void InitializeSectionStructures(void); @@ -1168,6 +1162,19 @@ __declspec(noreturn) void CxbxKrnlCleanup(const char *szErrorMessage, ...) void CxbxKrnlRegisterThread(HANDLE hThread) { + // we must duplicate this handle in order to retain Suspend/Resume thread rights from a remote thread + { + HANDLE hDupHandle = NULL; + + if (DuplicateHandle(g_CurrentProcessHandle, hThread, g_CurrentProcessHandle, &hDupHandle, 0, FALSE, DUPLICATE_SAME_ACCESS)) { + hThread = hDupHandle; // Thread handle was duplicated, continue registration with the duplicate + } + else { + auto message = CxbxGetLastErrorString("DuplicateHandle"); + EmuWarning(message.c_str()); + } + } + int v=0; for(v=0;v Date: Mon, 15 Jan 2018 13:05:55 +0000 Subject: [PATCH 10/21] Fix an issue where D3DResource_Register returned a host pointer to Xbox code --- src/CxbxKrnl/EmuD3D8.cpp | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/CxbxKrnl/EmuD3D8.cpp b/src/CxbxKrnl/EmuD3D8.cpp index d4fc4f955..393e766f8 100644 --- a/src/CxbxKrnl/EmuD3D8.cpp +++ b/src/CxbxKrnl/EmuD3D8.cpp @@ -5218,7 +5218,7 @@ VOID WINAPI XTL::EMUPATCH(D3DResource_Register) { // TODO: once this is known to be working, remove the warning EmuWarning("Vertex buffer allocation size unknown"); - dwSize = 0x2000; // temporarily assign a small buffer, which will be increased later + dwSize = PAGE_SIZE; // temporarily assign a small buffer, which will be increased later /*hRet = E_FAIL; goto fail;*/ } @@ -5261,7 +5261,7 @@ VOID WINAPI XTL::EMUPATCH(D3DResource_Register) memcpy(pNativeData, (void*)pBase, dwSize); pNewHostVertexBuffer->Unlock(); - pResource->Data = (DWORD)pNativeData; // For now, give the native buffer memory to Xbox. TODO : g_MemoryManager.AllocateContiguous + pResource->Data = (DWORD)pBase; // Set pResource->Data to point to Xbox Vertex buffer memory } DbgPrintf("EmuIDirect3DResource8_Register : Successfully Created VertexBuffer (0x%.08X)\n", pNewHostVertexBuffer); From 8940e670d954b217f34ecf83421df109cde3ff79 Mon Sep 17 00:00:00 2001 From: Luke Usher Date: Mon, 15 Jan 2018 13:29:21 +0000 Subject: [PATCH 11/21] Fix an issue where CxbxKrnl_DebugFileName could become a pointer to invalid memory. This happened if the original std::string DebugFileName went out of scope. The solution is to store the actual data as CxbxKrnl_DebugFilename rather than a pointer. --- src/CxbxKrnl/CxbxKrnl.cpp | 4 ++-- src/CxbxKrnl/CxbxKrnl.h | 2 +- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/src/CxbxKrnl/CxbxKrnl.cpp b/src/CxbxKrnl/CxbxKrnl.cpp index 422b4107a..741390536 100644 --- a/src/CxbxKrnl/CxbxKrnl.cpp +++ b/src/CxbxKrnl/CxbxKrnl.cpp @@ -83,7 +83,7 @@ Xbe::Header *CxbxKrnl_XbeHeader = NULL; HWND CxbxKrnl_hEmuParent = NULL; DebugMode CxbxKrnl_DebugMode = DebugMode::DM_NONE; -char* CxbxKrnl_DebugFileName = NULL; +std::string CxbxKrnl_DebugFileName = ""; Xbe::Certificate *g_pCertificate = NULL; /*! thread handles */ @@ -533,7 +533,7 @@ void CxbxKrnlMain(int argc, char* argv[]) } // Get KernelDebugFileName : - std::string DebugFileName; + std::string DebugFileName = ""; if (argc > 4) { DebugFileName = argv[5]; } diff --git a/src/CxbxKrnl/CxbxKrnl.h b/src/CxbxKrnl/CxbxKrnl.h index 359125796..7fd8bf3b5 100644 --- a/src/CxbxKrnl/CxbxKrnl.h +++ b/src/CxbxKrnl/CxbxKrnl.h @@ -221,7 +221,7 @@ extern Xbe *CxbxKrnl_Xbe; /*! parent window handle */ extern HWND CxbxKrnl_hEmuParent; extern DebugMode CxbxKrnl_DebugMode; -extern char* CxbxKrnl_DebugFileName; +extern std::string CxbxKrnl_DebugFileName; /*! file paths */ extern char szFilePath_CxbxReloaded_Exe[MAX_PATH]; From c59ce5ccee63f9e11148710855c904061796dba1 Mon Sep 17 00:00:00 2001 From: Luke Usher Date: Mon, 15 Jan 2018 13:30:05 +0000 Subject: [PATCH 12/21] Fix an issue where Xboxdash could not properly launch Xonlinedash. --- src/CxbxKrnl/EmuKrnlHal.cpp | 7 ++++++- 1 file changed, 6 insertions(+), 1 deletion(-) diff --git a/src/CxbxKrnl/EmuKrnlHal.cpp b/src/CxbxKrnl/EmuKrnlHal.cpp index 7066e23ae..b2468c316 100644 --- a/src/CxbxKrnl/EmuKrnlHal.cpp +++ b/src/CxbxKrnl/EmuKrnlHal.cpp @@ -57,6 +57,7 @@ namespace xboxkrnl #include "EmuShared.h" #include "EmuFile.h" // For FindNtSymbolicLinkObjectByDriveLetter +#include // for std::replace #include #include @@ -472,7 +473,11 @@ XBSYSAPI EXPORTNUM(49) xboxkrnl::VOID DECLSPEC_NORETURN NTAPI xboxkrnl::HalRetur char szArgsBuffer[4096]; - snprintf(szArgsBuffer, 4096, "/load \"%s\" %u %d \"%s\"", XbePath.c_str(), CxbxKrnl_hEmuParent, CxbxKrnl_DebugMode, CxbxKrnl_DebugFileName); + // Some titles (Xbox Dashboard) use ";" as a final path seperator + // This allows the Xbox Live option on the dashboard to properly launch XOnlinedash.xbe + std::replace(XbePath.begin(), XbePath.end(), ';', '\\'); + + snprintf(szArgsBuffer, 4096, "/load \"%s\" %u %d \"%s\"", XbePath.c_str(), CxbxKrnl_hEmuParent, CxbxKrnl_DebugMode, CxbxKrnl_DebugFileName.c_str()); if ((int)ShellExecute(NULL, "open", szFilePath_CxbxReloaded_Exe, szArgsBuffer, szWorkingDirectoy, SW_SHOWDEFAULT) <= 32) CxbxKrnlCleanup("Could not launch %s", XbePath.c_str()); } From e141cdb78ed3871cc1286b3cf316f3d9856b3bac Mon Sep 17 00:00:00 2001 From: PatrickvL Date: Thu, 18 Jan 2018 17:55:55 +0100 Subject: [PATCH 13/21] Introduced ConvertD3DTextureToARGBBuffer (already used by ConvertD3DTextureToARGB for showing logo's) in preparation on removing the OLD_COLOR_CONVERSION define --- src/CxbxKrnl/EmuD3D8.cpp | 166 +++++++++++++++++++++---------- src/CxbxKrnl/EmuD3D8.h | 3 +- src/CxbxKrnl/EmuD3D8/Convert.cpp | 73 ++++++++------ src/CxbxKrnl/EmuD3D8/Convert.h | 2 + 4 files changed, 157 insertions(+), 87 deletions(-) diff --git a/src/CxbxKrnl/EmuD3D8.cpp b/src/CxbxKrnl/EmuD3D8.cpp index d4fc4f955..653f0443d 100644 --- a/src/CxbxKrnl/EmuD3D8.cpp +++ b/src/CxbxKrnl/EmuD3D8.cpp @@ -984,12 +984,66 @@ VOID CxbxGetPixelContainerMeasures } } +bool ConvertD3DTextureToARGBBuffer( + XTL::X_D3DFORMAT X_Format, + uint8 *pSrc, + int SrcWidth, int SrcHeight, + uint SrcPitch, + uint8 *pDest, int DestPitch, + int TextureStage = 0 +) +{ + const XTL::FormatToARGBRow ConvertRowToARGB = EmuXBFormatComponentConverter(X_Format); + if (ConvertRowToARGB == nullptr) + return false; // Unhandled conversion + + uint8 *unswizleBuffer = nullptr; + if (XTL::EmuXBFormatIsSwizzled(X_Format)) { + unswizleBuffer = (uint8*)malloc(SrcPitch * SrcHeight); // TODO : Reuse buffer when performance is important + // First we need to unswizzle the texture data + XTL::EmuUnswizzleRect( + pSrc, SrcWidth, SrcHeight, 1, unswizleBuffer, + SrcPitch, {}, {}, EmuXBFormatBytesPerPixel(X_Format) + ); + // Convert colors from the unswizzled buffer + pSrc = unswizleBuffer; + } + + int AdditionalArgument; + if (X_Format == XTL::X_D3DFMT_P8) + AdditionalArgument = (int)g_pCurrentPalette[TextureStage]; + else + AdditionalArgument = DestPitch; + + DWORD SrcRowOff = 0; + uint8 *pDestRow = pDest; + if (EmuXBFormatIsCompressed(X_Format)) { + // All compressed formats (DXT1, DXT3 and DXT5) encode blocks of 4 pixels on 4 lines + SrcHeight = (SrcHeight + 3) / 4; + DestPitch *= 4; + } + + for (int y = 0; y < SrcHeight; y++) { + *(int*)pDestRow = AdditionalArgument; // Dirty hack, to avoid an extra parameter to all conversion callbacks + ConvertRowToARGB(pSrc + SrcRowOff, pDestRow, SrcWidth); + SrcRowOff += SrcPitch; + pDestRow += DestPitch; + } + + if (unswizleBuffer) + free(unswizleBuffer); + + return true; +} + uint8 *XTL::ConvertD3DTextureToARGB( XTL::X_D3DPixelContainer *pXboxPixelContainer, uint8 *pSrc, - int *pWidth, int *pHeight + int *pWidth, int *pHeight, + int TextureStage // default = 0 ) { + // Avoid allocating pDest when ConvertD3DTextureToARGBBuffer will fail anyway XTL::X_D3DFORMAT X_Format = GetXboxPixelContainerFormat(pXboxPixelContainer); const XTL::FormatToARGBRow ConvertRowToARGB = EmuXBFormatComponentConverter(X_Format); if (ConvertRowToARGB == nullptr) @@ -1005,43 +1059,18 @@ uint8 *XTL::ConvertD3DTextureToARGB( &SrcSize ); + // Now we know ConvertD3DTextureToARGBBuffer will do it's thing, allocate the resulting buffer int DestPitch = *pWidth * sizeof(DWORD); uint8 *pDest = (uint8 *)malloc(DestPitch * *pHeight); - uint8 *unswizleBuffer = nullptr; - if (XTL::EmuXBFormatIsSwizzled(X_Format)) { - unswizleBuffer = (uint8*)malloc(SrcPitch * *pHeight); // TODO : Reuse buffer when performance is important - // First we need to unswizzle the texture data - XTL::EmuUnswizzleRect( - pSrc, *pWidth, *pHeight, 1, unswizleBuffer, - SrcPitch, {}, {}, EmuXBFormatBytesPerPixel(X_Format) - ); - // Convert colors from the unswizzled buffer - pSrc = unswizleBuffer; - } - - DWORD SrcRowOff = 0; - uint8 *pDestRow = pDest; - if (EmuXBFormatIsCompressed(X_Format)) { - // All compressed formats (DXT1, DXT3 and DXT5) encode blocks of 4 pixels on 4 lines - for (int y = 0; y < *pHeight; y+=4) { - *(int*)pDestRow = DestPitch; // Dirty hack, to avoid an extra parameter to all conversion callbacks - ConvertRowToARGB(pSrc + SrcRowOff, pDestRow, *pWidth); - SrcRowOff += SrcPitch; - pDestRow += DestPitch * 4; - } - } - else { - while (SrcRowOff < SrcSize) { - ConvertRowToARGB(pSrc + SrcRowOff, pDestRow, *pWidth); - SrcRowOff += SrcPitch; - pDestRow += DestPitch; - } - } - - if (unswizleBuffer) - free(unswizleBuffer); + // And convert the source towards that buffer + /*ignore result*/ConvertD3DTextureToARGBBuffer( + X_Format, + pSrc, *pWidth, *pHeight, SrcPitch, + pDest, DestPitch, + TextureStage); + // NOTE : Caller must take ownership! return pDest; } @@ -5332,9 +5361,20 @@ VOID WINAPI XTL::EMUPATCH(D3DResource_Register) // Let's try using some 16-bit format instead... if(X_Format == X_D3DFMT_X1R5G5B5 ) { +#ifdef OLD_COLOR_CONVERSION // Current approach EmuWarning( "X_D3DFMT_X1R5G5B5 -> D3DFMT_R5GB5" ); X_Format = X_D3DFMT_R5G6B5; PCFormat = D3DFMT_R5G6B5; +#else // Later, convert to ARGB : + CacheFormat = PCFormat; // Save this for later + PCFormat = D3DFMT_A8R8G8B8; // ARGB + } + + // Detect formats that must be converted to ARGB + if (EmuXBFormatRequiresConversionToARGB(X_Format)) { + CacheFormat = PCFormat; // Save this for later + PCFormat = D3DFMT_A8R8G8B8; // ARGB +#endif // !OLD_COLOR_CONVERSION } DWORD dwWidth, dwHeight, dwBPP, dwDepth = 1, dwPitch = 0, dwMipMapLevels = 1; @@ -5489,6 +5529,7 @@ VOID WINAPI XTL::EMUPATCH(D3DResource_Register) dwMipMapLevels = 3; } +#ifdef OLD_COLOR_CONVERSION // Current palette approach - Later, use ______P8ToARGBRow_C() // HACK HACK HACK HACK HACK HACK HACK HACK HACK HACK // Since most modern graphics cards does not support // palette based textures we need to expand it to @@ -5503,6 +5544,7 @@ VOID WINAPI XTL::EMUPATCH(D3DResource_Register) CacheFormat = PCFormat; // Save this for later PCFormat = D3DFMT_A8R8G8B8; // ARGB } +#endif // OLD_COLOR_CONVERSION if(bCubemap) { @@ -5628,6 +5670,39 @@ VOID WINAPI XTL::EMUPATCH(D3DResource_Register) { // TODO: Fix or handle this situation..? } +#ifndef OLD_COLOR_CONVERSION // Later, use ConvertD3DTextureToARGBBuffer + else if (CacheFormat != 0) // Do we need to convert to ARGB? + { + EmuWarning("Unsupported texture format, expanding to D3DFMT_A8R8G8B8"); + + BYTE *pPixelData = (BYTE*)LockedRect.pBits; + DWORD dwDataSize = dwMipWidth*dwMipHeight; + DWORD* pExpandedTexture = (DWORD*)malloc(dwDataSize * sizeof(DWORD)); + + uint8 *pSrc = pPixelData; + uint8 *pDest = (uint8 *)pExpandedTexture; + + DWORD dwSrcPitch = dwMipWidth * dwBPP;//sizeof(DWORD); + DWORD dwDestPitch = dwMipWidth * sizeof(DWORD); + DWORD dwMipSizeInBytes = dwDataSize; + + // Convert a row at a time, using a libyuv-like callback approach : + if (!ConvertD3DTextureToARGBBuffer( + X_Format, + pSrc, dwMipWidth, dwMipHeight, dwSrcPitch, + pDest, dwDestPitch, + TextureStage)) { + CxbxKrnlCleanup("Unhandled conversion!"); + } + + //__asm int 3; + // Copy the expanded texture back to the buffer + memcpy(pPixelData, pExpandedTexture, dwDataSize * sizeof(DWORD)); + + // Flush unused data buffers + free(pExpandedTexture); + } +#endif // !OLD_COLOR_CONVERSION else { if (bSwizzled) @@ -5685,6 +5760,7 @@ VOID WINAPI XTL::EMUPATCH(D3DResource_Register) } } +#ifdef OLD_COLOR_CONVERSION // Currently, convert here. Later, use ConvertD3DTextureToARGBBuffer above if (CacheFormat != 0) // Do we need to convert to ARGB? { EmuWarning("Unsupported texture format, expanding to D3DFMT_A8R8G8B8"); @@ -5725,7 +5801,6 @@ VOID WINAPI XTL::EMUPATCH(D3DResource_Register) } else { -#ifdef OLD_COLOR_CONVERSION const ComponentEncodingInfo *encoding = EmuXBFormatComponentEncodingInfo(X_Format); for (unsigned int y = 0; y < dwDataSize; y++) @@ -5752,25 +5827,6 @@ VOID WINAPI XTL::EMUPATCH(D3DResource_Register) w += dwMipWidth * (sizeof(DWORD) - dwBPP); } } -#else // !OLD_COLOR_CONVERSION - // Convert a row at a time, using a libyuv-like callback approach : - const FormatToARGBRow ConvertRowToARGB = EmuXBFormatComponentConverter(X_Format); - if (ConvertRowToARGB == nullptr) - CxbxKrnlCleanup("Unhandled conversion!"); - - uint8 *pSrc = pPixelData; - uint8 *pDest = (uint8 *)pExpandedTexture; - DWORD dwSrcPitch = dwMipWidth * sizeof(DWORD); - DWORD dwDestPitch = dwMipWidth * sizeof(DWORD); - DWORD dwMipSizeInBytes = dwDataSize; - - DWORD SrcRowOff = 0; - uint8 *pDestRow = (uint8 *)pDest; - while (SrcRowOff < dwMipSizeInBytes) { - ConvertRowToARGB(((uint8 *)pSrc) + SrcRowOff, pDestRow, dwMipWidth); - SrcRowOff += dwSrcPitch; - pDestRow += dwDestPitch; - } #endif // !OLD_COLOR_CONVERSION } @@ -7939,7 +7995,7 @@ VOID WINAPI XTL::EMUPATCH(D3DDevice_SetStreamSource) #ifdef _DEBUG_TRACK_VB if(pStreamData != NULL) { - g_bVBSkipStream = g_VBTrackDisable.exists(GetHostVertexBuffer(pStreamData)); + g_bVBSkipStream = g_VBTrackDisable.exists(pHostVertexBuffer); } #endif diff --git a/src/CxbxKrnl/EmuD3D8.h b/src/CxbxKrnl/EmuD3D8.h index 5c1b73e67..df1802283 100644 --- a/src/CxbxKrnl/EmuD3D8.h +++ b/src/CxbxKrnl/EmuD3D8.h @@ -60,7 +60,8 @@ extern VOID CxbxSetPixelContainerHeader extern uint8 *ConvertD3DTextureToARGB( XTL::X_D3DPixelContainer *pXboxPixelContainer, uint8 *pSrc, - int *pWidth, int *pHeight + int *pWidth, int *pHeight, + int TextureStage = 0 ); // initialize direct3d diff --git a/src/CxbxKrnl/EmuD3D8/Convert.cpp b/src/CxbxKrnl/EmuD3D8/Convert.cpp index 9829e41f0..7e5664c50 100644 --- a/src/CxbxKrnl/EmuD3D8/Convert.cpp +++ b/src/CxbxKrnl/EmuD3D8/Convert.cpp @@ -51,15 +51,15 @@ enum _ComponentEncoding { NoCmpnts = 0, // Format doesn't contain any component (ARGB/QWVU) A1R5G5B5, - X1R5G5B5, + X1R5G5B5, // NOTE : A=255 A4R4G4B4, __R5G6B5, // NOTE : A=255 A8R8G8B8, - X8R8G8B8, + X8R8G8B8, // NOTE : A=255 ____R8B8, // NOTE : A takes R, G takes B ____G8B8, // NOTE : A takes G, R takes B - ______A8, - __R6G5B5, + ______A8, // TEST : R=G=B= 255 + __R6G5B5, // NOTE : A=255 R5G5B5A1, R4G4B4A4, A8B8G8R8, @@ -754,8 +754,8 @@ enum _FormatStorage { Cmprsd // Compressed }; -enum _FormatSpecial { - None = 0, +enum _FormatUsage { + Texture = 0, RenderTarget, DepthBuffer }; @@ -765,7 +765,7 @@ typedef struct _FormatInfo { _FormatStorage stored; _ComponentEncoding components; XTL::D3DFORMAT pc; - _FormatSpecial special; + _FormatUsage usage; char *warning; } FormatInfo; @@ -781,7 +781,7 @@ static const FormatInfo FormatInfos[] = { // to ARGB is needed (which is implemented in EMUPATCH(D3DResource_Register). /* 0x00 X_D3DFMT_L8 */ { 8, Swzzld, ______L8, XTL::D3DFMT_L8 }, - /* 0x01 X_D3DFMT_AL8 */ { 8, Swzzld, _____AL8, XTL::D3DFMT_L8 , None, "X_D3DFMT_AL8 -> D3DFMT_L8" }, + /* 0x01 X_D3DFMT_AL8 */ { 8, Swzzld, _____AL8, XTL::D3DFMT_L8 , Texture, "X_D3DFMT_AL8 -> D3DFMT_L8" }, /* 0x02 X_D3DFMT_A1R5G5B5 */ { 16, Swzzld, A1R5G5B5, XTL::D3DFMT_A1R5G5B5 }, /* 0x03 X_D3DFMT_X1R5G5B5 */ { 16, Swzzld, X1R5G5B5, XTL::D3DFMT_X1R5G5B5 , RenderTarget }, /* 0x04 X_D3DFMT_A4R4G4B4 */ { 16, Swzzld, A4R4G4B4, XTL::D3DFMT_A4R4G4B4 }, @@ -802,12 +802,12 @@ static const FormatInfo FormatInfos[] = { /* 0x13 X_D3DFMT_LIN_L8 */ { 8, Linear, ______L8, XTL::D3DFMT_L8 , RenderTarget }, /* 0x14 undefined */ {}, /* 0x15 undefined */ {}, - /* 0x16 X_D3DFMT_LIN_R8B8 */ { 16, Linear, ____R8B8, XTL::D3DFMT_R5G6B5 , None, "X_D3DFMT_LIN_R8B8 -> D3DFMT_R5G6B5" }, + /* 0x16 X_D3DFMT_LIN_R8B8 */ { 16, Linear, ____R8B8, XTL::D3DFMT_R5G6B5 , Texture, "X_D3DFMT_LIN_R8B8 -> D3DFMT_R5G6B5" }, /* 0x17 X_D3DFMT_LIN_G8B8 */ { 16, Linear, ____G8B8, XTL::D3DFMT_R5G6B5 , RenderTarget, "X_D3DFMT_LIN_G8B8 -> D3DFMT_R5G6B5" }, // Alias : X_D3DFMT_LIN_V8U8 /* 0x18 undefined */ {}, /* 0x19 X_D3DFMT_A8 */ { 8, Swzzld, ______A8, XTL::D3DFMT_A8 }, /* 0x1A X_D3DFMT_A8L8 */ { 16, Swzzld, ____A8L8, XTL::D3DFMT_A8L8 }, - /* 0x1B X_D3DFMT_LIN_AL8 */ { 8, Linear, _____AL8, XTL::D3DFMT_L8 , None, "X_D3DFMT_LIN_AL8 -> D3DFMT_L8" }, + /* 0x1B X_D3DFMT_LIN_AL8 */ { 8, Linear, _____AL8, XTL::D3DFMT_L8 , Texture, "X_D3DFMT_LIN_AL8 -> D3DFMT_L8" }, /* 0x1C X_D3DFMT_LIN_X1R5G5B5 */ { 16, Linear, X1R5G5B5, XTL::D3DFMT_X1R5G5B5 , RenderTarget }, /* 0x1D X_D3DFMT_LIN_A4R4G4B4 */ { 16, Linear, A4R4G4B4, XTL::D3DFMT_A4R4G4B4 }, /* 0x1E X_D3DFMT_LIN_X8R8G8B8 */ { 32, Linear, X8R8G8B8, XTL::D3DFMT_X8R8G8B8 , RenderTarget }, // Alias : X_D3DFMT_LIN_X8L8V8U8 @@ -821,31 +821,31 @@ static const FormatInfo FormatInfos[] = { /* 0x26 undefined */ {}, /* 0x27 X_D3DFMT_L6V5U5 */ { 16, Swzzld, __R6G5B5, XTL::D3DFMT_L6V5U5 }, // Alias : X_D3DFMT_R6G5B5 // XQEMU NOTE : This might be signed /* 0x28 X_D3DFMT_V8U8 */ { 16, Swzzld, ____G8B8, XTL::D3DFMT_V8U8 }, // Alias : X_D3DFMT_G8B8 // XQEMU NOTE : This might be signed - /* 0x29 X_D3DFMT_R8B8 */ { 16, Swzzld, ____R8B8, XTL::D3DFMT_R5G6B5 , None, "X_D3DFMT_R8B8 -> D3DFMT_R5G6B5" }, // XQEMU NOTE : This might be signed + /* 0x29 X_D3DFMT_R8B8 */ { 16, Swzzld, ____R8B8, XTL::D3DFMT_R5G6B5 , Texture, "X_D3DFMT_R8B8 -> D3DFMT_R5G6B5" }, // XQEMU NOTE : This might be signed /* 0x2A X_D3DFMT_D24S8 */ { 32, Swzzld, NoCmpnts, XTL::D3DFMT_D24S8 , DepthBuffer }, /* 0x2B X_D3DFMT_F24S8 */ { 32, Swzzld, NoCmpnts, XTL::D3DFMT_D24S8 , DepthBuffer, "X_D3DFMT_F24S8 -> D3DFMT_D24S8" }, // HACK : PC doesn't have D3DFMT_F24S8 (Float vs Int) - /* 0x2C X_D3DFMT_D16 */ { 16, Swzzld, NoCmpnts, XTL::D3DFMT_D16 , DepthBuffer }, // Alias : X_D3DFMT_D16_LOCKABLE // TODO : D3DFMT_D16 is always lockable on Xbox; Should PC use D3DFMT_D16_LOCKABLE instead? Needs testcase. - /* 0x2D X_D3DFMT_F16 */ { 16, Swzzld, NoCmpnts, XTL::D3DFMT_D16 , DepthBuffer, "X_D3DFMT_F16 -> D3DFMT_D16" }, // HACK : PC doesn't have D3DFMT_F16 (Float vs Int) + /* 0x2C X_D3DFMT_D16 */ { 16, Swzzld, NoCmpnts, XTL::D3DFMT_D16_LOCKABLE, DepthBuffer }, // Alias : X_D3DFMT_D16_LOCKABLE // Note : D3DFMT_D16 is always lockable on Xbox, D3DFMT_D16 on host is not. + /* 0x2D X_D3DFMT_F16 */ { 16, Swzzld, NoCmpnts, XTL::D3DFMT_D16_LOCKABLE, DepthBuffer, "X_D3DFMT_F16 -> D3DFMT_D16" }, // HACK : PC doesn't have D3DFMT_F16 (Float vs Int) /* 0x2E X_D3DFMT_LIN_D24S8 */ { 32, Linear, NoCmpnts, XTL::D3DFMT_D24S8 , DepthBuffer }, /* 0x2F X_D3DFMT_LIN_F24S8 */ { 32, Linear, NoCmpnts, XTL::D3DFMT_D24S8 , DepthBuffer, "X_D3DFMT_LIN_F24S8 -> D3DFMT_D24S8" }, // HACK : PC doesn't have D3DFMT_F24S8 (Float vs Int) - /* 0x30 X_D3DFMT_LIN_D16 */ { 16, Linear, NoCmpnts, XTL::D3DFMT_D16 , DepthBuffer }, // TODO : D3DFMT_D16 is always lockable on Xbox; Should PC use D3DFMT_D16_LOCKABLE instead? Needs testcase. - /* 0x31 X_D3DFMT_LIN_F16 */ { 16, Linear, NoCmpnts, XTL::D3DFMT_D16 , DepthBuffer, "X_D3DFMT_LIN_F16 -> D3DFMT_D16" }, // HACK : PC doesn't have D3DFMT_F16 (Float vs Int) - /* 0x32 X_D3DFMT_L16 */ { 16, Swzzld, _____L16, XTL::D3DFMT_A8L8 , None, "X_D3DFMT_L16 -> D3DFMT_A8L8" }, + /* 0x30 X_D3DFMT_LIN_D16 */ { 16, Linear, NoCmpnts, XTL::D3DFMT_D16_LOCKABLE, DepthBuffer }, // Note : D3DFMT_D16 is always lockable on Xbox, D3DFMT_D16 on host is not. + /* 0x31 X_D3DFMT_LIN_F16 */ { 16, Linear, NoCmpnts, XTL::D3DFMT_D16_LOCKABLE, DepthBuffer, "X_D3DFMT_LIN_F16 -> D3DFMT_D16" }, // HACK : PC doesn't have D3DFMT_F16 (Float vs Int) + /* 0x32 X_D3DFMT_L16 */ { 16, Swzzld, _____L16, XTL::D3DFMT_A8L8 , Texture, "X_D3DFMT_L16 -> D3DFMT_A8L8" }, /* 0x33 X_D3DFMT_V16U16 */ { 32, Swzzld, NoCmpnts, XTL::D3DFMT_V16U16 }, /* 0x34 undefined */ {}, - /* 0x35 X_D3DFMT_LIN_L16 */ { 16, Linear, _____L16, XTL::D3DFMT_A8L8 , None, "X_D3DFMT_LIN_L16 -> D3DFMT_A8L8" }, + /* 0x35 X_D3DFMT_LIN_L16 */ { 16, Linear, _____L16, XTL::D3DFMT_A8L8 , Texture, "X_D3DFMT_LIN_L16 -> D3DFMT_A8L8" }, /* 0x36 X_D3DFMT_LIN_V16U16 */ { 32, Linear, NoCmpnts, XTL::D3DFMT_V16U16 }, /* 0x37 X_D3DFMT_LIN_L6V5U5 */ { 16, Linear, __R6G5B5, XTL::D3DFMT_L6V5U5 }, // Alias : X_D3DFMT_LIN_R6G5B5 - /* 0x38 X_D3DFMT_R5G5B5A1 */ { 16, Swzzld, R5G5B5A1, XTL::D3DFMT_A1R5G5B5 , None, "X_D3DFMT_R5G5B5A1 -> D3DFMT_A1R5G5B5" }, - /* 0x39 X_D3DFMT_R4G4B4A4 */ { 16, Swzzld, R4G4B4A4, XTL::D3DFMT_A4R4G4B4 , None, "X_D3DFMT_R4G4B4A4 -> D3DFMT_A4R4G4B4" }, + /* 0x38 X_D3DFMT_R5G5B5A1 */ { 16, Swzzld, R5G5B5A1, XTL::D3DFMT_A1R5G5B5 , Texture, "X_D3DFMT_R5G5B5A1 -> D3DFMT_A1R5G5B5" }, + /* 0x39 X_D3DFMT_R4G4B4A4 */ { 16, Swzzld, R4G4B4A4, XTL::D3DFMT_A4R4G4B4 , Texture, "X_D3DFMT_R4G4B4A4 -> D3DFMT_A4R4G4B4" }, /* 0x3A X_D3DFMT_Q8W8V8U8 */ { 32, Swzzld, A8B8G8R8, XTL::D3DFMT_Q8W8V8U8 }, // Alias : X_D3DFMT_A8B8G8R8 // TODO : Needs testcase. - /* 0x3B X_D3DFMT_B8G8R8A8 */ { 32, Swzzld, B8G8R8A8, XTL::D3DFMT_A8R8G8B8 , None, "X_D3DFMT_B8G8R8A8 -> D3DFMT_A8R8G8B8" }, - /* 0x3C X_D3DFMT_R8G8B8A8 */ { 32, Swzzld, R8G8B8A8, XTL::D3DFMT_A8R8G8B8 , None, "X_D3DFMT_R8G8B8A8 -> D3DFMT_A8R8G8B8" }, - /* 0x3D X_D3DFMT_LIN_R5G5B5A1 */ { 16, Linear, R5G5B5A1, XTL::D3DFMT_A1R5G5B5 , None, "X_D3DFMT_LIN_R5G5B5A1 -> D3DFMT_A1R5G5B5" }, - /* 0x3E X_D3DFMT_LIN_R4G4B4A4 */ { 16, Linear, R4G4B4A4, XTL::D3DFMT_A4R4G4B4 , None, "X_D3DFMT_LIN_R4G4B4A4 -> D3DFMT_A4R4G4B4" }, - /* 0x3F X_D3DFMT_LIN_A8B8G8R8 */ { 32, Linear, A8B8G8R8, XTL::D3DFMT_A8R8G8B8 , None, "X_D3DFMT_LIN_A8B8G8R8 -> D3DFMT_A8R8G8B8" }, - /* 0x40 X_D3DFMT_LIN_B8G8R8A8 */ { 32, Linear, B8G8R8A8, XTL::D3DFMT_A8R8G8B8 , None, "X_D3DFMT_LIN_B8G8R8A8 -> D3DFMT_A8R8G8B8" }, - /* 0x41 X_D3DFMT_LIN_R8G8B8A8 */ { 32, Linear, R8G8B8A8, XTL::D3DFMT_A8R8G8B8 , None, "X_D3DFMT_LIN_R8G8B8A8 -> D3DFMT_A8R8G8B8" }, + /* 0x3B X_D3DFMT_B8G8R8A8 */ { 32, Swzzld, B8G8R8A8, XTL::D3DFMT_A8R8G8B8 , Texture, "X_D3DFMT_B8G8R8A8 -> D3DFMT_A8R8G8B8" }, + /* 0x3C X_D3DFMT_R8G8B8A8 */ { 32, Swzzld, R8G8B8A8, XTL::D3DFMT_A8R8G8B8 , Texture, "X_D3DFMT_R8G8B8A8 -> D3DFMT_A8R8G8B8" }, + /* 0x3D X_D3DFMT_LIN_R5G5B5A1 */ { 16, Linear, R5G5B5A1, XTL::D3DFMT_A1R5G5B5 , Texture, "X_D3DFMT_LIN_R5G5B5A1 -> D3DFMT_A1R5G5B5" }, + /* 0x3E X_D3DFMT_LIN_R4G4B4A4 */ { 16, Linear, R4G4B4A4, XTL::D3DFMT_A4R4G4B4 , Texture, "X_D3DFMT_LIN_R4G4B4A4 -> D3DFMT_A4R4G4B4" }, + /* 0x3F X_D3DFMT_LIN_A8B8G8R8 */ { 32, Linear, A8B8G8R8, XTL::D3DFMT_A8R8G8B8 , Texture, "X_D3DFMT_LIN_A8B8G8R8 -> D3DFMT_A8R8G8B8" }, + /* 0x40 X_D3DFMT_LIN_B8G8R8A8 */ { 32, Linear, B8G8R8A8, XTL::D3DFMT_A8R8G8B8 , Texture, "X_D3DFMT_LIN_B8G8R8A8 -> D3DFMT_A8R8G8B8" }, + /* 0x41 X_D3DFMT_LIN_R8G8B8A8 */ { 32, Linear, R8G8B8A8, XTL::D3DFMT_A8R8G8B8 , Texture, "X_D3DFMT_LIN_R8G8B8A8 -> D3DFMT_A8R8G8B8" }, #if 0 /* 0x42 to 0x63 undefined */ {},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{}, /* 0x64 X_D3DFMT_VERTEXDATA */ { 8, Linear, NoCmpnts, XTL::D3DFMT_VERTEXDATA }, @@ -883,17 +883,28 @@ const XTL::FormatToARGBRow XTL::EmuXBFormatComponentConverter(X_D3DFORMAT Format return nullptr; } +// Is there a converter available from the supplied format to ARGB? +bool XTL::EmuXBFormatCanBeConvertedToARGB(X_D3DFORMAT Format) +{ + const FormatToARGBRow info = EmuXBFormatComponentConverter(Format); + return (info != nullptr); +} + +// Returns if convertion to ARGB is required. This is the case when +// the format has a warning message and there's a converter present. bool XTL::EmuXBFormatRequiresConversionToARGB(X_D3DFORMAT Format) { #ifdef OLD_COLOR_CONVERSION const ComponentEncodingInfo *info = EmuXBFormatComponentEncodingInfo(Format); -#else // !OLD_COLOR_CONVERSION - const FormatToARGBRow info = EmuXBFormatComponentConverter(Format); -#endif // !OLD_COLOR_CONVERSION // Conversion is required if there's ARGB conversion info present, and the format has a warning message if (info != nullptr) if (FormatInfos[Format].warning != nullptr) return true; +#else // !OLD_COLOR_CONVERSION + if (FormatInfos[Format].warning != nullptr) + if (EmuXBFormatCanBeConvertedToARGB(Format)) + return true; +#endif // !OLD_COLOR_CONVERSION return false; } @@ -939,7 +950,7 @@ BOOL XTL::EmuXBFormatIsSwizzled(X_D3DFORMAT Format) BOOL XTL::EmuXBFormatIsRenderTarget(X_D3DFORMAT Format) { if (Format <= X_D3DFMT_LIN_R8G8B8A8) - return (FormatInfos[Format].special == RenderTarget); + return (FormatInfos[Format].usage == RenderTarget); return false; } @@ -947,7 +958,7 @@ BOOL XTL::EmuXBFormatIsRenderTarget(X_D3DFORMAT Format) BOOL XTL::EmuXBFormatIsDepthBuffer(X_D3DFORMAT Format) { if (Format <= X_D3DFMT_LIN_R8G8B8A8) - return (FormatInfos[Format].special == DepthBuffer); + return (FormatInfos[Format].usage == DepthBuffer); return false; } diff --git a/src/CxbxKrnl/EmuD3D8/Convert.h b/src/CxbxKrnl/EmuD3D8/Convert.h index 371b6e88e..ffefe5615 100644 --- a/src/CxbxKrnl/EmuD3D8/Convert.h +++ b/src/CxbxKrnl/EmuD3D8/Convert.h @@ -58,6 +58,8 @@ typedef void(*FormatToARGBRow)(const uint8* src, uint8* dst_argb, int width); extern const FormatToARGBRow EmuXBFormatComponentConverter(X_D3DFORMAT Format); +bool EmuXBFormatCanBeConvertedToARGB(X_D3DFORMAT Format); + bool EmuXBFormatRequiresConversionToARGB(X_D3DFORMAT Format); // how many bits does this format use per pixel? From 69c7d6b99f43b57fbd76b61aad2100968679316c Mon Sep 17 00:00:00 2001 From: PatrickvL Date: Fri, 19 Jan 2018 13:54:28 +0100 Subject: [PATCH 14/21] New EMUPATCH(D3DDevice_GetTexture), forwarded to D3DDevice_GetTexture2. Corrected all texture-related types to X_D3DBaseTexture. Added a few safeguards against accessing null pointers (this part is the only functional change of this commit). --- src/CxbxKrnl/EmuD3D8.cpp | 44 +++++++++++++++++++-------- src/CxbxKrnl/EmuD3D8.h | 15 +++++++-- src/CxbxKrnl/EmuD3D8/VertexBuffer.cpp | 26 ++++++++-------- 3 files changed, 56 insertions(+), 29 deletions(-) diff --git a/src/CxbxKrnl/EmuD3D8.cpp b/src/CxbxKrnl/EmuD3D8.cpp index c132a6811..1875319a5 100644 --- a/src/CxbxKrnl/EmuD3D8.cpp +++ b/src/CxbxKrnl/EmuD3D8.cpp @@ -162,7 +162,7 @@ static XTL::X_VERTEXSHADERCONSTANTMODE g_VertexShaderConstantMode = X_D3DSCM_192 XTL::X_D3DTILE XTL::EmuD3DTileCache[0x08] = {0}; // cached active texture -XTL::X_D3DPixelContainer *XTL::EmuD3DActiveTexture[TEXTURE_STAGES] = {0,0,0,0}; +XTL::X_D3DBaseTexture *XTL::EmuD3DActiveTexture[TEXTURE_STAGES] = {0,0,0,0}; // information passed to the create device proxy thread @@ -2080,12 +2080,12 @@ static void EmuUnswizzleTextureStages() for( int i = 0; i < TEXTURE_STAGES; i++ ) { - XTL::X_D3DPixelContainer *pPixelContainer = XTL::EmuD3DActiveTexture[i]; - if (pPixelContainer == NULL) + XTL::X_D3DBaseTexture *pBaseTexture = XTL::EmuD3DActiveTexture[i]; + if (pBaseTexture == NULL) continue; HRESULT hRet; - XTL::IDirect3DTexture8 *pHostTexture = GetHostTexture(pPixelContainer); + XTL::IDirect3DTexture8 *pHostTexture = GetHostTexture(pBaseTexture); if (pHostTexture != nullptr) { if (pHostTexture->GetType() == XTL::D3DRTYPE_CUBETEXTURE) continue; // Prevent exceptions - skip cubes for now @@ -2093,15 +2093,15 @@ static void EmuUnswizzleTextureStages() DEBUG_D3DRESULT(hRet, "pHostTexture->UnlockRect"); } - if(!IsXboxResourceLocked(pPixelContainer)) + if(!IsXboxResourceLocked(pBaseTexture)) continue; - XTL::X_D3DFORMAT XBFormat = GetXboxPixelContainerFormat(pPixelContainer); + XTL::X_D3DFORMAT XBFormat = GetXboxPixelContainerFormat(pBaseTexture); if(!XTL::EmuXBFormatIsSwizzled(XBFormat)) continue; DWORD dwBPP = XTL::EmuXBFormatBytesPerPixel(XBFormat); - pPixelContainer->Common &= ~X_D3DCOMMON_ISLOCKED; + pBaseTexture->Common &= ~X_D3DCOMMON_ISLOCKED; // TODO: potentially XXHash32::hash() to see if this surface was actually modified.. @@ -3322,7 +3322,8 @@ XTL::X_D3DSurface * WINAPI XTL::EMUPATCH(D3DDevice_GetRenderTarget2)() X_D3DSurface *result = g_pCachedRenderTarget; - EMUPATCH(D3DResource_AddRef)(result); + if (result) + EMUPATCH(D3DResource_AddRef)(result); RETURN(result); } @@ -3355,7 +3356,8 @@ XTL::X_D3DSurface * WINAPI XTL::EMUPATCH(D3DDevice_GetDepthStencilSurface2)() X_D3DSurface *result = g_pCachedDepthStencil; - EMUPATCH(D3DResource_AddRef)(result); + if (result) + EMUPATCH(D3DResource_AddRef)(result); RETURN(result); } @@ -4455,7 +4457,7 @@ HRESULT WINAPI XTL::EMUPATCH(D3DDevice_SetIndices) VOID WINAPI XTL::EMUPATCH(D3DDevice_SetTexture) ( DWORD Stage, - X_D3DResource *pTexture + X_D3DBaseTexture *pTexture ) { FUNC_EXPORTS @@ -4467,7 +4469,7 @@ VOID WINAPI XTL::EMUPATCH(D3DDevice_SetTexture) IDirect3DBaseTexture8 *pHostBaseTexture = nullptr; - EmuD3DActiveTexture[Stage] = (X_D3DPixelContainer*)pTexture; + EmuD3DActiveTexture[Stage] = pTexture; if(pTexture != NULL) { EmuVerifyResourceIsRegistered(pTexture); @@ -9670,14 +9672,14 @@ VOID WINAPI XTL::EMUPATCH(D3DDevice_KickPushBuffer)() // ****************************************************************** // * patch: D3DDevice_GetTexture2 // ****************************************************************** -XTL::X_D3DResource* WINAPI XTL::EMUPATCH(D3DDevice_GetTexture2)(DWORD Stage) +XTL::X_D3DBaseTexture* WINAPI XTL::EMUPATCH(D3DDevice_GetTexture2)(DWORD Stage) { FUNC_EXPORTS LOG_FUNC_ONE_ARG(Stage); // Get the active texture from this stage - X_D3DPixelContainer* pRet = EmuD3DActiveTexture[Stage]; + X_D3DBaseTexture* pRet = EmuD3DActiveTexture[Stage]; if (pRet) { pRet->Common++; @@ -9686,6 +9688,22 @@ XTL::X_D3DResource* WINAPI XTL::EMUPATCH(D3DDevice_GetTexture2)(DWORD Stage) return pRet; } +// ****************************************************************** +// * patch: D3DDevice_GetTexture +// ****************************************************************** +VOID WINAPI XTL::EMUPATCH(D3DDevice_GetTexture) +( + DWORD Stage, + XTL::X_D3DBaseTexture **pTexture +) +{ + FUNC_EXPORTS + + LOG_FORWARD("D3DDevice_GetTexture2"); + + *pTexture = EMUPATCH(D3DDevice_GetTexture2)(Stage); +} + // ****************************************************************** // * patch: D3DDevice_SetStateVB (D3D::CDevice::SetStateVB) // ****************************************************************** diff --git a/src/CxbxKrnl/EmuD3D8.h b/src/CxbxKrnl/EmuD3D8.h index df1802283..68de8fcc2 100644 --- a/src/CxbxKrnl/EmuD3D8.h +++ b/src/CxbxKrnl/EmuD3D8.h @@ -74,7 +74,7 @@ extern VOID EmuD3DCleanup(); extern X_D3DTILE EmuD3DTileCache[0x08]; // EmuD3DActiveTexture -extern X_D3DPixelContainer *EmuD3DActiveTexture[TEXTURE_STAGES]; +extern X_D3DBaseTexture *EmuD3DActiveTexture[TEXTURE_STAGES]; // ****************************************************************** // * patch: Direct3D_CreateDevice @@ -560,7 +560,7 @@ HRESULT WINAPI EMUPATCH(D3DDevice_SetIndices) VOID WINAPI EMUPATCH(D3DDevice_SetTexture) ( DWORD Stage, - X_D3DResource *pTexture + X_D3DBaseTexture *pTexture ); // ****************************************************************** @@ -1736,7 +1736,16 @@ VOID WINAPI EMUPATCH(D3DDevice_KickPushBuffer)(); // ****************************************************************** // * patch: D3DDevice_GetTexture2 // ****************************************************************** -X_D3DResource* WINAPI EMUPATCH(D3DDevice_GetTexture2)(DWORD Stage); +X_D3DBaseTexture* WINAPI EMUPATCH(D3DDevice_GetTexture2)(DWORD Stage); + +// ****************************************************************** +// * patch: D3DDevice_GetTexture +// ****************************************************************** +VOID WINAPI EMUPATCH(D3DDevice_GetTexture) +( + DWORD Stage, + X_D3DBaseTexture **pTexture +); // ****************************************************************** // * patch: D3DDevice_SetStateVB (D3D::CDevice::SetStateVB) diff --git a/src/CxbxKrnl/EmuD3D8/VertexBuffer.cpp b/src/CxbxKrnl/EmuD3D8/VertexBuffer.cpp index 165b34b8e..43225c780 100644 --- a/src/CxbxKrnl/EmuD3D8/VertexBuffer.cpp +++ b/src/CxbxKrnl/EmuD3D8/VertexBuffer.cpp @@ -639,18 +639,18 @@ bool XTL::VertexPatcher::NormalizeTexCoords(VertexPatchDesc *pPatchDesc, UINT ui { // Check for active linear textures. bool bHasLinearTex = false, bTexIsLinear[4] = { false }; - X_D3DPixelContainer *pLinearPixelContainer[4]; + X_D3DBaseTexture *pLinearBaseTexture[4]; for(uint08 i = 0; i < 4; i++) { - X_D3DPixelContainer *pPixelContainer = EmuD3DActiveTexture[i]; - if (pPixelContainer) + X_D3DBaseTexture *pBaseTexture = EmuD3DActiveTexture[i]; + if (pBaseTexture) { - XTL::X_D3DFORMAT XBFormat = (XTL::X_D3DFORMAT)((pPixelContainer->Format & X_D3DFORMAT_FORMAT_MASK) >> X_D3DFORMAT_FORMAT_SHIFT); + XTL::X_D3DFORMAT XBFormat = (XTL::X_D3DFORMAT)((pBaseTexture->Format & X_D3DFORMAT_FORMAT_MASK) >> X_D3DFORMAT_FORMAT_SHIFT); if (EmuXBFormatIsLinear(XBFormat)) { bHasLinearTex = bTexIsLinear[i] = true; - pLinearPixelContainer[i] = pPixelContainer; + pLinearBaseTexture[i] = pBaseTexture; } } } @@ -741,8 +741,8 @@ bool XTL::VertexPatcher::NormalizeTexCoords(VertexPatchDesc *pPatchDesc, UINT ui { if(bTexIsLinear[0]) { - ((FLOAT*)pUVData)[0] /= ( pLinearPixelContainer[0]->Size & X_D3DSIZE_WIDTH_MASK) + 1; - ((FLOAT*)pUVData)[1] /= ((pLinearPixelContainer[0]->Size & X_D3DSIZE_HEIGHT_MASK) >> X_D3DSIZE_HEIGHT_SHIFT) + 1; + ((FLOAT*)pUVData)[0] /= ( pLinearBaseTexture[0]->Size & X_D3DSIZE_WIDTH_MASK) + 1; + ((FLOAT*)pUVData)[1] /= ((pLinearBaseTexture[0]->Size & X_D3DSIZE_HEIGHT_MASK) >> X_D3DSIZE_HEIGHT_SHIFT) + 1; } pUVData += sizeof(FLOAT) * 2; } @@ -751,8 +751,8 @@ bool XTL::VertexPatcher::NormalizeTexCoords(VertexPatchDesc *pPatchDesc, UINT ui { if(bTexIsLinear[1]) { - ((FLOAT*)pUVData)[0] /= ( pLinearPixelContainer[1]->Size & X_D3DSIZE_WIDTH_MASK) + 1; - ((FLOAT*)pUVData)[1] /= ((pLinearPixelContainer[1]->Size & X_D3DSIZE_HEIGHT_MASK) >> X_D3DSIZE_HEIGHT_SHIFT) + 1; + ((FLOAT*)pUVData)[0] /= ( pLinearBaseTexture[1]->Size & X_D3DSIZE_WIDTH_MASK) + 1; + ((FLOAT*)pUVData)[1] /= ((pLinearBaseTexture[1]->Size & X_D3DSIZE_HEIGHT_MASK) >> X_D3DSIZE_HEIGHT_SHIFT) + 1; } pUVData += sizeof(FLOAT) * 2; } @@ -761,16 +761,16 @@ bool XTL::VertexPatcher::NormalizeTexCoords(VertexPatchDesc *pPatchDesc, UINT ui { if(bTexIsLinear[2]) { - ((FLOAT*)pUVData)[0] /= ( pLinearPixelContainer[2]->Size & X_D3DSIZE_WIDTH_MASK) + 1; - ((FLOAT*)pUVData)[1] /= ((pLinearPixelContainer[2]->Size & X_D3DSIZE_HEIGHT_MASK) >> X_D3DSIZE_HEIGHT_SHIFT) + 1; + ((FLOAT*)pUVData)[0] /= ( pLinearBaseTexture[2]->Size & X_D3DSIZE_WIDTH_MASK) + 1; + ((FLOAT*)pUVData)[1] /= ((pLinearBaseTexture[2]->Size & X_D3DSIZE_HEIGHT_MASK) >> X_D3DSIZE_HEIGHT_SHIFT) + 1; } pUVData += sizeof(FLOAT) * 2; } if((dwTexN >= 4) && bTexIsLinear[3]) { - ((FLOAT*)pUVData)[0] /= ( pLinearPixelContainer[3]->Size & X_D3DSIZE_WIDTH_MASK) + 1; - ((FLOAT*)pUVData)[1] /= ((pLinearPixelContainer[3]->Size & X_D3DSIZE_HEIGHT_MASK) >> X_D3DSIZE_HEIGHT_SHIFT) + 1; + ((FLOAT*)pUVData)[0] /= ( pLinearBaseTexture[3]->Size & X_D3DSIZE_WIDTH_MASK) + 1; + ((FLOAT*)pUVData)[1] /= ((pLinearBaseTexture[3]->Size & X_D3DSIZE_HEIGHT_MASK) >> X_D3DSIZE_HEIGHT_SHIFT) + 1; } } From 81e2764aafcb1e3ed20560a68bb9e2e1518fbc21 Mon Sep 17 00:00:00 2001 From: PatrickvL Date: Fri, 19 Jan 2018 17:12:44 +0100 Subject: [PATCH 15/21] HalWriteSMBusValue typo fix that allows it to succeed after the final IORead --- src/CxbxKrnl/EmuKrnlHal.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/CxbxKrnl/EmuKrnlHal.cpp b/src/CxbxKrnl/EmuKrnlHal.cpp index b2468c316..928172b02 100644 --- a/src/CxbxKrnl/EmuKrnlHal.cpp +++ b/src/CxbxKrnl/EmuKrnlHal.cpp @@ -539,7 +539,7 @@ XBSYSAPI EXPORTNUM(50) xboxkrnl::NTSTATUS NTAPI xboxkrnl::HalWriteSMBusValue // Note : GE_HOST_STC triggers ExecuteTransaction, which writes the command to the specified address // Check if the command was executed successfully - if (g_SMBus->IORead(1, SMB_GLOBAL_STATUS) | GS_PRERR_STS) { + if (g_SMBus->IORead(1, SMB_GLOBAL_STATUS) & GS_PRERR_STS) { Status = STATUS_UNSUCCESSFUL; } From 1f7e8c9877672ee90e1eafd54b8b95ee4b8a63ca Mon Sep 17 00:00:00 2001 From: PatrickvL Date: Fri, 19 Jan 2018 17:14:20 +0100 Subject: [PATCH 16/21] SMBus::ConnectDevice requires the same address-translation as ExecuteTransaction (otherwise, devices can't be found). --- src/CxbxKrnl/SMBus.cpp | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/src/CxbxKrnl/SMBus.cpp b/src/CxbxKrnl/SMBus.cpp index 7d64a8fe4..90b13a268 100644 --- a/src/CxbxKrnl/SMBus.cpp +++ b/src/CxbxKrnl/SMBus.cpp @@ -24,13 +24,14 @@ void SMBus::Reset() void SMBus::ConnectDevice(uint8_t addr, SMDevice *pDevice) { + uint8_t dev_addr = (addr >> 1) & 0x7f; - if (m_Devices.find(addr) != m_Devices.end()) { + if (m_Devices.find(dev_addr) != m_Devices.end()) { printf("PCIBus: Attempting to connect two devices to the same device address\n"); return; } - m_Devices[addr] = pDevice; + m_Devices[dev_addr] = pDevice; pDevice->Init(); } From 06eb0f3a5c0b0ca6f51cad30879e79cdfd6d33bd Mon Sep 17 00:00:00 2001 From: PatrickvL Date: Fri, 19 Jan 2018 17:16:27 +0100 Subject: [PATCH 17/21] Unpatched D3DResource_AddRef, and avoid calling it wherever possible --- src/CxbxKrnl/EmuD3D8.cpp | 12 ++++++------ 1 file changed, 6 insertions(+), 6 deletions(-) diff --git a/src/CxbxKrnl/EmuD3D8.cpp b/src/CxbxKrnl/EmuD3D8.cpp index 1875319a5..e156e802d 100644 --- a/src/CxbxKrnl/EmuD3D8.cpp +++ b/src/CxbxKrnl/EmuD3D8.cpp @@ -3114,7 +3114,7 @@ XTL::X_D3DSurface* WINAPI XTL::EMUPATCH(D3DDevice_GetBackBuffer2) pBackBuffer->Data = X_D3DRESOURCE_DATA_BACK_BUFFER; // Increment reference count - pBackBuffer->Common++; + pBackBuffer->Common++; // EMUPATCH(D3DResource_AddRef)(pBackBuffer); return pBackBuffer; } @@ -3323,7 +3323,7 @@ XTL::X_D3DSurface * WINAPI XTL::EMUPATCH(D3DDevice_GetRenderTarget2)() X_D3DSurface *result = g_pCachedRenderTarget; if (result) - EMUPATCH(D3DResource_AddRef)(result); + result->Common++; // EMUPATCH(D3DResource_AddRef)(result); RETURN(result); } @@ -3357,7 +3357,7 @@ XTL::X_D3DSurface * WINAPI XTL::EMUPATCH(D3DDevice_GetDepthStencilSurface2)() X_D3DSurface *result = g_pCachedDepthStencil; if (result) - EMUPATCH(D3DResource_AddRef)(result); + result->Common++; // EMUPATCH(D3DResource_AddRef)(result); RETURN(result); } @@ -5952,7 +5952,7 @@ ULONG WINAPI XTL::EMUPATCH(D3DResource_AddRef) X_D3DResource *pThis ) { - FUNC_EXPORTS + // FUNC_EXPORTS LOG_FUNC_ONE_ARG(pThis); @@ -7936,7 +7936,7 @@ XTL::X_D3DVertexBuffer* WINAPI XTL::EMUPATCH(D3DDevice_GetStreamSource2) pVertexBuffer = g_D3DStreams[StreamNumber]; if (pVertexBuffer) { - EMUPATCH(D3DResource_AddRef)(pVertexBuffer); + pVertexBuffer->Common++; // EMUPATCH(D3DResource_AddRef)(pVertexBuffer); *pStride = g_D3DStreamStrides[StreamNumber]; } } @@ -9682,7 +9682,7 @@ XTL::X_D3DBaseTexture* WINAPI XTL::EMUPATCH(D3DDevice_GetTexture2)(DWORD Stage) X_D3DBaseTexture* pRet = EmuD3DActiveTexture[Stage]; if (pRet) { - pRet->Common++; + pRet->Common++; // EMUPATCH(D3DResource_AddRef)(pRet); } return pRet; From ac88ecbe9513f195715ace2ab46c5f07b8d9f4ee Mon Sep 17 00:00:00 2001 From: PatrickvL Date: Fri, 19 Jan 2018 17:18:00 +0100 Subject: [PATCH 18/21] Switched over to new color-format conversion (required lowering an #endif) My tests thus far show no regressions! --- src/CxbxKrnl/EmuD3D8.cpp | 2 +- src/CxbxKrnl/EmuD3D8/Convert.h | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/src/CxbxKrnl/EmuD3D8.cpp b/src/CxbxKrnl/EmuD3D8.cpp index e156e802d..e7bee279d 100644 --- a/src/CxbxKrnl/EmuD3D8.cpp +++ b/src/CxbxKrnl/EmuD3D8.cpp @@ -5829,7 +5829,6 @@ VOID WINAPI XTL::EMUPATCH(D3DResource_Register) w += dwMipWidth * (sizeof(DWORD) - dwBPP); } } -#endif // !OLD_COLOR_CONVERSION } //__asm int 3; @@ -5839,6 +5838,7 @@ VOID WINAPI XTL::EMUPATCH(D3DResource_Register) // Flush unused data buffers free(pExpandedTexture); } +#endif // !OLD_COLOR_CONVERSION } } diff --git a/src/CxbxKrnl/EmuD3D8/Convert.h b/src/CxbxKrnl/EmuD3D8/Convert.h index ffefe5615..b16a86521 100644 --- a/src/CxbxKrnl/EmuD3D8/Convert.h +++ b/src/CxbxKrnl/EmuD3D8/Convert.h @@ -36,7 +36,7 @@ #include "CxbxKrnl.h" -#define OLD_COLOR_CONVERSION +//#define OLD_COLOR_CONVERSION // simple render state encoding lookup table #define X_D3DRSSE_UNK 0x7fffffff From c09210d12bbce55fd7365a724b858af18b058e6e Mon Sep 17 00:00:00 2001 From: PatrickvL Date: Fri, 19 Jan 2018 17:40:33 +0100 Subject: [PATCH 19/21] Log SetLEDSequence --- src/CxbxKrnl/CxbxKrnl.cpp | 1 + 1 file changed, 1 insertion(+) diff --git a/src/CxbxKrnl/CxbxKrnl.cpp b/src/CxbxKrnl/CxbxKrnl.cpp index 741390536..4c5f7bc29 100644 --- a/src/CxbxKrnl/CxbxKrnl.cpp +++ b/src/CxbxKrnl/CxbxKrnl.cpp @@ -789,6 +789,7 @@ void SetLEDSequence(LED::Sequence aLEDSequence) { // TODO : Move to best suited location & implement // See http://xboxdevwiki.net/PIC#The_LED + DbgPrintf("SMC : SetLEDSequence : %u\n", (byte)aLEDSequence); } __declspec(noreturn) void CxbxKrnlInit From 9084661b0ebf471e9ec5c078b2c7a18b2f3675a3 Mon Sep 17 00:00:00 2001 From: ergo720 Date: Sun, 21 Jan 2018 11:02:25 +0100 Subject: [PATCH 20/21] LED --- resource/Cxbx.rc | 1 + src/Cxbx/ResCxbx.h | 1 + src/Cxbx/WndMain.cpp | 165 ++++++++++++++++++++++++++++++++++--- src/Cxbx/WndMain.h | 35 ++++++-- src/CxbxKrnl/CxbxKrnl.cpp | 8 -- src/CxbxKrnl/EmuShared.h | 33 ++++++++ src/CxbxKrnl/LED.h | 2 - src/CxbxKrnl/SMCDevice.cpp | 35 +++++++- 8 files changed, 248 insertions(+), 32 deletions(-) diff --git a/resource/Cxbx.rc b/resource/Cxbx.rc index 5b48b0c29..2119e7eee 100644 --- a/resource/Cxbx.rc +++ b/resource/Cxbx.rc @@ -161,6 +161,7 @@ BEGIN MENUITEM SEPARATOR MENUITEM "&About", ID_HELP_ABOUT END + MENUITEM "LED", ID_LED END diff --git a/src/Cxbx/ResCxbx.h b/src/Cxbx/ResCxbx.h index 642580dd5..70b20c4e2 100644 --- a/src/Cxbx/ResCxbx.h +++ b/src/Cxbx/ResCxbx.h @@ -103,6 +103,7 @@ #define ID_SETTINGS_XINPUT 40086 #define ID_SETTINGS_HACKS 40087 #define ID_HACKS_DISABLEPIXELSHADERS 40088 +#define ID_LED 40089 #define IDC_STATIC -1 // Next default values for new objects diff --git a/src/Cxbx/WndMain.cpp b/src/Cxbx/WndMain.cpp index 9b9cd0c7e..d9d944bf8 100644 --- a/src/Cxbx/WndMain.cpp +++ b/src/Cxbx/WndMain.cpp @@ -42,12 +42,14 @@ #include "ResCxbx.h" #include "CxbxVersion.h" #include "Shlwapi.h" +#include #include #include // for std::stringstream #include "CxbxKrnl/xxhash32.h" // for XXHash32::hash +#define XBOX_LED_FLASH_PERIOD 176 // if you know a more accurate value, put it here #define STBI_ONLY_JPEG #define STBI_NO_LINEAR #define STB_IMAGE_IMPLEMENTATION @@ -84,6 +86,7 @@ void ClearHLECache() } #define TIMERID_FPS 0 +#define TIMERID_LED 1 WndMain::WndMain(HINSTANCE x_hInstance) : Wnd(x_hInstance), @@ -366,6 +369,23 @@ LRESULT CALLBACK WndMain::WndProc(HWND hwnd, UINT uMsg, WPARAM wParam, LPARAM lP m_BackBmp = CreateCompatibleBitmap(hDC, m_w, m_h); + // create Xbox LED bitmap + { + m_xBmp = GetSystemMetrics(SM_CXMENUCHECK); + m_yBmp = GetSystemMetrics(SM_CYMENUCHECK); + m_LedDC = CreateCompatibleDC(hDC); + m_LedBmp = CreateCompatibleBitmap(hDC, m_xBmp, m_yBmp); + m_BrushBlack = CreateSolidBrush(RGB(0, 0, 0)); + m_BrushRed = CreateSolidBrush(RGB(255, 0, 0)); + m_BrushGreen = CreateSolidBrush(RGB(0, 255, 0)); + m_BrushOrange = CreateSolidBrush(RGB(255, 165, 0)); + m_PenBlack = CreatePen(PS_SOLID, 1, RGB(0, 0, 0)); + m_PenRed = CreatePen(PS_SOLID, 1, RGB(255, 0, 0)); + m_PenGreen = CreatePen(PS_SOLID, 1, RGB(0, 255, 0)); + m_PenOrange = CreatePen(PS_SOLID, 1, RGB(255, 165, 0)); + DrawLedBitmap(hwnd, true); + } + // decompress jpeg, convert to bitmap resource { HRSRC hSrc = FindResource(NULL, MAKEINTRESOURCE(IDR_JPEG_SPLASH), "JPEG"); @@ -450,9 +470,14 @@ LRESULT CALLBACK WndMain::WndProc(HWND hwnd, UINT uMsg, WPARAM wParam, LPARAM lP if (m_hwndChild == NULL) { float fps = 0; float mspf = 0; + bool LedHasChanged = false; + int LedSequence[4] = { XBOX_LED_COLOUR_GREEN, XBOX_LED_COLOUR_GREEN, XBOX_LED_COLOUR_GREEN, XBOX_LED_COLOUR_GREEN }; g_EmuShared->SetCurrentMSpF(&mspf); g_EmuShared->SetCurrentFPS(&fps); + g_EmuShared->SetLedStatus(&LedHasChanged); + g_EmuShared->SetLedSequence(LedSequence); SetTimer(hwnd, TIMERID_FPS, 1000, (TIMERPROC)NULL); + SetTimer(hwnd, TIMERID_LED, XBOX_LED_FLASH_PERIOD, (TIMERPROC)NULL); m_hwndChild = GetWindow(hwnd, GW_CHILD); // (HWND)HIWORD(wParam) seems to be NULL UpdateCaption(); RefreshMenus(); @@ -469,8 +494,10 @@ LRESULT CALLBACK WndMain::WndProc(HWND hwnd, UINT uMsg, WPARAM wParam, LPARAM lP // (HWND)HIWORD(wParam) seems to be NULL, so we can't compare to m_hwndChild if (m_hwndChild != NULL) { // Let's hope this signal originated from the only child window KillTimer(hwnd, TIMERID_FPS); + KillTimer(hwnd, TIMERID_LED); m_hwndChild = NULL; StopEmulation(); + DrawLedBitmap(hwnd, true); } } break; @@ -487,6 +514,12 @@ LRESULT CALLBACK WndMain::WndProc(HWND hwnd, UINT uMsg, WPARAM wParam, LPARAM lP UpdateCaption(); } break; + + case TIMERID_LED: + { + DrawLedBitmap(hwnd, false); + } + break; } } break; @@ -1246,27 +1279,49 @@ LRESULT CALLBACK WndMain::WndProc(HWND hwnd, UINT uMsg, WPARAM wParam, LPARAM lP { FreeConsole(); - HDC hDC = GetDC(hwnd); + HDC hDC = GetDC(hwnd); - SelectObject(m_LogoDC, m_OrigLogo); + SelectObject(m_LogoDC, m_OrigLogo); - SelectObject(m_BackDC, m_OrigBmp); + SelectObject(m_BackDC, m_OrigBmp); SelectObject(m_GameLogoDC, m_OrigGameLogo); - DeleteObject(m_LogoDC); + SelectObject(m_LedDC, m_OriLed); - DeleteObject(m_BackDC); + DeleteObject(m_LogoDC); + + DeleteObject(m_BackDC); DeleteObject(m_GameLogoDC); - DeleteObject(m_LogoBmp); + DeleteObject(m_LedDC); - DeleteObject(m_BackBmp); + DeleteObject(m_LogoBmp); + + DeleteObject(m_BackBmp); DeleteObject(m_GameLogoBMP); - ReleaseDC(hwnd, hDC); + DeleteObject(m_LedBmp); + + DeleteObject(m_BrushBlack); + + DeleteObject(m_BrushRed); + + DeleteObject(m_BrushGreen); + + DeleteObject(m_BrushOrange); + + DeleteObject(m_PenBlack); + + DeleteObject(m_PenRed); + + DeleteObject(m_PenGreen); + + DeleteObject(m_PenOrange); + + ReleaseDC(hwnd, hDC); delete m_Xbe; @@ -2027,8 +2082,8 @@ void WndMain::CrashMonitor() if (m_bIsStarted) // that's a hard crash, Dr Watson is invoked { KillTimer(m_hwnd, TIMERID_FPS); - //KillTimer(m_hwnd, 2); for the LED - //DrawDefaultLedBitmap(hwnd); for the LED + KillTimer(m_hwnd, TIMERID_LED); + DrawLedBitmap(m_hwnd, true); m_hwndChild = NULL; m_bIsStarted = false; UpdateCaption(); @@ -2045,3 +2100,93 @@ void WndMain::CrashMonitor() return; } + +// draw Xbox LED bitmap +void WndMain::DrawLedBitmap(HWND hwnd, bool bdefault) +{ + HMENU hMenu = GetMenu(hwnd); + if (bdefault) // draw default black bitmap + { + SelectObject(m_LedDC, m_BrushBlack); + SelectObject(m_LedDC, m_PenBlack); + m_OriLed = (HBITMAP)SelectObject(m_LedDC, m_LedBmp); + Rectangle(m_LedDC, 0, 0, m_xBmp, m_yBmp); + m_LedBmp = (HBITMAP)SelectObject(m_LedDC, m_OriLed); + MENUITEMINFO mii; + mii.cbSize = sizeof(mii); + mii.fMask = MIIM_BITMAP | MIIM_FTYPE; + mii.fType = MFT_RIGHTJUSTIFY; + mii.hbmpItem = m_LedBmp; + SetMenuItemInfo(hMenu, ID_LED, FALSE, &mii); + DrawMenuBar(hwnd); + } + else // draw colored bitmap + { + static int LedSequenceOffset = 0; + bool bLedHasChanged; + int LedSequence[4]; + + g_EmuShared->GetLedStatus(&bLedHasChanged); + g_EmuShared->GetLedSequence(LedSequence); + if (bLedHasChanged) + { + LedSequenceOffset = 0; + bLedHasChanged = false; + g_EmuShared->SetLedStatus(&bLedHasChanged); + } + + m_OriLed = (HBITMAP)SelectObject(m_LedDC, m_LedBmp); + Rectangle(m_LedDC, 0, 0, m_xBmp, m_yBmp); + MENUITEMINFO mii; + mii.cbSize = sizeof(mii); + mii.fMask = MIIM_BITMAP | MIIM_FTYPE; + mii.fType = MFT_RIGHTJUSTIFY; + mii.hbmpItem = m_LedBmp; + + switch (LedSequence[LedSequenceOffset]) + { + case XBOX_LED_COLOUR_RED: + { + SelectObject(m_LedDC, m_BrushRed); + SelectObject(m_LedDC, m_PenRed); + } + break; + + case XBOX_LED_COLOUR_GREEN: + { + SelectObject(m_LedDC, m_BrushGreen); + SelectObject(m_LedDC, m_PenGreen); + } + break; + + case XBOX_LED_COLOUR_ORANGE: + { + SelectObject(m_LedDC, m_BrushOrange); + SelectObject(m_LedDC, m_PenOrange); + } + break; + + case XBOX_LED_COLOUR_OFF: + { + SelectObject(m_LedDC, m_BrushBlack); + SelectObject(m_LedDC, m_PenBlack); + } + break; + } + + m_LedBmp = (HBITMAP)SelectObject(m_LedDC, m_OriLed); + if (LedSequenceOffset == 3) + { + LedSequenceOffset = 0; + } + else + { + ++LedSequenceOffset; + } + SetMenuItemInfo(hMenu, ID_LED, FALSE, &mii); + + DrawMenuBar(hwnd); + } + + return; +} diff --git a/src/Cxbx/WndMain.h b/src/Cxbx/WndMain.h index 649cd44ab..5a5a70183 100644 --- a/src/Cxbx/WndMain.h +++ b/src/Cxbx/WndMain.h @@ -131,18 +131,35 @@ class WndMain : public Wnd // ****************************************************************** void CrashMonitor(); - // ****************************************************************** - // * drawing information - // ****************************************************************** - HDC m_BackDC; - HDC m_LogoDC; + // ****************************************************************** + // * draw Xbox LED bitmap + // ****************************************************************** + void DrawLedBitmap(HWND hwnd, bool boolbDefault); + + // ****************************************************************** + // * drawing information + // ****************************************************************** + HDC m_BackDC; + HDC m_LogoDC; HDC m_GameLogoDC; - HBITMAP m_OrigBmp; - HBITMAP m_OrigLogo; + HDC m_LedDC; + HBITMAP m_OrigBmp; + HBITMAP m_OrigLogo; HBITMAP m_OrigGameLogo; - HBITMAP m_BackBmp; - HBITMAP m_LogoBmp; + HBITMAP m_OriLed; + HBITMAP m_BackBmp; + HBITMAP m_LogoBmp; HBITMAP m_GameLogoBMP; + HBITMAP m_LedBmp; + HBRUSH m_BrushBlack; + HBRUSH m_BrushRed; + HBRUSH m_BrushGreen; + HBRUSH m_BrushOrange; + HPEN m_PenBlack; + HPEN m_PenRed; + HPEN m_PenGreen; + HPEN m_PenOrange; + int m_xBmp, m_yBmp; // ****************************************************************** // * Xbe objects diff --git a/src/CxbxKrnl/CxbxKrnl.cpp b/src/CxbxKrnl/CxbxKrnl.cpp index 4c5f7bc29..29eb29666 100644 --- a/src/CxbxKrnl/CxbxKrnl.cpp +++ b/src/CxbxKrnl/CxbxKrnl.cpp @@ -65,7 +65,6 @@ namespace xboxkrnl #include "Xbox.h" // For InitXboxHardware() #include "EEPROMDevice.h" // For g_EEPROM -#include "LED.h" // For LED::Sequence /* prevent name collisions */ namespace NtDll @@ -785,13 +784,6 @@ void LoadXboxKeys(std::string path) EmuWarning("Failed to load Keys.bin. Cxbx-Reloaded will be unable to read Save Data from a real Xbox"); } -void SetLEDSequence(LED::Sequence aLEDSequence) -{ - // TODO : Move to best suited location & implement - // See http://xboxdevwiki.net/PIC#The_LED - DbgPrintf("SMC : SetLEDSequence : %u\n", (byte)aLEDSequence); -} - __declspec(noreturn) void CxbxKrnlInit ( HWND hwndParent, diff --git a/src/CxbxKrnl/EmuShared.h b/src/CxbxKrnl/EmuShared.h index bcc49e4cc..15ac8fbdb 100644 --- a/src/CxbxKrnl/EmuShared.h +++ b/src/CxbxKrnl/EmuShared.h @@ -41,6 +41,13 @@ #include +enum { + XBOX_LED_COLOUR_OFF, + XBOX_LED_COLOUR_GREEN, + XBOX_LED_COLOUR_RED, + XBOX_LED_COLOUR_ORANGE, +}; + enum { LLE_APU = 1 << 0, LLE_GPU = 1 << 1, @@ -136,6 +143,30 @@ class EmuShared : public Mutex void GetLaunchDataPAddress(PAddr *value) { Lock(); *value = m_LaunchDataPAddress; Unlock(); } void SetLaunchDataPAddress(PAddr *value) { Lock(); m_LaunchDataPAddress = *value; Unlock(); } + // ****************************************************************** + // * Xbox LED values Accessors + // ****************************************************************** + void GetLedStatus(bool *value) { Lock(); *value = m_bLedHasChanged; Unlock(); } + void SetLedStatus(bool *value) { Lock(); m_bLedHasChanged = *value; Unlock(); } + void GetLedSequence(int *value) + { + Lock(); + for (int i = 0; i < 4; ++i) + { + value[i] = m_LedSequence[i]; + } + Unlock(); + } + void SetLedSequence(int *value) + { + Lock(); + for (int i = 0; i < 4; ++i) + { + m_LedSequence[i] = value[i]; + } + Unlock(); + } + private: // ****************************************************************** @@ -158,6 +189,8 @@ class EmuShared : public Mutex float m_FPS; bool m_bMultiXbe; PAddr m_LaunchDataPAddress; + bool m_bLedHasChanged; + int m_LedSequence[4]; }; // ****************************************************************** diff --git a/src/CxbxKrnl/LED.h b/src/CxbxKrnl/LED.h index 16273a58a..f05668e82 100644 --- a/src/CxbxKrnl/LED.h +++ b/src/CxbxKrnl/LED.h @@ -90,5 +90,3 @@ namespace LED { constexpr Sequence FAST_GREEN_ORANGE = Phase0::Green | Phase1::Orange | Phase2::Green | Phase3::Orange; } - -extern void SetLEDSequence(LED::Sequence aLEDSequence); diff --git a/src/CxbxKrnl/SMCDevice.cpp b/src/CxbxKrnl/SMCDevice.cpp index 18a708270..8e7c8c007 100644 --- a/src/CxbxKrnl/SMCDevice.cpp +++ b/src/CxbxKrnl/SMCDevice.cpp @@ -35,15 +35,44 @@ // ****************************************************************** #define _XBOXKRNL_DEFEXTRN_ -#include "SMCDevice.h" // For SMCDevice -#include "LED.h" - /* prevent name collisions */ namespace xboxkrnl { #include // For xbox.h:AV_PACK_HDTV }; +#include "EmuShared.h" +#include "SMCDevice.h" // For SMCDevice +#include "LED.h" + +void SetLEDSequence(LED::Sequence aLEDSequence) +{ + // See http://xboxdevwiki.net/PIC#The_LED + DbgPrintf("SMC : SetLEDSequence : %u\n", (byte)aLEDSequence); + + bool bLedHasChanged = true; + + if (aLEDSequence == LED::GREEN) // Automatic solid green color + { + int LedSequence[4] = { XBOX_LED_COLOUR_GREEN, XBOX_LED_COLOUR_GREEN, XBOX_LED_COLOUR_GREEN, XBOX_LED_COLOUR_GREEN }; + + g_EmuShared->SetLedStatus(&bLedHasChanged); + g_EmuShared->SetLedSequence(LedSequence); + } + else // Draw the color represented by the sequence obtained + { + int LedSequence[4] = { XBOX_LED_COLOUR_OFF, XBOX_LED_COLOUR_OFF, XBOX_LED_COLOUR_OFF, XBOX_LED_COLOUR_OFF }; + + LedSequence[0] = ((aLEDSequence >> 3) & 1) | ((aLEDSequence >> 6) & 2); + LedSequence[1] = ((aLEDSequence >> 2) & 1) | ((aLEDSequence >> 5) & 2); + LedSequence[2] = ((aLEDSequence >> 1) & 1) | ((aLEDSequence >> 4) & 2); + LedSequence[3] = (aLEDSequence & 1) | ((aLEDSequence >> 3) & 2); + + g_EmuShared->SetLedStatus(&bLedHasChanged); + g_EmuShared->SetLedSequence(LedSequence); + } +} + /* SMCDevice */ SMCDevice::SMCDevice(HardwareModel hardwareModel) From 1bde0199777f96443352be0b64411eb4806ebe49 Mon Sep 17 00:00:00 2001 From: ergo720 Date: Sun, 21 Jan 2018 11:32:53 +0100 Subject: [PATCH 21/21] comment on the led --- src/CxbxKrnl/SMCDevice.cpp | 6 +++++- 1 file changed, 5 insertions(+), 1 deletion(-) diff --git a/src/CxbxKrnl/SMCDevice.cpp b/src/CxbxKrnl/SMCDevice.cpp index 8e7c8c007..2520f24c7 100644 --- a/src/CxbxKrnl/SMCDevice.cpp +++ b/src/CxbxKrnl/SMCDevice.cpp @@ -182,7 +182,11 @@ void SMCDevice::WriteByte(uint8_t command, uint8_t value) // TODO : Implement the above, SMB_GLOBAL_STATUS should probably get the GS_PRERR_STS flag. But how? return; } - // #define SMC_COMMAND_LED_SEQUENCE 0x08 // LED flashing sequence + case SMC_COMMAND_LED_SEQUENCE: // 0x08 LED flashing sequence + // ergo720: if WriteWord is true the Xbox still sets the LED correctly but it errors with ntstatus + // STATUS_IO_DEVICE_ERROR, however WriteWord is not accessible from here + // The LED flashing sequence is stored in the buffer of the SMCDevice class, so there's nothing to do here + break; //0x0C tray eject(0 = eject; 1 = load) //0x0E another scratch register ? seems like an error code. //0x19 reset on eject(0 = enable; 1 = disable)