diff options
Diffstat (limited to 'board/MAI/bios_emulator/scitech/src/pm/win32/ddraw.c')
-rw-r--r-- | board/MAI/bios_emulator/scitech/src/pm/win32/ddraw.c | 583 |
1 files changed, 583 insertions, 0 deletions
diff --git a/board/MAI/bios_emulator/scitech/src/pm/win32/ddraw.c b/board/MAI/bios_emulator/scitech/src/pm/win32/ddraw.c new file mode 100644 index 00000000000..cf89401fe64 --- /dev/null +++ b/board/MAI/bios_emulator/scitech/src/pm/win32/ddraw.c @@ -0,0 +1,583 @@ +/**************************************************************************** +* +* SciTech Multi-platform Graphics Library +* +* ======================================================================== +* +* The contents of this file are subject to the SciTech MGL Public +* License Version 1.0 (the "License"); you may not use this file +* except in compliance with the License. You may obtain a copy of +* the License at http://www.scitechsoft.com/mgl-license.txt +* +* Software distributed under the License is distributed on an +* "AS IS" basis, WITHOUT WARRANTY OF ANY KIND, either express or +* implied. See the License for the specific language governing +* rights and limitations under the License. +* +* The Original Code is Copyright (C) 1991-1998 SciTech Software, Inc. +* +* The Initial Developer of the Original Code is SciTech Software, Inc. +* All Rights Reserved. +* +* ======================================================================== +* +* Language: ANSI C +* Environment: Win32 +* +* Description: Win32 implementation for the SciTech cross platform +* event library. +* +****************************************************************************/ + +#include "event.h" +#include "pmapi.h" +#include "win32/oshdr.h" +#include "nucleus/graphics.h" + +/*---------------------------- Global Variables ---------------------------*/ + +/* Publicly accessible variables */ + +int _PM_deskX,_PM_deskY;/* Desktop dimentions */ +HWND _PM_hwndConsole; /* Window handle for console */ +#ifdef __INTEL__ +uint _PM_cw_default; /* Default FPU control word */ +#endif + +/* Private internal variables */ + +static HINSTANCE hInstApp = NULL;/* Application instance handle */ +static HWND hwndUser = NULL;/* User window handle */ +static HINSTANCE hInstDD = NULL; /* Handle to DirectDraw DLL */ +static LPDIRECTDRAW lpDD = NULL; /* DirectDraw object */ +static LONG oldWndStyle; /* Info about old user window */ +static LONG oldExWndStyle; /* Info about old user window */ +static int oldWinPosX; /* Old window position X coordinate */ +static int oldWinPosY; /* Old window pisition Y coordinate */ +static int oldWinSizeX; /* Old window size X */ +static int oldWinSizeY; /* Old window size Y */ +static WNDPROC oldWinProc = NULL; +static PM_saveState_cb suspendApp = NULL; +static ibool waitActive = false; +static ibool isFullScreen = false; +static ibool backInGDI = false; + +/* Internal strings */ + +static char *szWinClassName = "SciTechDirectDrawWindow"; +static char *szAutoPlayKey = "Software\\Microsoft\\Windows\\CurrentVersion\\Policies\\Explorer"; +static char *szAutoPlayValue = "NoDriveTypeAutoRun"; + +/* Dynalinks to DirectDraw functions */ + +static HRESULT (WINAPI *pDirectDrawCreate)(GUID FAR *lpGUID, LPDIRECTDRAW FAR *lplpDD, IUnknown FAR *pUnkOuter); + +/*---------------------------- Implementation -----------------------------*/ + +/**************************************************************************** +REMARKS: +Temporarily disables AutoPlay operation while we are running in fullscreen +graphics modes. +****************************************************************************/ +static void DisableAutoPlay(void) +{ + DWORD dwAutoPlay,dwSize = sizeof(dwAutoPlay); + HKEY hKey; + + if (RegOpenKeyEx(HKEY_CURRENT_USER,szAutoPlayKey,0,KEY_EXECUTE | KEY_WRITE,&hKey) == ERROR_SUCCESS) { + RegQueryValueEx(hKey,szAutoPlayValue,NULL,NULL,(void*)&dwAutoPlay,&dwSize); + dwAutoPlay |= AUTOPLAY_DRIVE_CDROM; + RegSetValueEx(hKey,szAutoPlayValue,0,REG_DWORD,(void*)&dwAutoPlay,dwSize); + RegCloseKey(hKey); + } +} + +/**************************************************************************** +REMARKS: +Re-enables AutoPlay operation when we return to regular GDI mode. +****************************************************************************/ +static void RestoreAutoPlay(void) +{ + DWORD dwAutoPlay,dwSize = sizeof(dwAutoPlay); + HKEY hKey; + + if (RegOpenKeyEx(HKEY_CURRENT_USER,szAutoPlayKey,0,KEY_EXECUTE | KEY_WRITE,&hKey) == ERROR_SUCCESS) { + RegQueryValueEx(hKey,szAutoPlayValue,NULL,NULL,(void*)&dwAutoPlay,&dwSize); + dwAutoPlay &= ~AUTOPLAY_DRIVE_CDROM; + RegSetValueEx(hKey,szAutoPlayValue,0,REG_DWORD,(void*)&dwAutoPlay,dwSize); + RegCloseKey(hKey); + } +} + +/**************************************************************************** +REMARKS: +Suspends the application by switching back to the GDI desktop, allowing +normal application code to be processed, and then waiting for the +application activate command to bring us back to fullscreen mode with our +window minimised. +****************************************************************************/ +static void LeaveFullScreen(void) +{ + int retCode = PM_SUSPEND_APP; + + if (backInGDI) + return; + if (suspendApp) + retCode = suspendApp(PM_DEACTIVATE); + RestoreAutoPlay(); + backInGDI = true; + + /* Now process messages normally until we are re-activated */ + waitActive = true; + if (retCode != PM_NO_SUSPEND_APP) { + while (waitActive) { + _EVT_pumpMessages(); + Sleep(200); + } + } +} + +/**************************************************************************** +REMARKS: +Reactivate all the surfaces for DirectDraw and set the system back up for +fullscreen rendering. +****************************************************************************/ +static void RestoreFullScreen(void) +{ + static ibool firstTime = true; + + if (firstTime) { + /* Clear the message queue while waiting for the surfaces to be + * restored. + */ + firstTime = false; + while (1) { + /* Continue looping until out application has been restored + * and we have reset the display mode. + */ + _EVT_pumpMessages(); + if (GetActiveWindow() == _PM_hwndConsole) { + if (suspendApp) + suspendApp(PM_REACTIVATE); + DisableAutoPlay(); + backInGDI = false; + waitActive = false; + firstTime = true; + return; + } + Sleep(200); + } + } +} + +/**************************************************************************** +REMARKS: +This function suspends the application by switching back to the GDI desktop, +allowing normal application code to be processed and then waiting for the +application activate command to bring us back to fullscreen mode with our +window minimised. + +This version only gets called if we have not captured the screen switch in +our activate message loops and will occur if the DirectDraw drivers lose a +surface for some reason while rendering. This should not normally happen, +but it is included just to be sure (it can happen on WinNT/2000 if the user +hits the Ctrl-Alt-Del key combination). Note that this code will always +spin loop, and we cannot disable the spin looping from this version (ie: +if the user hits Ctrl-Alt-Del under WinNT/2000 the application main loop +will cease to be executed until the user switches back to the application). +****************************************************************************/ +void PMAPI PM_doSuspendApp(void) +{ + static ibool firstTime = true; + + /* Call system DLL version if found */ + if (_PM_imports.PM_doSuspendApp != PM_doSuspendApp) { + _PM_imports.PM_doSuspendApp(); + return; + } + + if (firstTime) { + if (suspendApp) + suspendApp(PM_DEACTIVATE); + RestoreAutoPlay(); + firstTime = false; + backInGDI = true; + } + RestoreFullScreen(); + firstTime = true; +} + +/**************************************************************************** +REMARKS: +Main Window proc for the full screen DirectDraw Window that we create while +running in full screen mode. Here we capture all mouse and keyboard events +for the window and plug them into our event queue. +****************************************************************************/ +static LONG CALLBACK PM_winProc( + HWND hwnd, + UINT msg, + WPARAM wParam, + LONG lParam) +{ + switch (msg) { + case WM_SYSCHAR: + /* Stop Alt-Space from pausing our application */ + return 0; + case WM_KEYDOWN: + case WM_SYSKEYDOWN: + if (HIWORD(lParam) & KF_REPEAT) { + if (msg == WM_SYSKEYDOWN) + return 0; + break; + } + /* Fall through for keydown events */ + case WM_KEYUP: + case WM_SYSKEYUP: + if (msg == WM_SYSKEYDOWN || msg == WM_SYSKEYUP) { + if ((HIWORD(lParam) & KF_ALTDOWN) && wParam == VK_RETURN) + break; + /* We ignore the remainder of the system keys to stop the + * system menu from being activated from the keyboard and pausing + * our app while fullscreen (ie: pressing the Alt key). + */ + return 0; + } + break; + case WM_SYSCOMMAND: + switch (wParam & ~0x0F) { + case SC_SCREENSAVE: + case SC_MONITORPOWER: + /* Ignore screensaver requests in fullscreen modes */ + return 0; + } + break; + case WM_SIZE: + if (waitActive && backInGDI && (wParam != SIZE_MINIMIZED)) { + /* Start the re-activation process */ + PostMessage(hwnd,WM_DO_SUSPEND_APP,WM_PM_RESTORE_FULLSCREEN,0); + } + else if (!waitActive && isFullScreen && !backInGDI && (wParam == SIZE_MINIMIZED)) { + /* Start the de-activation process */ + PostMessage(hwnd,WM_DO_SUSPEND_APP,WM_PM_LEAVE_FULLSCREEN,0); + } + break; + case WM_DO_SUSPEND_APP: + switch (wParam) { + case WM_PM_RESTORE_FULLSCREEN: + RestoreFullScreen(); + break; + case WM_PM_LEAVE_FULLSCREEN: + LeaveFullScreen(); + break; + } + return 0; + } + if (oldWinProc) + return oldWinProc(hwnd,msg,wParam,lParam); + return DefWindowProc(hwnd,msg,wParam,lParam); +} + +/**************************************************************************** +PARAMETERS: +hwnd - User window to convert +width - Window of the fullscreen window +height - Height of the fullscreen window + +RETURNS: +Handle to converted fullscreen Window. + +REMARKS: +This function takes the original user window handle and modifies the size, +position and attributes for the window to convert it into a fullscreen +window that we can use. +****************************************************************************/ +static PM_HWND _PM_convertUserWindow( + HWND hwnd, + int width, + int height) +{ + RECT window; + + GetWindowRect(hwnd,&window); + oldWinPosX = window.left; + oldWinPosY = window.top; + oldWinSizeX = window.right - window.left; + oldWinSizeY = window.bottom - window.top; + oldWndStyle = SetWindowLong(hwnd,GWL_STYLE,WS_POPUP | WS_SYSMENU); + oldExWndStyle = SetWindowLong(hwnd,GWL_EXSTYLE,WS_EX_APPWINDOW); + ShowWindow(hwnd,SW_SHOW); + MoveWindow(hwnd,0,0,width,height,TRUE); + SetWindowPos(hwnd,HWND_TOPMOST,0,0,0,0,SWP_NOMOVE | SWP_NOSIZE); + oldWinProc = (WNDPROC)SetWindowLong(hwnd,GWL_WNDPROC, (LPARAM)PM_winProc); + return hwnd; +} + +/**************************************************************************** +PARAMETERS: +hwnd - User window to restore + +REMARKS: +This function restores the original attributes of the user window and put's +it back into it's original state before it was converted to a fullscreen +window. +****************************************************************************/ +static void _PM_restoreUserWindow( + HWND hwnd) +{ + SetWindowLong(hwnd,GWL_WNDPROC, (LPARAM)oldWinProc); + SetWindowLong(hwnd,GWL_EXSTYLE,oldExWndStyle); + SetWindowLong(hwnd,GWL_STYLE,oldWndStyle); + SetWindowPos(hwnd,HWND_NOTOPMOST,0,0,0,0,SWP_NOMOVE | SWP_NOSIZE); + ShowWindow(hwnd,SW_SHOW); + MoveWindow(hwnd,oldWinPosX,oldWinPosY,oldWinSizeX,oldWinSizeY,TRUE); + oldWinProc = NULL; +} + +/**************************************************************************** +PARAMETERS: +device - Index of the device to load DirectDraw for (0 for primary) + +REMARKS: +Attempts to dynamically load the DirectDraw DLL's and create the DirectDraw +objects that we need. +****************************************************************************/ +void * PMAPI PM_loadDirectDraw( + int device) +{ + HDC hdc; + int bits; + + /* Call system DLL version if found */ + if (_PM_imports.PM_loadDirectDraw != PM_loadDirectDraw) + return _PM_imports.PM_loadDirectDraw(device); + + // TODO: Handle multi-monitor!! + if (device != 0) + return NULL; + + /* Load the DirectDraw DLL if not presently loaded */ + GET_DEFAULT_CW(); + if (!hInstDD) { + hdc = GetDC(NULL); + bits = GetDeviceCaps(hdc,BITSPIXEL); + ReleaseDC(NULL,hdc); + if (bits < 8) + return NULL; + if ((hInstDD = LoadLibrary("ddraw.dll")) == NULL) + return NULL; + pDirectDrawCreate = (void*)GetProcAddress(hInstDD,"DirectDrawCreate"); + if (!pDirectDrawCreate) + return NULL; + } + + /* Create the DirectDraw object */ + if (!lpDD && pDirectDrawCreate(NULL, &lpDD, NULL) != DD_OK) { + lpDD = NULL; + return NULL; + } + RESET_DEFAULT_CW(); + return lpDD; +} + +/**************************************************************************** +PARAMETERS: +device - Index of the device to unload DirectDraw for (0 for primary) + +REMARKS: +Frees any DirectDraw objects for the device. We never actually explicitly +unload the ddraw.dll library, since unloading and reloading it is +unnecessary since we only want to unload it when the application exits and +that happens automatically. +****************************************************************************/ +void PMAPI PM_unloadDirectDraw( + int device) +{ + /* Call system DLL version if found */ + if (_PM_imports.PM_unloadDirectDraw != PM_unloadDirectDraw) { + _PM_imports.PM_unloadDirectDraw(device); + return; + } + if (lpDD) { + IDirectDraw_Release(lpDD); + lpDD = NULL; + } + (void)device; +} + +/**************************************************************************** +REMARKS: +Open a console for output to the screen, creating the main event handling +window if necessary. +****************************************************************************/ +PM_HWND PMAPI PM_openConsole( + PM_HWND hWndUser, + int device, + int xRes, + int yRes, + int bpp, + ibool fullScreen) +{ + WNDCLASS cls; + static ibool classRegistered = false; + + /* Call system DLL version if found */ + GA_getSystemPMImports(); + if (_PM_imports.PM_openConsole != PM_openConsole) { + if (fullScreen) { + _PM_deskX = xRes; + _PM_deskY = yRes; + } + return _PM_imports.PM_openConsole(hWndUser,device,xRes,yRes,bpp,fullScreen); + } + + /* Create the fullscreen window if necessary */ + hwndUser = hWndUser; + if (fullScreen) { + if (!classRegistered) { + /* Create a Window class for the fullscreen window in here, since + * we need to register one that will do all our event handling for + * us. + */ + hInstApp = GetModuleHandle(NULL); + cls.hCursor = LoadCursor(NULL,IDC_ARROW); + cls.hIcon = LoadIcon(hInstApp,MAKEINTRESOURCE(1)); + cls.lpszMenuName = NULL; + cls.lpszClassName = szWinClassName; + cls.hbrBackground = GetStockObject(BLACK_BRUSH); + cls.hInstance = hInstApp; + cls.style = CS_DBLCLKS; + cls.lpfnWndProc = PM_winProc; + cls.cbWndExtra = 0; + cls.cbClsExtra = 0; + if (!RegisterClass(&cls)) + return NULL; + classRegistered = true; + } + _PM_deskX = xRes; + _PM_deskY = yRes; + if (!hwndUser) { + char windowTitle[80]; + if (LoadString(hInstApp,1,windowTitle,sizeof(windowTitle)) == 0) + strcpy(windowTitle,"MGL Fullscreen Application"); + _PM_hwndConsole = CreateWindowEx(WS_EX_APPWINDOW,szWinClassName, + windowTitle,WS_POPUP | WS_SYSMENU,0,0,xRes,yRes, + NULL,NULL,hInstApp,NULL); + } + else { + _PM_hwndConsole = _PM_convertUserWindow(hwndUser,xRes,yRes); + } + ShowCursor(false); + isFullScreen = true; + } + else { + _PM_hwndConsole = hwndUser; + isFullScreen = false; + } + SetFocus(_PM_hwndConsole); + SetForegroundWindow(_PM_hwndConsole); + DisableAutoPlay(); + (void)bpp; + return _PM_hwndConsole; +} + +/**************************************************************************** +REMARKS: +Find the size of the console state buffer. +****************************************************************************/ +int PMAPI PM_getConsoleStateSize(void) +{ + /* Call system DLL version if found */ + if (_PM_imports.PM_getConsoleStateSize != PM_getConsoleStateSize) + return _PM_imports.PM_getConsoleStateSize(); + + /* Not used in Windows */ + return 1; +} + +/**************************************************************************** +REMARKS: +Save the state of the console. +****************************************************************************/ +void PMAPI PM_saveConsoleState( + void *stateBuf, + PM_HWND hwndConsole) +{ + /* Call system DLL version if found */ + if (_PM_imports.PM_saveConsoleState != PM_saveConsoleState) { + _PM_imports.PM_saveConsoleState(stateBuf,hwndConsole); + return; + } + + /* Not used in Windows */ + (void)stateBuf; + (void)hwndConsole; +} + +/**************************************************************************** +REMARKS: +Set the suspend application callback for the fullscreen console. +****************************************************************************/ +void PMAPI PM_setSuspendAppCallback( + PM_saveState_cb saveState) +{ + /* Call system DLL version if found */ + if (_PM_imports.PM_setSuspendAppCallback != PM_setSuspendAppCallback) { + _PM_imports.PM_setSuspendAppCallback(saveState); + return; + } + suspendApp = saveState; +} + +/**************************************************************************** +REMARKS: +Restore the console state. +****************************************************************************/ +void PMAPI PM_restoreConsoleState( + const void *stateBuf, + PM_HWND hwndConsole) +{ + /* Call system DLL version if found */ + if (_PM_imports.PM_restoreConsoleState != PM_restoreConsoleState) { + _PM_imports.PM_restoreConsoleState(stateBuf,hwndConsole); + return; + } + + /* Not used in Windows */ + (void)stateBuf; + (void)hwndConsole; +} + +/**************************************************************************** +REMARKS: +Close the fullscreen console. +****************************************************************************/ +void PMAPI PM_closeConsole( + PM_HWND hwndConsole) +{ + /* Call system DLL version if found */ + if (_PM_imports.PM_closeConsole != PM_closeConsole) { + _PM_imports.PM_closeConsole(hwndConsole); + return; + } + ShowCursor(true); + RestoreAutoPlay(); + if (hwndUser) + _PM_restoreUserWindow(hwndConsole); + else + DestroyWindow(hwndConsole); + hwndUser = NULL; + _PM_hwndConsole = NULL; +} + +/**************************************************************************** +REMARKS: +Return the DirectDraw window handle used by the application. +****************************************************************************/ +PM_HWND PMAPI PM_getDirectDrawWindow(void) +{ + /* Call system DLL version if found */ + if (_PM_imports.PM_getDirectDrawWindow != PM_getDirectDrawWindow) + return _PM_imports.PM_getDirectDrawWindow(); + return _PM_hwndConsole; +} + |