From 753d9d89c21217f3f188b7b359291dce66488ece Mon Sep 17 00:00:00 2001 From: ergo720 Date: Sun, 28 Jan 2018 10:06:11 +0100 Subject: [PATCH] Dashboard fatal error + fix issue #878 --- import/OpenXDK/include/xboxkrnl/xboxkrnl.h | 12 ++ resource/Cxbx.rc | Bin 12494 -> 27016 bytes src/Common/Xbe.cpp | 53 +++++++- src/Common/Xbe.h | 2 +- src/Cxbx/ResCxbx.h | 1 + src/Cxbx/WndMain.cpp | 2 +- src/CxbxKrnl/CxbxKrnl.cpp | 23 ++-- src/CxbxKrnl/CxbxKrnl.h | 2 +- src/CxbxKrnl/EmuD3D8.cpp | 147 ++++++++++----------- src/CxbxKrnl/EmuD3D8.h | 2 +- src/CxbxKrnl/EmuKrnlHal.cpp | 4 + 11 files changed, 151 insertions(+), 97 deletions(-) diff --git a/import/OpenXDK/include/xboxkrnl/xboxkrnl.h b/import/OpenXDK/include/xboxkrnl/xboxkrnl.h index 07616d4f4..9ee3acb04 100644 --- a/import/OpenXDK/include/xboxkrnl/xboxkrnl.h +++ b/import/OpenXDK/include/xboxkrnl/xboxkrnl.h @@ -1271,6 +1271,18 @@ typedef struct _LAUNCH_DATA_PAGE } LAUNCH_DATA_PAGE, *PLAUNCH_DATA_PAGE; +// ****************************************************************** +// * DASH_LAUNCH_DATA +// ****************************************************************** +typedef struct _DASH_LAUNCH_DATA +{ + DWORD dwReason; + DWORD dwContext; + DWORD dwParameter1; + DWORD dwParameter2; + BYTE Reserved[3072 - 16]; +} DASH_LAUNCH_DATA, *PDASH_LAUNCH_DATA; + // ****************************************************************** // * DISPATCHER_HEADER // ****************************************************************** diff --git a/resource/Cxbx.rc b/resource/Cxbx.rc index 2119e7eeee62d2b0d9c9c6fb1a2999ebf76c0129..cc0b630ce7574482bc41f60bb2a10b94a0e09d94 100644 GIT binary patch literal 27016 zcmd^|-Ev$<5yuZ)B~;}ZSmY`}3gN6ITXu3mm9+Y>V#yNPl@x=kge2RFuq+wLj-3?6 zEASv(bHNq2yaW`N@D3F4|4nae&exv(@Y#4xYU}9io{yRT^mO-h_weEP0k|)Wzj!RvCsqV!?RO*;%4$l@9_2`)$}Gg((x$S3FZ3l zo5`2SR49Y;ZiKg=hSI2UG1*SqNhjG&mXq~lD>=~HE4sR@?+=oV;H_(v=N; zcT^yoypN;vb0b+3HS&~yDwfH+S8d7At|Y9bnh(Tb8~RZ0@APT(e6yo6 zcEraAdh3DS|2WjTp{oycbyw%Lz^i`6o?BDd>yp=d$&AWw>$xRev3K%M9O$k|_6_MC zbkvEY<52G%OHSa016}9p6SZhoQgK^{;c#kBRv$YWN9X5;XhNILuk{#rigz2y>%a$a z#hIRet(ISj8+dqn(8cJE7y5RnQcbI)TQ9rMzSNryT|d`vv^-BA>UrK^)=^!cpo zNwj~z=luSZp0}~*X15h_yn(WeT~8}C3OaXBHQpB&FJJeC_uyomom2eWYvl0zoH=Gi z&0b>+_m|Z6HTBYi@N}fCjq!1mPml9uBmJYK*&XfC6-G_UXB-=){xZ8`Dk&e|reu3u z>NxKrh^^>_YJNmiy~?{0q~dYlH?JN3DI3R%T<3i?Ssa%}144fLxgow`v_ea~xW4M` zK<<|$_ZyO}H62coUgst8Uq_Z6V}7q^($}X{@`c8P3+b67VR(_UGaX?X{p5UibbiK? zN1whbrQwcf2vy*i&F&b?8#WqKM!EEEi{{%JS)t}sGA%pcR66=ePCClpbvk=3^vsIt zw34<&Yw$Lt&5!gAEpb!jGSXLn;E4kvSy$g-gMg5B9E7o9C8K@3q;d=`wFSS2G0jj6 zQa@$pF<@_R$^HNjBh*T0$C_-OMR^`RCO8^D7g15dw%*~rj!N7aqBU(v&{re0rP!Lb zYTpwQYl%~uo*BMHQ=&>1S3`WX7)JK~J)Wm?IkH97F&etT=$)4WydrERvtEpI8rQOM zm6Hzd?P@9Ur;0p*+%-k}&vayK-WLCw)%K=7UpJ2V5pdiZ1CCoG;J7^o9Jfcnu`mW43nSpTGX@-YM!<1* z3^?wNfaB9K;P|u@NAw-~Yqr5gfijJ_BHjEZ*sp_H4iQaWGc(>|Bc-)+u@(8TXhm8d z``P?eFTHxK$(G?3FynIC7Pl7l8}X}aay(_Un^tSFxG&^!5i9O*4R~p8v0zt0vFIP9 z?f(Pa+mtnh6_urGEXTf;qgzqWjuRdIU4^dL_l`T;f72?3D9mw)k`H1By-lAj%FeK8 zQX~0!vXC(H5Lxff|HkjJ&#-elio4uX|1HXX#)94tB~o5m3cTHZF7K~pS!74@e@+4- zi~03OMVVE|h@mgZ16ornx5RJd{zdP;Dq+hqHAS?xkrkWsfc*JXb`mGlr5!GAUR zDWlul^tXF_UVeZ7%zG(M)n!o;c{HyAPjpoj#mkA_Tp4;VuSiKO<8-gLL?d!gx<;?S$ly=mY zXi9YD;IXVcI`R>i!Hc6@9+S(AYn6WJ_Ja0V5w2>OJy5 z@c%&ED5cKm_*&w~9evPGF%7JX&TxPGg~>zqzL z7gu-0VQCtA3(L>Ftr{!!pj+m!y&f?!x3ya{CM$DvOlxDnWM!6N>dkdo?ztCq#IwS9 z={+~Pj#w5CUa9n>uH0?w_Z#u#nPjjnt#sIp#WPapdB-^9UeFQu!^nx&XJ&)!7UqA} z7b#J^lBEd|tLGZKm^tvwjjRT(rb@ZSv@9dyIFEF!Dz~QC zZpWNG_m&rO`p}!55$AT8d72iQ3ypAwYGGhhZbvX*nfFe>#hfGk+ABKNuNN4{;1-{6 zcAAVr`!%)DVgUTLT)-_w2C(jqb)X{|FW-n;-{{-EYCh7rt$XC)q&<7*O}KAcqt`vP zlpZHmLxxtFG!{8xFil^44}X49*vKa(qM4T*r&9Sjj~#h3|1pg^_RNQ&Wn`nJXQq+B zad zm+`x-u5wO?&dlzYc@JD&6=t{sjfwR{RtRXFBg#wlyY%0xWQ0rzvJpW^Y2`C2JG#Fn z2`D~4pUf*xnXcDsFwHPn`EVy56cUzyV^%d}=V!AV=k+!`;y8DaCj3 zTORAla~(Far76_Z$ZUBKt>%=PtHl>)koW<;0GKh&q`@*+4e0(m%V4}t$jmMVJnV0!K*)! z{y|R4=&&I!wXp^}bf??v^nSgVcGMRq>JjEm`lG@-$)hqJsTb95FjdM{o8n^vSTfjHt!V@{D8d0>I zz+_xgFQz5&OmEpHMro3bW~o!F#ArYn1=4=KaYnthJ3p8=%)I$gDW{@Q?nzq6Hi%qN zFP6v){m`IE(rAny>P6E_cerdENOO?I%t$_`krnNM&0ODjQ>8f~3Vg@4E{eOsTB#R> zb4VF?=22ilIW6kd>5(_8aaf-i4x>iBIC^nK)K6u6QLm<|;)^tnB4^Z#qlz<%IMTdP zucTJKJsRixJYEy$ep#c5*S3+8o>}<@b2aJ`Vui;67i-Pa zGSnLxV;;Eh50PuvE{@DJUbTNj%$K<0c8D()*CI{{7hazE)2weInn@g*+@v&48wv4L zTLBH)7F2V=i@MeIl-)1uUoU?AN$@2s<~vNyw{vx8<0Sp-&bFC2w2i#1^CS-aOt$M! z#1CfiGiR5!VTtrdI?Tx$GFqVbvDJpB#b9`%ob^M57i}~G6MTG2DARs(OD!PwLF}UJ zGbN5WQ~M9a17RUgSEABM*!xfF2Y)% z7~6M$*5WuWsm_5!7vMaoJ{LH_Vx0DSMt3d4BgSFKt+hFUnQq*LwiCsPeMuxeKWorG zy1?wabBwJ%HY&t;3v`0R&vYgu#xfYH+saHf^YJ$4j`dI5OzvrMRb(W_2GbF-V$8K) z9E^x4b~cen>ZCO2HE0~nGEiy3s#>!cB3Y9WCyN<6?;<(|PuuPuM2m|W*?E6YdY0@$ zW?Q#IwS{(rzHsKw46>NoEE$Fw%iI*Gpm*{ z79gug>$lMtM4c^zt*FtbWCNJ)CeMKA?(1+yJEi4eQ@WV!we*PB(i22qnOkO_A3j;p zhxw?fjK#oP7ON#c434qPB7Aq}_89xla+cHYj%YR`8s61ksF&xs>Q=4_zwhn?Pk$|q zdtA~Q?mY~4U%hRZ6>enFTCpGfM~H2Ay1DF^+mGF?N!5&w@sTP zVCZkBVIz{ub}Xv_?NP0-d)a7M$Y!e=ZH%{!Pt&tCX-*^FQf(huR*mgN^0kmHh8YvA zd!oXhWq2-aXMn{t1GsLBQ)U9Mqa|!k$ZV77Hw}*~OEa>uzY12$lL2sHON|3pTFY2Y zAlbWk8@3}$HN}uA_Q2sUnt`J(ifsu4nJ8pXveMrXT~$)cEKiej)A@sA%Fa)gY3mi~ zt(dV@)Y%WEU-trDR?%OIl80d@nxft&D{DuxvmeeY(t5mEuhz3s-2GD`P;j}~jOF%d z%pdj~fbXt78nd&j^&5Ji{@L0=?NKy7_NV84Po6DWZ5d=GYFn+@%;;!qpIsk^bl50e zZV?Qt557=8FvC^ehVEyu!4cyA~U^E$jgIOoz?VnFL^gX00~son6^I_jQ;b zW05@aWr#?P!xCk@8PyVXdz&cIiL~>v^fOk1uf!n#y*T4#?If)bJOx(9? zZ#IV)yQ-g6ZdO4#Ek?Izt+nsgo;3{oO~+ctZ_l>H@wW40wbuW3t=cqyPKrf4ntf(g z_Hfp0)>dJ>&F801&TmKO=Z4m5u(y=unC7$M*i*~z6Zf=;5?NZVx8vELi&v_@O{qNd zgV@#cX7U^TI*~pG8AtCNMaJZ}-w$+h`XrCUDd2sSzdsqj9i5-a+p)dRm=C!OQR`x^ zB|a@aDk~~2lEbJ)8QH8r;+e$bz03`9#>1fd@VD3>;38!Dx z?7e*6J*Xu=KjAU2_-(PnBJq;y*mf3=HmHA3@B>7Su<%XV# z`;+2F^EWQ11xa}B-EZ}z(&`sncl zyUM=4@DlSxm*GvGcoKM°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 diff --git a/src/Common/Xbe.cpp b/src/Common/Xbe.cpp index 4b91fcaa5..904bcb849 100644 --- a/src/Common/Xbe.cpp +++ b/src/Common/Xbe.cpp @@ -33,15 +33,28 @@ // * All rights reserved // * // ****************************************************************** +#define _XBOXKRNL_DEFEXTRN_ + +// prevent name collisions +namespace xboxkrnl +{ + #include +}; + #include "Xbe.h" #include "CxbxUtil.h" // For RoundUp - +#include // filesystem related functions available on C++ 17 #include // For ctime +#include "devices\LED.h" // For LED::Sequence +#include "CxbxKrnl/CxbxKrnl.h" // For CxbxKrnlPrintUEM +#include "CxbxKrnl/EmuShared.h" // Include this to avoid including EmuXapi.h and EmuD3D8.h + +namespace fs = std::experimental::filesystem; + -#define PAGE_SIZE 0x1000 // construct via Xbe file -Xbe::Xbe(const char *x_szFilename) +Xbe::Xbe(const char *x_szFilename, bool bFromGUI) { char szBuffer[MAX_PATH]; @@ -54,8 +67,38 @@ Xbe::Xbe(const char *x_szFilename) // verify Xbe file was opened successfully if(XbeFile == 0) { - SetFatalError("Could not open Xbe file."); - return; + using namespace fs; // limit its scope inside here + + std::string XbeName = path(x_szFilename).filename().string(); // recover the xbe name + + // NOTE: the check for the existence of the child window is necessary because the user could have previously loaded the dashboard, + // removed/changed the path and attempt to load it again from the recent list, which will crash CxbxInitWindow below + // Note that GetHwnd(), CxbxKrnl_hEmuParent and HalReturnToFirmware are all not suitable here for various reasons + if (XbeName.compare(std::string("xboxdash.xbe")) == 0 && !bFromGUI) + { + // The dashboard could not be found on partition2. This is a fatal error on the Xbox so we display the UEM. The + // error code is different if we have a launch data page + + XTL::CxbxInitWindow(false); + + ULONG FatalErrorCode = FATAL_ERROR_XBE_DASH_GENERIC; + + if (xboxkrnl::LaunchDataPage && xboxkrnl::LaunchDataPage->Header.dwLaunchDataType == LDT_FROM_DASHBOARD) + { + xboxkrnl::PDASH_LAUNCH_DATA pLaunchDashboard = (xboxkrnl::PDASH_LAUNCH_DATA)&(xboxkrnl::LaunchDataPage->LaunchData[0]); + FatalErrorCode += pLaunchDashboard->dwReason; + } + SetLEDSequence(0xE1); // green, red, red, red + CxbxKrnlPrintUEM(FatalErrorCode); // won't return + + // TODO: FATAL_ERROR_XBE_DASH_X2_PASS (requires DVD drive authentication emulation...) + } + else + { + // Report which xbe could not be found + SetFatalError(std::string("Could not open the Xbe file ") + XbeName); + return; + } } printf("OK\n"); diff --git a/src/Common/Xbe.h b/src/Common/Xbe.h index f6b0e6f27..088dc276f 100644 --- a/src/Common/Xbe.h +++ b/src/Common/Xbe.h @@ -51,7 +51,7 @@ class Xbe : public Error { public: // construct via Xbe file - Xbe(const char *x_szFilename); + Xbe(const char *x_szFilename, bool bFromGUI); // deconstructor ~Xbe(); diff --git a/src/Cxbx/ResCxbx.h b/src/Cxbx/ResCxbx.h index 70b20c4e2..d18c0d8f9 100644 --- a/src/Cxbx/ResCxbx.h +++ b/src/Cxbx/ResCxbx.h @@ -14,6 +14,7 @@ #define IDD_ABOUT 119 #define IDR_CONTRIBUTORS 121 #define IDR_COPYING 122 +#define IDS_UEM 123 #define IDC_SET_X 1000 #define IDC_SET_Y 1001 #define IDC_SET_A 1002 diff --git a/src/Cxbx/WndMain.cpp b/src/Cxbx/WndMain.cpp index 56a34bfa0..48b997715 100644 --- a/src/Cxbx/WndMain.cpp +++ b/src/Cxbx/WndMain.cpp @@ -1786,7 +1786,7 @@ void WndMain::OpenXbe(const char *x_filename) strcpy(m_XbeFilename, x_filename); - m_Xbe = new Xbe(m_XbeFilename); + m_Xbe = new Xbe(m_XbeFilename, true); if(m_Xbe->HasError()) { diff --git a/src/CxbxKrnl/CxbxKrnl.cpp b/src/CxbxKrnl/CxbxKrnl.cpp index 9f99cfb38..91aefb75a 100644 --- a/src/CxbxKrnl/CxbxKrnl.cpp +++ b/src/CxbxKrnl/CxbxKrnl.cpp @@ -571,6 +571,9 @@ void CxbxKrnlMain(int argc, char* argv[]) } } + // We must save this handle now to keep the child window working in the case we need to display the UEM + CxbxKrnl_hEmuParent = IsWindow(hWnd) ? hWnd : NULL; + g_CurrentProcessHandle = GetCurrentProcess(); // OpenProcess(PROCESS_ALL_ACCESS, FALSE, GetCurrentProcessId()); // Write a header to the log @@ -600,6 +603,7 @@ void CxbxKrnlMain(int argc, char* argv[]) g_IsWine = true; } } + // Now we got the arguments, start by initializing the Xbox memory map : // PrepareXBoxMemoryMap() { @@ -670,7 +674,7 @@ void CxbxKrnlMain(int argc, char* argv[]) { // Load Xbe (this one will reside above WinMain's virtual_memory_placeholder) g_EmuShared->SetXbePath(xbePath.c_str()); - CxbxKrnl_Xbe = new Xbe(xbePath.c_str()); // TODO : Instead of using the Xbe class, port Dxbx _ReadXbeBlock() + CxbxKrnl_Xbe = new Xbe(xbePath.c_str(), false); // TODO : Instead of using the Xbe class, port Dxbx _ReadXbeBlock() if (CxbxKrnl_Xbe->HasFatalError()) { CxbxKrnlCleanup(CxbxKrnl_Xbe->GetError().c_str()); @@ -740,7 +744,6 @@ void CxbxKrnlMain(int argc, char* argv[]) EntryPoint ^= XOR_EP_KEY[g_XbeType]; // Launch XBE CxbxKrnlInit( - hWnd, XbeTlsData, XbeTls, CxbxKrnl_Xbe->m_LibraryVersion, @@ -790,7 +793,6 @@ void LoadXboxKeys(std::string path) __declspec(noreturn) void CxbxKrnlInit ( - HWND hwndParent, void *pTLSData, Xbe::TLS *pTLS, Xbe::LibraryVersion *pLibraryVersion, @@ -804,7 +806,6 @@ __declspec(noreturn) void CxbxKrnlInit CxbxKrnl_TLS = pTLS; CxbxKrnl_TLSData = pTLSData; CxbxKrnl_XbeHeader = pXbeHeader; - CxbxKrnl_hEmuParent = IsWindow(hwndParent) ? hwndParent : NULL; CxbxKrnl_DebugMode = DbgMode; CxbxKrnl_DebugFileName = (char*)szDebugFilename; @@ -837,7 +838,7 @@ __declspec(noreturn) void CxbxKrnlInit " pXBEHeaderSize : 0x%.08X\n" " Entry : 0x%.08X\n" ");\n", - GetCurrentThreadId(), hwndParent, pTLSData, pTLS, pLibraryVersion, DbgMode, szDebugFilename, pXbeHeader, dwXbeHeaderSize, Entry); + GetCurrentThreadId(), CxbxKrnl_hEmuParent, pTLSData, pTLS, pLibraryVersion, DbgMode, szDebugFilename, pXbeHeader, dwXbeHeaderSize, Entry); #else printf("[0x%X] INIT: Debug Trace Disabled.\n", GetCurrentThreadId()); #endif @@ -1008,7 +1009,7 @@ __declspec(noreturn) void CxbxKrnlInit // initialize grapchics DbgPrintf("INIT: Initializing render window.\n"); - XTL::CxbxInitWindow(pXbeHeader, dwXbeHeaderSize); + XTL::CxbxInitWindow(true); // Now process the boot flags to see if there are any special conditions to handle int BootFlags = 0; @@ -1296,6 +1297,11 @@ void CxbxKrnlPrintUEM(ULONG ErrorCode) xboxkrnl::XBOX_EEPROM Eeprom; ULONG ResultSize; + int BootFlags; + g_EmuShared->GetBootFlags(&BootFlags); + BootFlags &= ~BOOT_FATAL_ERROR; // clear the fatal error flag to avoid looping here endlessly + g_EmuShared->SetBootFlags(&BootFlags); + NTSTATUS status = xboxkrnl::ExQueryNonVolatileSetting(xboxkrnl::XC_MAX_ALL, &Type, &Eeprom, sizeof(Eeprom), &ResultSize); if (status == STATUS_SUCCESS) @@ -1329,11 +1335,6 @@ void CxbxKrnlPrintUEM(ULONG ErrorCode) g_CxbxFatalErrorCode = ErrorCode; g_CxbxPrintUEM = true; // print the UEM - int BootFlags; - g_EmuShared->GetBootFlags(&BootFlags); - BootFlags ^= BOOT_FATAL_ERROR; // clear the fatal error flag to avoid looping here endlessly - g_EmuShared->SetBootFlags(&BootFlags); - // Sleep forever to prevent continuing the initialization Sleep(INFINITE); } diff --git a/src/CxbxKrnl/CxbxKrnl.h b/src/CxbxKrnl/CxbxKrnl.h index ed34fd26a..26931420b 100644 --- a/src/CxbxKrnl/CxbxKrnl.h +++ b/src/CxbxKrnl/CxbxKrnl.h @@ -177,7 +177,7 @@ bool CxbxKrnlVerifyVersion(const char *szVersion); void CxbxKrnlMain(int argc, char* argv[]); /*! initialize emulation */ -__declspec(noreturn) void CxbxKrnlInit(HWND hwndParent, void *pTLSData, Xbe::TLS *pTLS, Xbe::LibraryVersion *LibraryVersion, DebugMode DbgMode, const char *szDebugFilename, Xbe::Header *XbeHeader, uint32 XbeHeaderSize, void (*Entry)()); +__declspec(noreturn) void CxbxKrnlInit(void *pTLSData, Xbe::TLS *pTLS, Xbe::LibraryVersion *LibraryVersion, DebugMode DbgMode, const char *szDebugFilename, Xbe::Header *XbeHeader, uint32 XbeHeaderSize, void (*Entry)()); /*! cleanup emulation */ __declspec(noreturn) void CxbxKrnlCleanup(const char *szErrorMessage, ...); diff --git a/src/CxbxKrnl/EmuD3D8.cpp b/src/CxbxKrnl/EmuD3D8.cpp index 7d832b6b1..918dd6cd8 100644 --- a/src/CxbxKrnl/EmuD3D8.cpp +++ b/src/CxbxKrnl/EmuD3D8.cpp @@ -57,6 +57,7 @@ namespace xboxkrnl #include "Logging.h" #include "EmuD3D8Logging.h" #include "HLEIntercept.h" // for bLLE_GPU +#include "Cxbx\\ResCxbx.h" #include #include @@ -97,8 +98,6 @@ static XTL::DDCAPS g_DriverCaps = { 0 }; static DWORD g_dwOverlayW = 640; // Cached Overlay Width static DWORD g_dwOverlayH = 480; // Cached Overlay Height static DWORD g_dwOverlayP = 640; // Cached Overlay Pitch -static Xbe::Header *g_XbeHeader = NULL; // XbeHeader -static uint32 g_XbeHeaderSize = 0; // XbeHeaderSize static HBRUSH g_hBgBrush = NULL; // Background Brush static volatile bool g_bRenderWindowActive = false; static XBVideo g_XBVideo; @@ -452,18 +451,15 @@ const char *D3DErrorString(HRESULT hResult) return buffer; } -VOID XTL::CxbxInitWindow(Xbe::Header *XbeHeader, uint32 XbeHeaderSize) +VOID XTL::CxbxInitWindow(bool bFullInit) { g_EmuShared->GetXBVideo(&g_XBVideo); if(g_XBVideo.GetFullscreen()) CxbxKrnl_hEmuParent = NULL; - // cache XbeHeader and size of XbeHeader - g_XbeHeader = XbeHeader; - g_XbeHeaderSize = XbeHeaderSize; - // create timing thread + if (bFullInit) { DWORD dwThreadId; @@ -499,7 +495,8 @@ VOID XTL::CxbxInitWindow(Xbe::Header *XbeHeader, uint32 XbeHeaderSize) // Ported from Dxbx : // If possible, assign this thread to another core than the one that runs Xbox1 code : - SetThreadAffinityMask(hRenderWindowThread, g_CPUOthers); + if (bFullInit) + SetThreadAffinityMask(hRenderWindowThread, g_CPUOthers); while(!g_bRenderWindowActive) SwitchToThread(); @@ -510,6 +507,70 @@ VOID XTL::CxbxInitWindow(Xbe::Header *XbeHeader, uint32 XbeHeaderSize) SetFocus(g_hEmuWindow); } +void DrawUEM(HWND hWnd) +{ + // Draw the universal error message (UEM) + // See http://xboxdevwiki.net/Fatal_Error + // Only call this from WM_PAINT message! + + PAINTSTRUCT ps; + + BeginPaint(hWnd, &ps); + + HDC hDC = GetDC(hWnd); + HDC hMemDC = CreateCompatibleDC(hDC); + HBITMAP hUEMBmp = CreateCompatibleBitmap(hDC, 640, 480); + HBITMAP hOriUEMBmp = (HBITMAP)SelectObject(hMemDC, hUEMBmp); + + + int nHeight = -MulDiv(8, GetDeviceCaps(hMemDC, LOGPIXELSY), 72); + + HFONT hFont = CreateFont(nHeight, 0, 0, 0, FW_NORMAL, FALSE, FALSE, FALSE, DEFAULT_CHARSET, OUT_DEFAULT_PRECIS, CLIP_DEFAULT_PRECIS, ANTIALIASED_QUALITY, FF_ROMAN, "Verdana"); + + HGDIOBJ tmpObj = SelectObject(hMemDC, hFont); + + SetBkColor(hMemDC, RGB(0, 0, 0)); + + SetTextColor(hMemDC, RGB(0, 204, 0)); + + wchar_t buff[500]; + LoadStringW(GetModuleHandle(NULL), IDS_UEM, buff, sizeof(buff) / sizeof(wchar_t)); + std::wstring wstr(buff); + + // Unfortunately, DrawTextW doesn't support vertical alignemnt, so we have to do the calculation + // ourselves. See here: https://social.msdn.microsoft.com/Forums/vstudio/en-US/abd89aae-16a0-41c6-8db6-b119ea90b42a/win32-drawtext-how-center-in-vertical-with-new-lines-and-tabs?forum=vclanguage + + RECT rect = { 0, 0, 640, 480 }; + RECT textrect = { 0, 0, 640, 480 }; + DrawTextW(hMemDC, wstr.c_str(), wstr.length(), &textrect, DT_CALCRECT); + rect.top = (rect.bottom - textrect.bottom) / 2; + DrawTextW(hMemDC, wstr.c_str(), wstr.length(), &rect, DT_CENTER); + + + // Draw the Xbox error code + + SetTextColor(hMemDC, RGB(255, 255, 255)); + std::string err_str(std::to_string(g_CxbxFatalErrorCode)); + rect.left = 20; + DrawText(hMemDC, err_str.c_str(), err_str.length(), &rect, DT_LEFT); + + GetClientRect(hWnd, &rect); + SetStretchBltMode(hDC, COLORONCOLOR); + StretchBlt(hDC, rect.left, rect.top, rect.right, rect.bottom, hMemDC, 0, 0, 640, 480, SRCCOPY); + + SelectObject(hMemDC, hOriUEMBmp); + SelectObject(hDC, tmpObj); + + DeleteObject(hUEMBmp); + DeleteObject(hFont); + DeleteObject(hMemDC); + + if (hDC != NULL) + ReleaseDC(hWnd, hDC); + + EndPaint(hWnd, &ps); +} + inline DWORD GetXboxCommonResourceType(const XTL::X_D3DResource *pXboxResource) { // Don't pass in unassigned Xbox resources @@ -1369,75 +1430,7 @@ static LRESULT WINAPI EmuMsgProc(HWND hWnd, UINT msg, WPARAM wParam, LPARAM lPar { if (g_CxbxPrintUEM) { - // Draw the universal error message (UEM) - // See http://xboxdevwiki.net/Fatal_Error - - PAINTSTRUCT ps; - - BeginPaint(hWnd, &ps); - - HDC hDC = GetDC(hWnd); - HDC hMemDC = CreateCompatibleDC(hDC); - HBITMAP hUEMBmp = CreateCompatibleBitmap(hDC, 640, 480); - HBITMAP hOriUEMBmp = (HBITMAP)SelectObject(hMemDC, hUEMBmp); - - - int nHeight = -MulDiv(8, GetDeviceCaps(hMemDC, LOGPIXELSY), 72); - - HFONT hFont = CreateFont(nHeight, 0, 0, 0, FW_NORMAL, FALSE, FALSE, FALSE, DEFAULT_CHARSET, OUT_DEFAULT_PRECIS, CLIP_DEFAULT_PRECIS, ANTIALIASED_QUALITY, FF_ROMAN, "Verdana"); - - HGDIOBJ tmpObj = SelectObject(hMemDC, hFont); - - SetBkColor(hMemDC, RGB(0, 0, 0)); - - SetTextColor(hMemDC, RGB(0, 204, 0)); - - std::wstring wstr( - L"Your Xbox requires service.\n\n\ -Please call Xbox Customer Support.\n\n\n\ -Ihre Xbox muss gewartet werden.\n\n\ -Bitte den Xbox-Kundendienst anrufen.\n\n\n\ -La consola Xbox requiere asistencia técnica.\n\n\ -Llame al servicio de soporte al cliente de la Xbox.\n\n\n\ -Xbox ha bisogno di manutenzione.\n\n\ -Chiamare l'Assistenza Clienti di Xbox.\n\n\n\ -Votre Xbox ne fonctionne pas correctement.\n\n\ -Veuillez contacter le Support à la clientèle Xbox.\n\n\n\ -不具合が生じました。お手数ですが、\n\n\ -Xboxカスタマー サポートにお問い合わせください。"); - - // Unfortunately, DrawTextW doesn't support vertical alignemnt, so we have to do the calculation - // ourselves. See here: https://social.msdn.microsoft.com/Forums/vstudio/en-US/abd89aae-16a0-41c6-8db6-b119ea90b42a/win32-drawtext-how-center-in-vertical-with-new-lines-and-tabs?forum=vclanguage - - RECT rect = { 0, 0, 640, 480 }; - RECT textrect = { 0, 0, 640, 480 }; - DrawTextW(hMemDC, wstr.c_str(), wstr.length(), &textrect, DT_CALCRECT); - rect.top = (rect.bottom - textrect.bottom) / 2; - DrawTextW(hMemDC, wstr.c_str(), wstr.length(), &rect, DT_CENTER); - - - // Draw the Xbox error code - - SetTextColor(hMemDC, RGB(255, 255, 255)); - std::string err_str(std::to_string(g_CxbxFatalErrorCode)); - rect.left = 20; - DrawText(hMemDC, err_str.c_str(), err_str.length(), &rect, DT_LEFT); - - GetClientRect(hWnd, &rect); - SetStretchBltMode(hDC, COLORONCOLOR); - StretchBlt(hDC, rect.left, rect.top, rect.right, rect.bottom, hMemDC, 0, 0, 640, 480, SRCCOPY); - - SelectObject(hMemDC, hOriUEMBmp); - SelectObject(hDC, tmpObj); - - DeleteObject(hUEMBmp); - DeleteObject(hFont); - DeleteObject(hMemDC); - - if (hDC != NULL) - ReleaseDC(hWnd, hDC); - - EndPaint(hWnd, &ps); + DrawUEM(hWnd); } } break; diff --git a/src/CxbxKrnl/EmuD3D8.h b/src/CxbxKrnl/EmuD3D8.h index 68de8fcc2..596b6faba 100644 --- a/src/CxbxKrnl/EmuD3D8.h +++ b/src/CxbxKrnl/EmuD3D8.h @@ -43,7 +43,7 @@ #include // initialize render window -extern VOID CxbxInitWindow(Xbe::Header *XbeHeader, uint32 XbeHeaderSize); +extern VOID CxbxInitWindow(bool bFullInit); extern VOID CxbxSetPixelContainerHeader ( diff --git a/src/CxbxKrnl/EmuKrnlHal.cpp b/src/CxbxKrnl/EmuKrnlHal.cpp index e74a2ec57..d4593bed8 100644 --- a/src/CxbxKrnl/EmuKrnlHal.cpp +++ b/src/CxbxKrnl/EmuKrnlHal.cpp @@ -507,7 +507,11 @@ XBSYSAPI EXPORTNUM(49) xboxkrnl::VOID DECLSPEC_NORETURN NTAPI xboxkrnl::HalRetur g_EmuShared->GetXbePath(szWorkingDirectoy); snprintf(szArgsBuffer, 4096, "/load \"%s\" %u %d \"%s\"", szWorkingDirectoy, CxbxKrnl_hEmuParent, CxbxKrnl_DebugMode, CxbxKrnl_DebugFileName.c_str()); if ((int)ShellExecute(NULL, "open", szFilePath_CxbxReloaded_Exe, szArgsBuffer, szWorkingDirectoy, SW_SHOWDEFAULT) <= 32) + { + int BootFlags = 0; + g_EmuShared->SetBootFlags(&BootFlags); // clear all boot flags in the case of failure CxbxKrnlCleanup("Could not reboot"); + } break; }