diff --git a/resource/Cxbx.rc b/resource/Cxbx.rc index b5ad5e49b..3c9700d72 100644 --- a/resource/Cxbx.rc +++ b/resource/Cxbx.rc @@ -163,6 +163,7 @@ BEGIN MENUITEM SEPARATOR MENUITEM "&About", ID_HELP_ABOUT END + MENUITEM "LED", ID_LED END 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; diff --git a/src/Cxbx/ResCxbx.h b/src/Cxbx/ResCxbx.h index 3c7a7fe8a..1e925ec4a 100644 --- a/src/Cxbx/ResCxbx.h +++ b/src/Cxbx/ResCxbx.h @@ -105,6 +105,7 @@ #define ID_EMULATION_STARTDEBUG 40087 #define ID_SETTINGS_HACKS 40088 #define ID_HACKS_DISABLEPIXELSHADERS 40089 +#define ID_LED 40090 #define IDC_STATIC -1 // Next default values for new objects @@ -112,7 +113,7 @@ #ifdef APSTUDIO_INVOKED #ifndef APSTUDIO_READONLY_SYMBOLS #define _APS_NEXT_RESOURCE_VALUE 130 -#define _APS_NEXT_COMMAND_VALUE 40090 +#define _APS_NEXT_COMMAND_VALUE 40091 #define _APS_NEXT_CONTROL_VALUE 1058 #define _APS_NEXT_SYMED_VALUE 104 #endif diff --git a/src/Cxbx/WndMain.cpp b/src/Cxbx/WndMain.cpp index a518169c2..2cd2bc7ac 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; @@ -1256,27 +1289,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; @@ -2065,8 +2120,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(); @@ -2083,3 +2138,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 081856f10..6d209a19d 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 676619874..a296d39d5 100644 --- a/src/CxbxKrnl/CxbxKrnl.cpp +++ b/src/CxbxKrnl/CxbxKrnl.cpp @@ -66,7 +66,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 @@ -84,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 */ @@ -534,7 +533,7 @@ void CxbxKrnlMain(int argc, char* argv[]) } // Get KernelDebugFileName : - std::string DebugFileName; + std::string DebugFileName = ""; if (argc > 4) { DebugFileName = argv[5]; } @@ -651,6 +650,7 @@ void CxbxKrnlMain(int argc, char* argv[]) } CxbxRestoreContiguousMemory(szFilePath_memory_bin); + CxbxRestorePersistentMemoryRegions(); EEPROM = CxbxRestoreEEPROM(szFilePath_EEPROM_bin); if (EEPROM == nullptr) @@ -687,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); @@ -799,12 +797,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 -} - __declspec(noreturn) void CxbxKrnlInit ( HWND hwndParent, @@ -997,13 +989,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); @@ -1130,7 +1116,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; @@ -1187,6 +1173,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;vGetType() == XTL::D3DRTYPE_CUBETEXTURE) continue; // Prevent exceptions - skip cubes for now @@ -2071,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.. @@ -3092,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; } @@ -3300,7 +3322,8 @@ XTL::X_D3DSurface * WINAPI XTL::EMUPATCH(D3DDevice_GetRenderTarget2)() X_D3DSurface *result = g_pCachedRenderTarget; - EMUPATCH(D3DResource_AddRef)(result); + if (result) + result->Common++; // EMUPATCH(D3DResource_AddRef)(result); RETURN(result); } @@ -3333,7 +3356,8 @@ XTL::X_D3DSurface * WINAPI XTL::EMUPATCH(D3DDevice_GetDepthStencilSurface2)() X_D3DSurface *result = g_pCachedDepthStencil; - EMUPATCH(D3DResource_AddRef)(result); + if (result) + result->Common++; // EMUPATCH(D3DResource_AddRef)(result); RETURN(result); } @@ -4433,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 @@ -4445,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); @@ -5225,7 +5249,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;*/ } @@ -5268,7 +5292,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); @@ -5311,7 +5335,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); @@ -5337,9 +5363,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; @@ -5494,6 +5531,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 @@ -5508,6 +5546,7 @@ VOID WINAPI XTL::EMUPATCH(D3DResource_Register) CacheFormat = PCFormat; // Save this for later PCFormat = D3DFMT_A8R8G8B8; // ARGB } +#endif // OLD_COLOR_CONVERSION if(bCubemap) { @@ -5633,6 +5672,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) @@ -5690,6 +5762,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"); @@ -5730,7 +5803,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++) @@ -5757,26 +5829,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 } //__asm int 3; @@ -5786,6 +5838,7 @@ VOID WINAPI XTL::EMUPATCH(D3DResource_Register) // Flush unused data buffers free(pExpandedTexture); } +#endif // !OLD_COLOR_CONVERSION } } @@ -5899,7 +5952,7 @@ ULONG WINAPI XTL::EMUPATCH(D3DResource_AddRef) X_D3DResource *pThis ) { - FUNC_EXPORTS + // FUNC_EXPORTS LOG_FUNC_ONE_ARG(pThis); @@ -7883,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]; } } @@ -7944,7 +7997,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 @@ -9619,22 +9672,38 @@ 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++; + pRet->Common++; // EMUPATCH(D3DResource_AddRef)(pRet); } 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 5c1b73e67..68de8fcc2 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 @@ -73,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 @@ -559,7 +560,7 @@ HRESULT WINAPI EMUPATCH(D3DDevice_SetIndices) VOID WINAPI EMUPATCH(D3DDevice_SetTexture) ( DWORD Stage, - X_D3DResource *pTexture + X_D3DBaseTexture *pTexture ); // ****************************************************************** @@ -1735,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/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..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 @@ -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? 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; } } 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)); } diff --git a/src/CxbxKrnl/EmuKrnlHal.cpp b/src/CxbxKrnl/EmuKrnlHal.cpp index 7066e23ae..928172b02 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()); } @@ -534,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; } diff --git a/src/CxbxKrnl/EmuKrnlPs.cpp b/src/CxbxKrnl/EmuKrnlPs.cpp index 2641125cc..f7ff4c13c 100644 --- a/src/CxbxKrnl/EmuKrnlPs.cpp +++ b/src/CxbxKrnl/EmuKrnlPs.cpp @@ -132,9 +132,12 @@ static unsigned int WINAPI PCSTProxy StartSuspended, hStartedEvent); + // Do minimal thread initialization InitXboxThread(g_CPUXbox); + SetEvent(hStartedEvent); + if (StartSuspended == TRUE) // Suspend right before calling the thread notification routines SuspendThread(GetCurrentThread()); @@ -159,8 +162,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 +187,6 @@ static unsigned int WINAPI PCSTProxy callComplete: - if (hStartedEvent != NULL) { - CloseHandle(hStartedEvent); - } // This will also handle thread notification : xboxkrnl::PsTerminateSystemThread(STATUS_SUCCESS); @@ -301,6 +299,11 @@ 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(); @@ -309,45 +312,48 @@ 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"); + // Give the thread chance to start + Sleep(100); + + EmuWarning("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. + EmuWarning("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"); + EmuWarning("%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); + 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 - { - HANDLE hDupHandle = NULL; - - DuplicateHandle(g_CurrentProcessHandle, *ThreadHandle, g_CurrentProcessHandle, &hDupHandle, 0, FALSE, DUPLICATE_SAME_ACCESS); - - CxbxKrnlRegisterThread(hDupHandle); - } + CxbxKrnlRegisterThread(*ThreadHandle); if (ThreadId != NULL) *ThreadId = (xboxkrnl::HANDLE)dwThreadId; diff --git a/src/CxbxKrnl/EmuShared.h b/src/CxbxKrnl/EmuShared.h index adae9a307..b5ac99970 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, @@ -142,6 +149,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: // ****************************************************************** @@ -165,6 +196,8 @@ class EmuShared : public Mutex bool m_bMultiXbe; bool m_bDebugging; PAddr m_LaunchDataPAddress; + bool m_bLedHasChanged; + int m_LedSequence[4]; }; // ****************************************************************** 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, 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/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(); } diff --git a/src/CxbxKrnl/SMCDevice.cpp b/src/CxbxKrnl/SMCDevice.cpp index 18a708270..2520f24c7 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) @@ -153,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)