summaryrefslogtreecommitdiffstats
path: root/board/MAI/bios_emulator/scitech/src/pm/win32/ddraw.c
diff options
context:
space:
mode:
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.c583
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 0000000000..cf89401fe6
--- /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;
+}
+
OpenPOWER on IntegriCloud