summaryrefslogtreecommitdiffstats
path: root/board/MAI/bios_emulator/scitech/src/pm/win32
diff options
context:
space:
mode:
Diffstat (limited to 'board/MAI/bios_emulator/scitech/src/pm/win32')
-rw-r--r--board/MAI/bios_emulator/scitech/src/pm/win32/_pmwin32.asm78
-rw-r--r--board/MAI/bios_emulator/scitech/src/pm/win32/cpuinfo.c94
-rw-r--r--board/MAI/bios_emulator/scitech/src/pm/win32/ddraw.c583
-rw-r--r--board/MAI/bios_emulator/scitech/src/pm/win32/event.c460
-rw-r--r--board/MAI/bios_emulator/scitech/src/pm/win32/ntservc.c259
-rw-r--r--board/MAI/bios_emulator/scitech/src/pm/win32/oshdr.h80
-rw-r--r--board/MAI/bios_emulator/scitech/src/pm/win32/pm.c1460
-rw-r--r--board/MAI/bios_emulator/scitech/src/pm/win32/vflat.c53
-rw-r--r--board/MAI/bios_emulator/scitech/src/pm/win32/ztimer.c136
9 files changed, 3203 insertions, 0 deletions
diff --git a/board/MAI/bios_emulator/scitech/src/pm/win32/_pmwin32.asm b/board/MAI/bios_emulator/scitech/src/pm/win32/_pmwin32.asm
new file mode 100644
index 0000000000..7c242b5724
--- /dev/null
+++ b/board/MAI/bios_emulator/scitech/src/pm/win32/_pmwin32.asm
@@ -0,0 +1,78 @@
+;****************************************************************************
+;*
+;* SciTech OS Portability Manager 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: 80386 Assembler, TASM 4.0 or NASM
+;* Environment: Win32
+;*
+;* Description: Low level assembly support for the PM library specific
+;* to Windows.
+;*
+;****************************************************************************
+
+ IDEAL
+
+include "scitech.mac" ; Memory model macros
+
+header _pmwin32 ; Set up memory model
+
+begdataseg _pmwin32
+
+ cglobal _PM_ioentry
+ cglobal _PM_gdt
+_PM_ioentry dd 0 ; Offset to call gate
+_PM_gdt dw 0 ; Selector to call gate
+
+enddataseg _pmwin32
+
+begcodeseg _pmwin32 ; Start of code segment
+
+;----------------------------------------------------------------------------
+; int PM_setIOPL(int iopl)
+;----------------------------------------------------------------------------
+; Change the IOPL level for the 32-bit task. Returns the previous level
+; so it can be restored for the task correctly.
+;----------------------------------------------------------------------------
+cprocstart _PM_setIOPLViaCallGate
+
+ ARG iopl:UINT
+
+ enter_c
+ pushfd ; Save the old EFLAGS for later
+ mov ecx,[iopl] ; ECX := IOPL level
+ xor ebx,ebx ; Change IOPL level function code
+ifdef USE_NASM
+ call far dword [_PM_ioentry]
+else
+ call [FWORD _PM_ioentry]
+endif
+ pop eax
+ and eax,0011000000000000b
+ shr eax,12
+ leave_c
+ ret
+
+cprocend
+
+endcodeseg _pmwin32
+
+ END ; End of module
diff --git a/board/MAI/bios_emulator/scitech/src/pm/win32/cpuinfo.c b/board/MAI/bios_emulator/scitech/src/pm/win32/cpuinfo.c
new file mode 100644
index 0000000000..5978b9f76e
--- /dev/null
+++ b/board/MAI/bios_emulator/scitech/src/pm/win32/cpuinfo.c
@@ -0,0 +1,94 @@
+/****************************************************************************
+*
+* Ultra Long Period Timer
+*
+* ========================================================================
+*
+* 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: Module to implement OS specific services to measure the
+* CPU frequency.
+*
+****************************************************************************/
+
+/*---------------------------- Global variables ---------------------------*/
+
+static ibool havePerformanceCounter;
+
+/*----------------------------- Implementation ----------------------------*/
+
+/****************************************************************************
+REMARKS:
+Increase the thread priority to maximum, if possible.
+****************************************************************************/
+static int SetMaxThreadPriority(void)
+{
+ int oldPriority;
+ HANDLE hThread = GetCurrentThread();
+
+ oldPriority = GetThreadPriority(hThread);
+ if (oldPriority != THREAD_PRIORITY_ERROR_RETURN)
+ SetThreadPriority(hThread, THREAD_PRIORITY_TIME_CRITICAL);
+ return oldPriority;
+}
+
+/****************************************************************************
+REMARKS:
+Restore the original thread priority.
+****************************************************************************/
+static void RestoreThreadPriority(
+ int oldPriority)
+{
+ HANDLE hThread = GetCurrentThread();
+
+ if (oldPriority != THREAD_PRIORITY_ERROR_RETURN)
+ SetThreadPriority(hThread, oldPriority);
+}
+
+/****************************************************************************
+REMARKS:
+Initialise the counter and return the frequency of the counter.
+****************************************************************************/
+static void GetCounterFrequency(
+ CPU_largeInteger *freq)
+{
+ if (!QueryPerformanceFrequency((LARGE_INTEGER*)freq)) {
+ havePerformanceCounter = false;
+ freq->low = 100000;
+ freq->high = 0;
+ }
+ else
+ havePerformanceCounter = true;
+}
+
+/****************************************************************************
+REMARKS:
+Read the counter and return the counter value.
+****************************************************************************/
+#define GetCounter(t) \
+{ \
+ if (havePerformanceCounter) \
+ QueryPerformanceCounter((LARGE_INTEGER*)t); \
+ else { \
+ (t)->low = timeGetTime() * 100; \
+ (t)->high = 0; \
+ } \
+}
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;
+}
+
diff --git a/board/MAI/bios_emulator/scitech/src/pm/win32/event.c b/board/MAI/bios_emulator/scitech/src/pm/win32/event.c
new file mode 100644
index 0000000000..c14377dcda
--- /dev/null
+++ b/board/MAI/bios_emulator/scitech/src/pm/win32/event.c
@@ -0,0 +1,460 @@
+/****************************************************************************
+*
+* 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.
+*
+****************************************************************************/
+
+/*---------------------------- Global Variables ---------------------------*/
+
+static ushort keyUpMsg[256] = {0}; /* Table of key up messages */
+static int rangeX,rangeY; /* Range of mouse coordinates */
+
+/*---------------------------- Implementation -----------------------------*/
+
+/* These are not used under Win32 */
+#define _EVT_disableInt() 1
+#define _EVT_restoreInt(flags) (void)(flags)
+
+/****************************************************************************
+PARAMETERS:
+scanCode - Scan code to test
+
+REMARKS:
+This macro determines if a specified key is currently down at the
+time that the call is made.
+****************************************************************************/
+#define _EVT_isKeyDown(scanCode) (keyUpMsg[scanCode] != 0)
+
+/****************************************************************************
+REMARKS:
+This function is used to return the number of ticks since system
+startup in milliseconds. This should be the same value that is placed into
+the time stamp fields of events, and is used to implement auto mouse down
+events.
+****************************************************************************/
+ulong _EVT_getTicks(void)
+{ return timeGetTime(); }
+
+/****************************************************************************
+REMARKS:
+Pumps all messages in the message queue from Win32 into our event queue.
+****************************************************************************/
+void _EVT_pumpMessages(void)
+{
+ MSG msg;
+ MSG charMsg;
+ event_t evt;
+
+ // TODO: Add support for DirectInput! We can't support relative mouse
+ // movement motion counters without DirectInput ;-(.
+ while (PeekMessage(&msg,NULL,0,0,PM_REMOVE)) {
+ memset(&evt,0,sizeof(evt));
+ switch (msg.message) {
+ case WM_MOUSEMOVE:
+ evt.what = EVT_MOUSEMOVE;
+ break;
+ case WM_LBUTTONDBLCLK:
+ evt.what = EVT_MOUSEDOWN;
+ evt.message = EVT_LEFTBMASK | EVT_DBLCLICK;
+ break;
+ case WM_LBUTTONDOWN:
+ evt.what = EVT_MOUSEDOWN;
+ evt.message = EVT_LEFTBMASK;
+ break;
+ case WM_LBUTTONUP:
+ evt.what = EVT_MOUSEUP;
+ evt.message = EVT_LEFTBMASK;
+ break;
+ case WM_RBUTTONDBLCLK:
+ evt.what = EVT_MOUSEDOWN | EVT_DBLCLICK;
+ evt.message = EVT_RIGHTBMASK;
+ break;
+ case WM_RBUTTONDOWN:
+ evt.what = EVT_MOUSEDOWN;
+ evt.message = EVT_RIGHTBMASK;
+ break;
+ case WM_RBUTTONUP:
+ evt.what = EVT_MOUSEUP;
+ evt.message = EVT_RIGHTBMASK;
+ break;
+ case WM_MBUTTONDBLCLK:
+ evt.what = EVT_MOUSEDOWN | EVT_DBLCLICK;
+ evt.message = EVT_MIDDLEBMASK;
+ break;
+ case WM_MBUTTONDOWN:
+ evt.what = EVT_MOUSEDOWN;
+ evt.message = EVT_MIDDLEBMASK;
+ break;
+ case WM_MBUTTONUP:
+ evt.what = EVT_MOUSEUP;
+ evt.message = EVT_MIDDLEBMASK;
+ break;
+ case WM_KEYDOWN:
+ case WM_SYSKEYDOWN:
+ if (HIWORD(msg.lParam) & KF_REPEAT) {
+ evt.what = EVT_KEYREPEAT;
+ }
+ else {
+ evt.what = EVT_KEYDOWN;
+ }
+ break;
+ case WM_KEYUP:
+ case WM_SYSKEYUP:
+ evt.what = EVT_KEYUP;
+ break;
+ }
+
+ /* Convert mouse event modifier flags */
+ if (evt.what & EVT_MOUSEEVT) {
+ if (_PM_deskX) {
+ evt.where_x = ((long)msg.pt.x * rangeX) / _PM_deskX;
+ evt.where_y = ((long)msg.pt.y * rangeY) / _PM_deskY;
+ }
+ else {
+ ScreenToClient(_PM_hwndConsole, &msg.pt);
+ evt.where_x = msg.pt.x;
+ evt.where_y = msg.pt.y;
+ }
+ if (evt.what == EVT_MOUSEMOVE) {
+ /* Save the current mouse position */
+ EVT.mx = evt.where_x;
+ EVT.my = evt.where_y;
+ if (EVT.oldMove != -1) {
+ EVT.evtq[EVT.oldMove].where_x = evt.where_x;/* Modify existing one */
+ EVT.evtq[EVT.oldMove].where_y = evt.where_y;
+// EVT.evtq[EVT.oldMove].relative_x += mickeyX; // TODO!
+// EVT.evtq[EVT.oldMove].relative_y += mickeyY; // TODO!
+ evt.what = 0;
+ }
+ else {
+ EVT.oldMove = EVT.freeHead; /* Save id of this move event */
+// evt.relative_x = mickeyX; // TODO!
+// evt.relative_y = mickeyY; // TODO!
+ }
+ }
+ else
+ EVT.oldMove = -1;
+ if (msg.wParam & MK_LBUTTON)
+ evt.modifiers |= EVT_LEFTBUT;
+ if (msg.wParam & MK_RBUTTON)
+ evt.modifiers |= EVT_RIGHTBUT;
+ if (msg.wParam & MK_MBUTTON)
+ evt.modifiers |= EVT_MIDDLEBUT;
+ if (msg.wParam & MK_SHIFT)
+ evt.modifiers |= EVT_SHIFTKEY;
+ if (msg.wParam & MK_CONTROL)
+ evt.modifiers |= EVT_CTRLSTATE;
+ }
+
+ /* Convert keyboard codes */
+ TranslateMessage(&msg);
+ if (evt.what & EVT_KEYEVT) {
+ int scanCode = (msg.lParam >> 16) & 0xFF;
+ if (evt.what == EVT_KEYUP) {
+ /* Get message for keyup code from table of cached down values */
+ evt.message = keyUpMsg[scanCode];
+ keyUpMsg[scanCode] = 0;
+ }
+ else {
+ if (PeekMessage(&charMsg,NULL,WM_CHAR,WM_CHAR,PM_REMOVE))
+ evt.message = charMsg.wParam;
+ if (PeekMessage(&charMsg,NULL,WM_SYSCHAR,WM_SYSCHAR,PM_REMOVE))
+ evt.message = charMsg.wParam;
+ evt.message |= ((msg.lParam >> 8) & 0xFF00);
+ keyUpMsg[scanCode] = (ushort)evt.message;
+ }
+ if (evt.what == EVT_KEYREPEAT)
+ evt.message |= (msg.lParam << 16);
+ if (HIWORD(msg.lParam) & KF_ALTDOWN)
+ evt.modifiers |= EVT_ALTSTATE;
+ if (GetKeyState(VK_SHIFT) & 0x8000U)
+ evt.modifiers |= EVT_SHIFTKEY;
+ if (GetKeyState(VK_CONTROL) & 0x8000U)
+ evt.modifiers |= EVT_CTRLSTATE;
+ EVT.oldMove = -1;
+ }
+
+ if (evt.what != 0) {
+ /* Add time stamp and add the event to the queue */
+ evt.when = msg.time;
+ if (EVT.count < EVENTQSIZE)
+ addEvent(&evt);
+ }
+ DispatchMessage(&msg);
+ }
+}
+
+/****************************************************************************
+REMARKS:
+This macro/function is used to converts the scan codes reported by the
+keyboard to our event libraries normalised format. We only have one scan
+code for the 'A' key, and use shift modifiers to determine if it is a
+Ctrl-F1, Alt-F1 etc. The raw scan codes from the keyboard work this way,
+but the OS gives us 'cooked' scan codes, we have to translate them back
+to the raw format.
+****************************************************************************/
+#define _EVT_maskKeyCode(evt)
+
+/****************************************************************************
+REMARKS:
+Safely abort the event module upon catching a fatal error.
+****************************************************************************/
+void _EVT_abort(
+ int signal)
+{
+ (void)signal;
+ EVT_exit();
+ PM_fatalError("Unhandled exception!");
+}
+
+/****************************************************************************
+PARAMETERS:
+mouseMove - Callback function to call wheneve the mouse needs to be moved
+
+REMARKS:
+Initiliase the event handling module. Here we install our mouse handling ISR
+to be called whenever any button's are pressed or released. We also build
+the free list of events in the event queue.
+
+We use handler number 2 of the mouse libraries interrupt handlers for our
+event handling routines.
+****************************************************************************/
+void EVTAPI EVT_init(
+ _EVT_mouseMoveHandler mouseMove)
+{
+ /* Initialise the event queue */
+ EVT.mouseMove = mouseMove;
+ initEventQueue();
+ memset(keyUpMsg,0,sizeof(keyUpMsg));
+
+ /* Catch program termination signals so we can clean up properly */
+ signal(SIGABRT, _EVT_abort);
+ signal(SIGFPE, _EVT_abort);
+ signal(SIGINT, _EVT_abort);
+}
+
+/****************************************************************************
+REMARKS
+Changes the range of coordinates returned by the mouse functions to the
+specified range of values. This is used when changing between graphics
+modes set the range of mouse coordinates for the new display mode.
+****************************************************************************/
+void EVTAPI EVT_setMouseRange(
+ int xRes,
+ int yRes)
+{
+ rangeX = xRes;
+ rangeY = yRes;
+}
+
+/****************************************************************************
+REMARKS
+Modifes the mouse coordinates as necessary if scaling to OS coordinates,
+and sets the OS mouse cursor position.
+****************************************************************************/
+void _EVT_setMousePos(
+ int *x,
+ int *y)
+{
+ /* Scale coordinates up to desktop coordinates first */
+ int scaledX = (*x * _PM_deskX) / rangeX;
+ int scaledY = (*y * _PM_deskY) / rangeY;
+
+ /* Scale coordinates back to screen coordinates again */
+ *x = (scaledX * rangeX) / _PM_deskX;
+ *y = (scaledY * rangeY) / _PM_deskY;
+ SetCursorPos(scaledX,scaledY);
+}
+
+/****************************************************************************
+REMARKS:
+Initiailises the internal event handling modules. The EVT_suspend function
+can be called to suspend event handling (such as when shelling out to DOS),
+and this function can be used to resume it again later.
+****************************************************************************/
+void EVT_resume(void)
+{
+ // Do nothing for Win32
+}
+
+/****************************************************************************
+REMARKS
+Suspends all of our event handling operations. This is also used to
+de-install the event handling code.
+****************************************************************************/
+void EVT_suspend(void)
+{
+ // Do nothing for Win32
+}
+
+/****************************************************************************
+REMARKS
+Exits the event module for program terminatation.
+****************************************************************************/
+void EVT_exit(void)
+{
+ /* Restore signal handlers */
+ signal(SIGABRT, SIG_DFL);
+ signal(SIGFPE, SIG_DFL);
+ signal(SIGINT, SIG_DFL);
+}
+
+/****************************************************************************
+DESCRIPTION:
+Returns the mask indicating what joystick axes are attached.
+
+HEADER:
+event.h
+
+REMARKS:
+This function is used to detect the attached joysticks, and determine
+what axes are present and functioning. This function will re-detect any
+attached joysticks when it is called, so if the user forgot to attach
+the joystick when the application started, you can call this function to
+re-detect any newly attached joysticks.
+
+SEE ALSO:
+EVT_joySetLowerRight, EVT_joySetCenter, EVT_joyIsPresent
+****************************************************************************/
+int EVTAPI EVT_joyIsPresent(void)
+{
+ // TODO: Implement joystick code based on DirectX!
+ return 0;
+}
+
+/****************************************************************************
+DESCRIPTION:
+Polls the joystick for position and button information.
+
+HEADER:
+event.h
+
+REMARKS:
+This routine is used to poll analogue joysticks for button and position
+information. It should be called once for each main loop of the user
+application, just before processing all pending events via EVT_getNext.
+All information polled from the joystick will be posted to the event
+queue for later retrieval.
+
+Note: Most analogue joysticks will provide readings that change even
+ though the joystick has not moved. Hence if you call this routine
+ you will likely get an EVT_JOYMOVE event every time through your
+ event loop.
+
+SEE ALSO:
+EVT_getNext, EVT_peekNext, EVT_joySetUpperLeft, EVT_joySetLowerRight,
+EVT_joySetCenter, EVT_joyIsPresent
+****************************************************************************/
+void EVTAPI EVT_pollJoystick(void)
+{
+}
+
+/****************************************************************************
+DESCRIPTION:
+Calibrates the joystick upper left position
+
+HEADER:
+event.h
+
+REMARKS:
+This function can be used to zero in on better joystick calibration factors,
+which may work better than the default simplistic calibration (which assumes
+the joystick is centered when the event library is initialised).
+To use this function, ask the user to hold the stick in the upper left
+position and then have them press a key or button. and then call this
+function. This function will then read the joystick and update the
+calibration factors.
+
+Usually, assuming that the stick was centered when the event library was
+initialized, you really only need to call EVT_joySetLowerRight since the
+upper left position is usually always 0,0 on most joysticks. However, the
+safest procedure is to call all three calibration functions.
+
+SEE ALSO:
+EVT_joySetUpperLeft, EVT_joySetLowerRight, EVT_joyIsPresent
+****************************************************************************/
+void EVTAPI EVT_joySetUpperLeft(void)
+{
+}
+
+/****************************************************************************
+DESCRIPTION:
+Calibrates the joystick lower right position
+
+HEADER:
+event.h
+
+REMARKS:
+This function can be used to zero in on better joystick calibration factors,
+which may work better than the default simplistic calibration (which assumes
+the joystick is centered when the event library is initialised).
+To use this function, ask the user to hold the stick in the lower right
+position and then have them press a key or button. and then call this
+function. This function will then read the joystick and update the
+calibration factors.
+
+Usually, assuming that the stick was centered when the event library was
+initialized, you really only need to call EVT_joySetLowerRight since the
+upper left position is usually always 0,0 on most joysticks. However, the
+safest procedure is to call all three calibration functions.
+
+SEE ALSO:
+EVT_joySetUpperLeft, EVT_joySetCenter, EVT_joyIsPresent
+****************************************************************************/
+void EVTAPI EVT_joySetLowerRight(void)
+{
+}
+
+/****************************************************************************
+DESCRIPTION:
+Calibrates the joystick center position
+
+HEADER:
+event.h
+
+REMARKS:
+This function can be used to zero in on better joystick calibration factors,
+which may work better than the default simplistic calibration (which assumes
+the joystick is centered when the event library is initialised).
+To use this function, ask the user to hold the stick in the center
+position and then have them press a key or button. and then call this
+function. This function will then read the joystick and update the
+calibration factors.
+
+Usually, assuming that the stick was centered when the event library was
+initialized, you really only need to call EVT_joySetLowerRight since the
+upper left position is usually always 0,0 on most joysticks. However, the
+safest procedure is to call all three calibration functions.
+
+SEE ALSO:
+EVT_joySetUpperLeft, EVT_joySetLowerRight, EVT_joySetCenter
+****************************************************************************/
+void EVTAPI EVT_joySetCenter(void)
+{
+}
+
diff --git a/board/MAI/bios_emulator/scitech/src/pm/win32/ntservc.c b/board/MAI/bios_emulator/scitech/src/pm/win32/ntservc.c
new file mode 100644
index 0000000000..a3324d33b8
--- /dev/null
+++ b/board/MAI/bios_emulator/scitech/src/pm/win32/ntservc.c
@@ -0,0 +1,259 @@
+/****************************************************************************
+*
+* SciTech Display Doctor
+*
+* Copyright (C) 1991-2001 SciTech Software, Inc.
+* All rights reserved.
+*
+* ======================================================================
+* |REMOVAL OR MODIFICATION OF THIS HEADER IS STRICTLY PROHIBITED BY LAW|
+* | |
+* |This copyrighted computer code is a proprietary trade secret of |
+* |SciTech Software, Inc., located at 505 Wall Street, Chico, CA 95928 |
+* |USA (www.scitechsoft.com). ANY UNAUTHORIZED POSSESSION, USE, |
+* |VIEWING, COPYING, MODIFICATION OR DISSEMINATION OF THIS CODE IS |
+* |STRICTLY PROHIBITED BY LAW. Unless you have current, express |
+* |written authorization from SciTech to possess or use this code, you |
+* |may be subject to civil and/or criminal penalties. |
+* | |
+* |If you received this code in error or you would like to report |
+* |improper use, please immediately contact SciTech Software, Inc. at |
+* |530-894-8400. |
+* | |
+* |REMOVAL OR MODIFICATION OF THIS HEADER IS STRICTLY PROHIBITED BY LAW|
+* ======================================================================
+*
+* Language: ANSI C
+* Environment: Windows NT, Windows 2K or Windows XP.
+*
+* Description: Main module to do the installation of the SDD and GLDirect
+* device driver components under Windows NT/2K/XP.
+*
+****************************************************************************/
+
+#include "pmapi.h"
+#include "win32/oshdr.h"
+
+/*----------------------------- Implementation ----------------------------*/
+
+/****************************************************************************
+PARAMETERS:
+szDriverName - Actual name of the driver to install in the system
+szServiceName - Name of the service to create
+szLoadGroup - Load group for the driver (NULL for normal drivers)
+dwServiceType - Service type to create
+
+RETURNS:
+True on success, false on failure.
+
+REMARKS:
+This function does all the work to install the driver into the system.
+The driver is not however activated; for that you must use the Start_SddFilt
+function.
+****************************************************************************/
+ulong PMAPI PM_installService(
+ const char *szDriverName,
+ const char *szServiceName,
+ const char *szLoadGroup,
+ ulong dwServiceType)
+{
+ SC_HANDLE scmHandle;
+ SC_HANDLE driverHandle;
+ char szDriverPath[MAX_PATH];
+ HKEY key;
+ char keyPath[MAX_PATH];
+ ulong status;
+
+ // Obtain a handle to the service control manager requesting all access
+ if ((scmHandle = OpenSCManager(NULL, NULL, SC_MANAGER_ALL_ACCESS)) == NULL)
+ return GetLastError();
+
+ // Find the path to the driver in system directory
+ GetSystemDirectory(szDriverPath, sizeof(szDriverPath));
+ strcat(szDriverPath, "\\drivers\\");
+ strcat(szDriverPath, szDriverName);
+
+ // Create the service with the Service Control Manager.
+ driverHandle = CreateService(scmHandle,
+ szServiceName,
+ szServiceName,
+ SERVICE_ALL_ACCESS,
+ dwServiceType,
+ SERVICE_BOOT_START,
+ SERVICE_ERROR_NORMAL,
+ szDriverPath,
+ szLoadGroup,
+ NULL,
+ NULL,
+ NULL,
+ NULL);
+
+ // Check to see if the driver could actually be installed.
+ if (!driverHandle) {
+ status = GetLastError();
+ CloseServiceHandle(scmHandle);
+ return status;
+ }
+
+ // Get a handle to the key for driver so that it can be altered in the
+ // next step.
+ strcpy(keyPath, "SYSTEM\\CurrentControlSet\\Services\\");
+ strcat(keyPath, szServiceName);
+ if ((status = RegOpenKeyEx(HKEY_LOCAL_MACHINE,keyPath,0,KEY_ALL_ACCESS,&key)) != ERROR_SUCCESS) {
+ // A problem has occured. Delete the service so that it is not installed.
+ status = GetLastError();
+ DeleteService(driverHandle);
+ CloseServiceHandle(driverHandle);
+ CloseServiceHandle(scmHandle);
+ return status;
+ }
+
+ // Delete the ImagePath value in the newly created key so that the
+ // system looks for the driver in the normal location.
+ if ((status = RegDeleteValue(key, "ImagePath")) != ERROR_SUCCESS) {
+ // A problem has occurred. Delete the service so that it is not
+ // installed and will not try to start.
+ RegCloseKey(key);
+ DeleteService(driverHandle);
+ CloseServiceHandle(driverHandle);
+ CloseServiceHandle(scmHandle);
+ return status;
+ }
+
+ // Clean up and exit
+ RegCloseKey(key);
+ CloseServiceHandle(driverHandle);
+ CloseServiceHandle(scmHandle);
+ return ERROR_SUCCESS;
+}
+
+/****************************************************************************
+PARAMETERS:
+szServiceName - Name of the service to start
+
+RETURNS:
+True on success, false on failure.
+
+REMARKS:
+This function is used to start the specified service and make it active.
+****************************************************************************/
+ulong PMAPI PM_startService(
+ const char *szServiceName)
+{
+ SC_HANDLE scmHandle;
+ SC_HANDLE driverHandle;
+ SERVICE_STATUS serviceStatus;
+ ulong status;
+
+ // Obtain a handle to the service control manager requesting all access
+ if ((scmHandle = OpenSCManager(NULL, NULL, SC_MANAGER_ALL_ACCESS)) == NULL)
+ return GetLastError();
+
+ // Open the service with the Service Control Manager.
+ if ((driverHandle = OpenService(scmHandle,szServiceName,SERVICE_ALL_ACCESS)) == NULL) {
+ status = GetLastError();
+ CloseServiceHandle(scmHandle);
+ return status;
+ }
+
+ // Start the service
+ if (!StartService(driverHandle,0,NULL)) {
+ status = GetLastError();
+ CloseServiceHandle(driverHandle);
+ CloseServiceHandle(scmHandle);
+ return status;
+ }
+
+ // Query the service to make sure it is there
+ if (!QueryServiceStatus(driverHandle,&serviceStatus)) {
+ status = GetLastError();
+ CloseServiceHandle(driverHandle);
+ CloseServiceHandle(scmHandle);
+ return status;
+ }
+ CloseServiceHandle(driverHandle);
+ CloseServiceHandle(scmHandle);
+ return ERROR_SUCCESS;
+}
+
+/****************************************************************************
+PARAMETERS:
+szServiceName - Name of the service to stop
+
+RETURNS:
+True on success, false on failure.
+
+REMARKS:
+This function is used to stop the specified service and disable it.
+****************************************************************************/
+ulong PMAPI PM_stopService(
+ const char *szServiceName)
+{
+ SC_HANDLE scmHandle;
+ SC_HANDLE driverHandle;
+ SERVICE_STATUS serviceStatus;
+ ulong status;
+
+ // Obtain a handle to the service control manager requesting all access
+ if ((scmHandle = OpenSCManager(NULL, NULL, SC_MANAGER_ALL_ACCESS)) == NULL)
+ return GetLastError();
+
+ // Open the service with the Service Control Manager.
+ if ((driverHandle = OpenService(scmHandle,szServiceName,SERVICE_ALL_ACCESS)) == NULL) {
+ status = GetLastError();
+ CloseServiceHandle(scmHandle);
+ return status;
+ }
+
+ // Stop the service from running
+ if (!ControlService(driverHandle, SERVICE_CONTROL_STOP, &serviceStatus)) {
+ status = GetLastError();
+ CloseServiceHandle(driverHandle);
+ CloseServiceHandle(scmHandle);
+ return status;
+ }
+ CloseServiceHandle(driverHandle);
+ CloseServiceHandle(scmHandle);
+ return ERROR_SUCCESS;
+}
+
+/****************************************************************************
+PARAMETERS:
+szServiceName - Name of the service to remove
+
+RETURNS:
+True on success, false on failure.
+
+REMARKS:
+This function is used to remove a service completely from the system.
+****************************************************************************/
+ulong PMAPI PM_removeService(
+ const char *szServiceName)
+{
+ SC_HANDLE scmHandle;
+ SC_HANDLE driverHandle;
+ ulong status;
+
+ // Obtain a handle to the service control manager requesting all access
+ if ((scmHandle = OpenSCManager(NULL, NULL, SC_MANAGER_ALL_ACCESS)) == NULL)
+ return GetLastError();
+
+ // Open the service with the Service Control Manager.
+ if ((driverHandle = OpenService(scmHandle,szServiceName,SERVICE_ALL_ACCESS)) == NULL) {
+ status = GetLastError();
+ CloseServiceHandle(scmHandle);
+ return status;
+ }
+
+ // Remove the service
+ if (!DeleteService(driverHandle)) {
+ status = GetLastError();
+ CloseServiceHandle(driverHandle);
+ CloseServiceHandle(scmHandle);
+ return status;
+ }
+ CloseServiceHandle(driverHandle);
+ CloseServiceHandle(scmHandle);
+ return ERROR_SUCCESS;
+}
+
diff --git a/board/MAI/bios_emulator/scitech/src/pm/win32/oshdr.h b/board/MAI/bios_emulator/scitech/src/pm/win32/oshdr.h
new file mode 100644
index 0000000000..018c936d8a
--- /dev/null
+++ b/board/MAI/bios_emulator/scitech/src/pm/win32/oshdr.h
@@ -0,0 +1,80 @@
+/****************************************************************************
+*
+* SciTech OS Portability Manager 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: Include file to include all OS specific header files.
+*
+****************************************************************************/
+
+#define WIN32_LEAN_AND_MEAN
+#define STRICT
+#include <windows.h>
+#include <mmsystem.h>
+#include <float.h>
+#define NONAMELESSUNION
+#include "pm/ddraw.h"
+
+/* Macros to save and restore the default control word. Windows 9x has
+ * some bugs in it such that calls to load any DLL's which load 16-bit
+ * DLL's cause the floating point control word to get trashed. We fix
+ * this by saving and restoring the control word across problematic
+ * calls.
+ */
+
+#if defined(__INTEL__)
+#define GET_DEFAULT_CW() \
+{ \
+ if (_PM_cw_default == 0) \
+ _PM_cw_default = _control87(0,0); \
+}
+#define RESET_DEFAULT_CW() \
+ _control87(_PM_cw_default,0xFFFFFFFF)
+#else
+#define GET_DEFAULT_CW()
+#define RESET_DEFAULT_CW()
+#endif
+
+/* Custom window messages */
+
+#define WM_DO_SUSPEND_APP WM_USER
+#define WM_PM_LEAVE_FULLSCREEN 0
+#define WM_PM_RESTORE_FULLSCREEN 1
+
+/* Macro for disabling AutoPlay on a use system */
+
+#define AUTOPLAY_DRIVE_CDROM 0x20
+
+/*--------------------------- Global Variables ----------------------------*/
+
+#ifdef __INTEL__
+extern uint _PM_cw_default; /* Default FPU control word */
+#endif
+extern int _PM_deskX,_PM_deskY; /* Desktop dimensions */
+extern HWND _PM_hwndConsole; /* Window handle for console */
+
+/*-------------------------- Internal Functions ---------------------------*/
+
+void _EVT_pumpMessages(void);
+
diff --git a/board/MAI/bios_emulator/scitech/src/pm/win32/pm.c b/board/MAI/bios_emulator/scitech/src/pm/win32/pm.c
new file mode 100644
index 0000000000..d08da4c630
--- /dev/null
+++ b/board/MAI/bios_emulator/scitech/src/pm/win32/pm.c
@@ -0,0 +1,1460 @@
+/****************************************************************************
+*
+* SciTech OS Portability Manager 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: Implementation for the OS Portability Manager Library, which
+* contains functions to implement OS specific services in a
+* generic, cross platform API. Porting the OS Portability
+* Manager library is the first step to porting any SciTech
+* products to a new platform.
+*
+****************************************************************************/
+
+#define WIN32_LEAN_AND_MEAN
+#define STRICT
+#include <windows.h>
+#include <mmsystem.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+#include <direct.h>
+#include "pmapi.h"
+#include "drvlib/os/os.h"
+#include "pm_help.h"
+
+/*--------------------------- Global variables ----------------------------*/
+
+ibool _PM_haveWinNT; /* True if we are running on NT */
+static uint VESABuf_len = 1024; /* Length of the VESABuf buffer */
+static void *VESABuf_ptr = NULL;/* Near pointer to VESABuf */
+static uint VESABuf_rseg; /* Real mode segment of VESABuf */
+static uint VESABuf_roff; /* Real mode offset of VESABuf */
+HANDLE _PM_hDevice = NULL; /* Handle to Win32 VxD */
+static ibool inited = false; /* Flags if we are initialised */
+static void (PMAPIP fatalErrorCleanup)(void) = NULL;
+
+static char *szMachineNameKey = "System\\CurrentControlSet\\control\\ComputerName\\ComputerName";
+static char *szMachineNameKeyNT = "System\\CurrentControlSet\\control\\ComputerName\\ActiveComputerName";
+static char *szMachineName = "ComputerName";
+
+/*----------------------------- Implementation ----------------------------*/
+
+/* Macro to check for a valid, loaded version of PMHELP. We check this
+ * on demand when we need these services rather than when PM_init() is
+ * called because if we are running on DirectDraw we don't need PMHELP.VXD.
+ */
+
+#define CHECK_FOR_PMHELP() \
+{ \
+ if (_PM_hDevice == INVALID_HANDLE_VALUE) \
+ if (_PM_haveWinNT) \
+ PM_fatalError("Unable to connect to PMHELP.SYS or SDDHELP.SYS!"); \
+ else \
+ PM_fatalError("Unable to connect to PMHELP.VXD or SDDHELP.VXD!"); \
+}
+
+/****************************************************************************
+REMARKS:
+Initialise the PM library and connect to our helper device driver. If we
+cannot connect to our helper device driver, we bail out with an error
+message. Our Windows 9x VxD is dynamically loadable, so it can be loaded
+after the system has started.
+****************************************************************************/
+void PMAPI PM_init(void)
+{
+ DWORD inBuf[1]; /* Buffer to receive data from VxD */
+ DWORD outBuf[1]; /* Buffer to receive data from VxD */
+ DWORD count; /* Count of bytes returned from VxD */
+ char cntPath[PM_MAX_PATH];
+ char *env;
+
+ /* Create a file handle for the static VxD if possible, otherwise
+ * dynamically load the PMHELP helper VxD. Note that if an old version
+ * of SDD is loaded, we use the PMHELP VxD instead.
+ */
+ if (!inited) {
+ /* Determine if we are running under Windows NT or not and
+ * set the global OS type variable.
+ */
+ _PM_haveWinNT = false;
+ if ((GetVersion() & 0x80000000UL) == 0)
+ _PM_haveWinNT = true;
+ ___drv_os_type = (_PM_haveWinNT) ? _OS_WINNT : _OS_WIN95;
+
+ /* Now try to connect to SDDHELP.VXD or SDDHELP.SYS */
+ _PM_hDevice = CreateFile(SDDHELP_MODULE_PATH, 0,0,0, CREATE_NEW, FILE_FLAG_DELETE_ON_CLOSE, 0);
+ if (_PM_hDevice != INVALID_HANDLE_VALUE) {
+ if (!DeviceIoControl(_PM_hDevice, PMHELP_GETVER32, NULL, 0,
+ outBuf, sizeof(outBuf), &count, NULL) || outBuf[0] < PMHELP_VERSION) {
+ /* Old version of SDDHELP loaded, so use PMHELP instead */
+ CloseHandle(_PM_hDevice);
+ _PM_hDevice = INVALID_HANDLE_VALUE;
+ }
+ }
+ if (_PM_hDevice == INVALID_HANDLE_VALUE) {
+ /* First try to see if there is a currently loaded PMHELP driver.
+ * This is usually the case when we are running under Windows NT/2K.
+ */
+ _PM_hDevice = CreateFile(PMHELP_MODULE_PATH, 0,0,0, CREATE_NEW, FILE_FLAG_DELETE_ON_CLOSE, 0);
+ if (_PM_hDevice == INVALID_HANDLE_VALUE) {
+ /* The driver was not staticly loaded, so try creating a file handle
+ * to a dynamic version of the VxD if possible. Note that on WinNT/2K we
+ * cannot support dynamically loading the drivers.
+ */
+ _PM_hDevice = CreateFile(PMHELP_VXD_PATH, 0,0,0, CREATE_NEW, FILE_FLAG_DELETE_ON_CLOSE, 0);
+ }
+ }
+ if (_PM_hDevice != INVALID_HANDLE_VALUE) {
+ /* Call the driver to determine the version number */
+ if (!DeviceIoControl(_PM_hDevice, PMHELP_GETVER32, inBuf, sizeof(inBuf),
+ outBuf, sizeof(outBuf), &count, NULL) || outBuf[0] < PMHELP_VERSION) {
+ if (_PM_haveWinNT)
+ PM_fatalError("Older version of PMHELP.SYS found!");
+ else
+ PM_fatalError("Older version of PMHELP.VXD found!");
+ }
+
+ /* Now set the current path inside the VxD so it knows what the
+ * current directory is for loading Nucleus drivers.
+ */
+ inBuf[0] = (ulong)PM_getCurrentPath(cntPath,sizeof(cntPath));
+ if (!DeviceIoControl(_PM_hDevice, PMHELP_SETCNTPATH32, inBuf, sizeof(inBuf), outBuf, sizeof(outBuf), &count, NULL))
+ PM_fatalError("Unable to set VxD current path!");
+
+ /* Now pass down the NUCLEUS_PATH environment variable to the device
+ * driver so it can use this value if it is found.
+ */
+ if ((env = getenv("NUCLEUS_PATH")) != NULL) {
+ inBuf[0] = (ulong)env;
+ if (!DeviceIoControl(_PM_hDevice, PMHELP_SETNUCLEUSPATH32, inBuf, sizeof(inBuf), outBuf, sizeof(outBuf), &count, NULL))
+ PM_fatalError("Unable to set VxD Nucleus path!");
+ }
+
+ /* Enable IOPL for ring-3 code by default if driver is present */
+ if (_PM_haveWinNT)
+ PM_setIOPL(3);
+ }
+
+ /* Indicate that we have been initialised */
+ inited = true;
+ }
+}
+
+/****************************************************************************
+REMARKS:
+We do have BIOS access under Windows 9x, but not under Windows NT.
+****************************************************************************/
+int PMAPI PM_setIOPL(
+ int iopl)
+{
+ DWORD inBuf[1]; /* Buffer to receive data from VxD */
+ DWORD outBuf[1]; /* Buffer to receive data from VxD */
+ DWORD count; /* Count of bytes returned from VxD */
+ static int cntIOPL = 0;
+ int oldIOPL = cntIOPL;
+
+ /* Enable I/O by adjusting the I/O permissions map on Windows NT */
+ if (_PM_haveWinNT) {
+ CHECK_FOR_PMHELP();
+ if (iopl == 3)
+ DeviceIoControl(_PM_hDevice, PMHELP_ENABLERING3IOPL, inBuf, sizeof(inBuf),outBuf, sizeof(outBuf), &count, NULL);
+ else
+ DeviceIoControl(_PM_hDevice, PMHELP_DISABLERING3IOPL, inBuf, sizeof(inBuf),outBuf, sizeof(outBuf), &count, NULL);
+ cntIOPL = iopl;
+ return oldIOPL;
+ }
+
+ /* We always have IOPL on Windows 9x */
+ return 3;
+}
+
+/****************************************************************************
+REMARKS:
+We do have BIOS access under Windows 9x, but not under Windows NT.
+****************************************************************************/
+ibool PMAPI PM_haveBIOSAccess(void)
+{
+ if (PM_getOSType() == _OS_WINNT)
+ return false;
+ else
+ return _PM_hDevice != INVALID_HANDLE_VALUE;
+}
+
+/****************************************************************************
+REMARKS:
+Return the operating system type identifier.
+****************************************************************************/
+long PMAPI PM_getOSType(void)
+{
+ if ((GetVersion() & 0x80000000UL) == 0)
+ return ___drv_os_type = _OS_WINNT;
+ else
+ return ___drv_os_type = _OS_WIN95;
+}
+
+/****************************************************************************
+REMARKS:
+Return the runtime type identifier.
+****************************************************************************/
+int PMAPI PM_getModeType(void)
+{
+ return PM_386;
+}
+
+/****************************************************************************
+REMARKS:
+Add a file directory separator to the end of the filename.
+****************************************************************************/
+void PMAPI PM_backslash(
+ char *s)
+{
+ uint pos = strlen(s);
+ if (s[pos-1] != '\\') {
+ s[pos] = '\\';
+ s[pos+1] = '\0';
+ }
+}
+
+/****************************************************************************
+REMARKS:
+Add a user defined PM_fatalError cleanup function.
+****************************************************************************/
+void PMAPI PM_setFatalErrorCleanup(
+ void (PMAPIP cleanup)(void))
+{
+ fatalErrorCleanup = cleanup;
+}
+
+/****************************************************************************
+REMARKS:
+Report a fatal error condition and halt the program.
+****************************************************************************/
+void PMAPI PM_fatalError(
+ const char *msg)
+{
+ if (fatalErrorCleanup)
+ fatalErrorCleanup();
+ MessageBox(NULL,msg,"Fatal Error!", MB_ICONEXCLAMATION);
+ exit(1);
+}
+
+/****************************************************************************
+REMARKS:
+Allocate the real mode VESA transfer buffer for communicating with the BIOS.
+****************************************************************************/
+void * PMAPI PM_getVESABuf(
+ uint *len,
+ uint *rseg,
+ uint *roff)
+{
+ DWORD outBuf[4]; /* Buffer to receive data from VxD */
+ DWORD count; /* Count of bytes returned from VxD */
+
+ /* We require the helper VxD to be loaded staticly in order to support
+ * the VESA transfer buffer. We do not support dynamically allocating
+ * real mode memory buffers from Win32 programs (we need a 16-bit DLL
+ * for this, and Windows 9x becomes very unstable if you free the
+ * memory blocks out of order).
+ */
+ if (!inited)
+ PM_init();
+ if (!VESABuf_ptr) {
+ CHECK_FOR_PMHELP();
+ if (DeviceIoControl(_PM_hDevice, PMHELP_GETVESABUF32, NULL, 0,
+ outBuf, sizeof(outBuf), &count, NULL)) {
+ if (!outBuf[0])
+ return NULL;
+ VESABuf_ptr = (void*)outBuf[0];
+ VESABuf_len = outBuf[1];
+ VESABuf_rseg = outBuf[2];
+ VESABuf_roff = outBuf[3];
+ }
+ }
+ *len = VESABuf_len;
+ *rseg = VESABuf_rseg;
+ *roff = VESABuf_roff;
+ return VESABuf_ptr;
+}
+
+/****************************************************************************
+REMARKS:
+Check if a key has been pressed.
+****************************************************************************/
+int PMAPI PM_kbhit(void)
+{
+ /* Not used in Windows */
+ return true;
+}
+
+/****************************************************************************
+REMARKS:
+Wait for and return the next keypress.
+****************************************************************************/
+int PMAPI PM_getch(void)
+{
+ /* Not used in Windows */
+ return 0xD;
+}
+
+/****************************************************************************
+REMARKS:
+Set the location of the OS console cursor.
+****************************************************************************/
+void PM_setOSCursorLocation(
+ int x,
+ int y)
+{
+ /* Nothing to do for Windows */
+ (void)x;
+ (void)y;
+}
+
+/****************************************************************************
+REMARKS:
+Set the width of the OS console.
+****************************************************************************/
+void PM_setOSScreenWidth(
+ int width,
+ int height)
+{
+ /* Nothing to do for Windows */
+ (void)width;
+ (void)height;
+}
+
+/****************************************************************************
+REMARKS:
+Set the real time clock handler (used for software stereo modes).
+****************************************************************************/
+ibool PMAPI PM_setRealTimeClockHandler(
+ PM_intHandler ih,
+ int frequency)
+{
+ /* We do not support this from Win32 programs. Rather the VxD handles
+ * this stuff it will take care of hooking the stereo flip functions at
+ * the VxD level.
+ */
+ (void)ih;
+ (void)frequency;
+ return false;
+}
+
+/****************************************************************************
+REMARKS:
+Set the real time clock frequency (for stereo modes).
+****************************************************************************/
+void PMAPI PM_setRealTimeClockFrequency(
+ int frequency)
+{
+ /* Not supported under Win32 */
+ (void)frequency;
+}
+
+/****************************************************************************
+REMARKS:
+Restore the original real time clock handler.
+****************************************************************************/
+void PMAPI PM_restoreRealTimeClockHandler(void)
+{
+ /* Not supported under Win32 */
+}
+
+/****************************************************************************
+REMARKS:
+Return the current operating system path or working directory.
+****************************************************************************/
+char * PMAPI PM_getCurrentPath(
+ char *path,
+ int maxLen)
+{
+ return getcwd(path,maxLen);
+}
+
+/****************************************************************************
+REMARKS:
+Query a string from the registry (extended version).
+****************************************************************************/
+static ibool REG_queryStringEx(
+ HKEY hKey,
+ const char *szValue,
+ char *value,
+ ulong size)
+{
+ DWORD type;
+
+ if (RegQueryValueEx(hKey,(PCHAR)szValue,(PDWORD)NULL,(PDWORD)&type,(LPBYTE)value,(PDWORD)&size) == ERROR_SUCCESS)
+ return true;
+ return false;
+}
+
+/****************************************************************************
+REMARKS:
+Query a string from the registry.
+****************************************************************************/
+static ibool REG_queryString(
+ const char *szKey,
+ const char *szValue,
+ char *value,
+ DWORD size)
+{
+ HKEY hKey;
+ ibool status = false;
+
+ memset(value,0,sizeof(value));
+ if (RegOpenKey(HKEY_LOCAL_MACHINE,szKey,&hKey) == ERROR_SUCCESS) {
+ status = REG_queryStringEx(hKey,szValue,value,size);
+ RegCloseKey(hKey);
+ }
+ return status;
+}
+
+/****************************************************************************
+REMARKS:
+Return the drive letter for the boot drive.
+****************************************************************************/
+char PMAPI PM_getBootDrive(void)
+{
+ static char path[256];
+ GetSystemDirectory(path,sizeof(path));
+ return path[0];
+}
+
+/****************************************************************************
+REMARKS:
+Return the path to the VBE/AF driver files.
+****************************************************************************/
+const char * PMAPI PM_getVBEAFPath(void)
+{
+ return "c:\\";
+}
+
+/****************************************************************************
+REMARKS:
+Return the path to the Nucleus driver files.
+****************************************************************************/
+const char * PMAPI PM_getNucleusPath(void)
+{
+ static char path[256];
+ char *env;
+
+ if ((env = getenv("NUCLEUS_PATH")) != NULL)
+ return env;
+ GetSystemDirectory(path,sizeof(path));
+ strcat(path,"\\nucleus");
+ return path;
+}
+
+/****************************************************************************
+REMARKS:
+Return the path to the Nucleus configuration files.
+****************************************************************************/
+const char * PMAPI PM_getNucleusConfigPath(void)
+{
+ static char path[256];
+ strcpy(path,PM_getNucleusPath());
+ PM_backslash(path);
+ strcat(path,"config");
+ return path;
+}
+
+/****************************************************************************
+REMARKS:
+Return a unique identifier for the machine if possible.
+****************************************************************************/
+const char * PMAPI PM_getUniqueID(void)
+{
+ return PM_getMachineName();
+}
+
+/****************************************************************************
+REMARKS:
+Get the name of the machine on the network.
+****************************************************************************/
+const char * PMAPI PM_getMachineName(void)
+{
+ static char name[256];
+
+ if (REG_queryString(szMachineNameKey,szMachineName,name,sizeof(name)))
+ return name;
+ if (REG_queryString(szMachineNameKeyNT,szMachineName,name,sizeof(name)))
+ return name;
+ return "Unknown";
+}
+
+/****************************************************************************
+REMARKS:
+Return a pointer to the real mode BIOS data area.
+****************************************************************************/
+void * PMAPI PM_getBIOSPointer(void)
+{
+ if (_PM_haveWinNT) {
+ /* On Windows NT we have to map it physically directly */
+ return PM_mapPhysicalAddr(0x400, 0x1000, true);
+ }
+ else {
+ /* For Windows 9x we can access this memory directly */
+ return (void*)0x400;
+ }
+}
+
+/****************************************************************************
+REMARKS:
+Return a pointer to 0xA0000 physical VGA graphics framebuffer.
+****************************************************************************/
+void * PMAPI PM_getA0000Pointer(void)
+{
+ if (_PM_haveWinNT) {
+ /* On Windows NT we have to map it physically directly */
+ return PM_mapPhysicalAddr(0xA0000, 0x0FFFF, false);
+ }
+ else {
+ /* Always use the 0xA0000 linear address so that we will use
+ * whatever page table mappings are set up for us (ie: for virtual
+ * bank switching.
+ */
+ return (void*)0xA0000;
+ }
+}
+
+/****************************************************************************
+REMARKS:
+Map a physical address to a linear address in the callers process.
+****************************************************************************/
+void * PMAPI PM_mapPhysicalAddr(
+ ulong base,
+ ulong limit,
+ ibool isCached)
+{
+ DWORD inBuf[3]; /* Buffer to send data to VxD */
+ DWORD outBuf[1]; /* Buffer to receive data from VxD */
+ DWORD count; /* Count of bytes returned from VxD */
+
+ if (!inited)
+ PM_init();
+ inBuf[0] = base;
+ inBuf[1] = limit;
+ inBuf[2] = isCached;
+ CHECK_FOR_PMHELP();
+ if (DeviceIoControl(_PM_hDevice, PMHELP_MAPPHYS32, inBuf, sizeof(inBuf),
+ outBuf, sizeof(outBuf), &count, NULL))
+ return (void*)outBuf[0];
+ return NULL;
+}
+
+/****************************************************************************
+REMARKS:
+Free a physical address mapping allocated by PM_mapPhysicalAddr.
+****************************************************************************/
+void PMAPI PM_freePhysicalAddr(
+ void *ptr,
+ ulong limit)
+{
+ /* We never free the mappings under Win32 (the VxD tracks them and
+ * reissues the same mappings until the system is rebooted).
+ */
+ (void)ptr;
+ (void)limit;
+}
+
+/****************************************************************************
+REMARKS:
+Find the physical address of a linear memory address in current process.
+****************************************************************************/
+ulong PMAPI PM_getPhysicalAddr(
+ void *p)
+{
+ DWORD inBuf[1]; /* Buffer to send data to VxD */
+ DWORD outBuf[1]; /* Buffer to receive data from VxD */
+ DWORD count; /* Count of bytes returned from VxD */
+
+ if (!inited)
+ PM_init();
+ inBuf[0] = (ulong)p;
+ CHECK_FOR_PMHELP();
+ if (DeviceIoControl(_PM_hDevice, PMHELP_GETPHYSICALADDR32, inBuf, sizeof(inBuf),
+ outBuf, sizeof(outBuf), &count, NULL))
+ return outBuf[0];
+ return 0xFFFFFFFFUL;
+}
+
+/****************************************************************************
+REMARKS:
+Find the physical address of a linear memory address in current process.
+****************************************************************************/
+ibool PMAPI PM_getPhysicalAddrRange(
+ void *p,
+ ulong length,
+ ulong *physAddress)
+{
+ DWORD inBuf[3]; /* Buffer to send data to VxD */
+ DWORD outBuf[1]; /* Buffer to receive data from VxD */
+ DWORD count; /* Count of bytes returned from VxD */
+
+ if (!inited)
+ PM_init();
+ inBuf[0] = (ulong)p;
+ inBuf[1] = (ulong)length;
+ inBuf[2] = (ulong)physAddress;
+ CHECK_FOR_PMHELP();
+ if (DeviceIoControl(_PM_hDevice, PMHELP_GETPHYSICALADDRRANGE32, inBuf, sizeof(inBuf),
+ outBuf, sizeof(outBuf), &count, NULL))
+ return outBuf[0];
+ return false;
+}
+
+/****************************************************************************
+REMARKS:
+Sleep for the specified number of milliseconds.
+****************************************************************************/
+void PMAPI PM_sleep(
+ ulong milliseconds)
+{
+ Sleep(milliseconds);
+}
+
+/****************************************************************************
+REMARKS:
+Return the base I/O port for the specified COM port.
+****************************************************************************/
+int PMAPI PM_getCOMPort(int port)
+{
+ // TODO: Re-code this to determine real values using the Plug and Play
+ // manager for the OS.
+ switch (port) {
+ case 0: return 0x3F8;
+ case 1: return 0x2F8;
+ case 2: return 0x3E8;
+ case 3: return 0x2E8;
+ }
+ return 0;
+}
+
+/****************************************************************************
+REMARKS:
+Return the base I/O port for the specified LPT port.
+****************************************************************************/
+int PMAPI PM_getLPTPort(int port)
+{
+ // TODO: Re-code this to determine real values using the Plug and Play
+ // manager for the OS.
+ switch (port) {
+ case 0: return 0x3BC;
+ case 1: return 0x378;
+ case 2: return 0x278;
+ }
+ return 0;
+}
+
+/****************************************************************************
+REMARKS:
+Allocate a block of shared memory. For Win9x we allocate shared memory
+as locked, global memory that is accessible from any memory context
+(including interrupt time context), which allows us to load our important
+data structure and code such that we can access it directly from a ring
+0 interrupt context.
+****************************************************************************/
+void * PMAPI PM_mallocShared(
+ long size)
+{
+ DWORD inBuf[1]; /* Buffer to send data to VxD */
+ DWORD outBuf[1]; /* Buffer to receive data from VxD */
+ DWORD count; /* Count of bytes returned from VxD */
+
+ inBuf[0] = size;
+ CHECK_FOR_PMHELP();
+ if (DeviceIoControl(_PM_hDevice, PMHELP_MALLOCSHARED32, inBuf, sizeof(inBuf),
+ outBuf, sizeof(outBuf), &count, NULL))
+ return (void*)outBuf[0];
+ return NULL;
+}
+
+/****************************************************************************
+REMARKS:
+Free a block of shared memory.
+****************************************************************************/
+void PMAPI PM_freeShared(
+ void *ptr)
+{
+ DWORD inBuf[1]; /* Buffer to send data to VxD */
+
+ inBuf[0] = (ulong)ptr;
+ CHECK_FOR_PMHELP();
+ DeviceIoControl(_PM_hDevice, PMHELP_FREESHARED32, inBuf, sizeof(inBuf), NULL, 0, NULL, NULL);
+}
+
+/****************************************************************************
+REMARKS:
+Map a linear memory address to the calling process address space. The
+address will have been allocated in another process using the
+PM_mapPhysicalAddr function.
+****************************************************************************/
+void * PMAPI PM_mapToProcess(
+ void *base,
+ ulong limit)
+{
+ (void)base;
+ (void)limit;
+ return base;
+}
+
+/****************************************************************************
+REMARKS:
+Map a real mode pointer to a protected mode pointer.
+****************************************************************************/
+void * PMAPI PM_mapRealPointer(
+ uint r_seg,
+ uint r_off)
+{
+ return (void*)(MK_PHYS(r_seg,r_off));
+}
+
+/****************************************************************************
+REMARKS:
+Allocate a block of real mode memory
+****************************************************************************/
+void * PMAPI PM_allocRealSeg(
+ uint size,
+ uint *r_seg,
+ uint *r_off)
+{
+ /* We do not support dynamically allocating real mode memory buffers
+ * from Win32 programs (we need a 16-bit DLL for this, and Windows
+ * 9x becomes very unstable if you free the memory blocks out of order).
+ */
+ (void)size;
+ (void)r_seg;
+ (void)r_off;
+ return NULL;
+}
+
+/****************************************************************************
+REMARKS:
+Free a block of real mode memory.
+****************************************************************************/
+void PMAPI PM_freeRealSeg(
+ void *mem)
+{
+ /* Not supported in Windows */
+ (void)mem;
+}
+
+/****************************************************************************
+REMARKS:
+Issue a real mode interrupt (parameters in DPMI compatible structure)
+****************************************************************************/
+void PMAPI DPMI_int86(
+ int intno,
+ DPMI_regs *regs)
+{
+ DWORD inBuf[2]; /* Buffer to send data to VxD */
+ DWORD count; /* Count of bytes returned from VxD */
+
+ if (!inited)
+ PM_init();
+ inBuf[0] = intno;
+ inBuf[1] = (ulong)regs;
+ CHECK_FOR_PMHELP();
+ DeviceIoControl(_PM_hDevice, PMHELP_DPMIINT8632, inBuf, sizeof(inBuf),
+ NULL, 0, &count, NULL);
+}
+
+/****************************************************************************
+REMARKS:
+Issue a real mode interrupt.
+****************************************************************************/
+int PMAPI PM_int86(
+ int intno,
+ RMREGS *in,
+ RMREGS *out)
+{
+ DWORD inBuf[3]; /* Buffer to send data to VxD */
+ DWORD outBuf[1]; /* Buffer to receive data from VxD */
+ DWORD count; /* Count of bytes returned from VxD */
+
+ if (!inited)
+ PM_init();
+ inBuf[0] = intno;
+ inBuf[1] = (ulong)in;
+ inBuf[2] = (ulong)out;
+ CHECK_FOR_PMHELP();
+ if (DeviceIoControl(_PM_hDevice, PMHELP_INT8632, inBuf, sizeof(inBuf),
+ outBuf, sizeof(outBuf), &count, NULL))
+ return outBuf[0];
+ return 0;
+}
+
+/****************************************************************************
+REMARKS:
+Issue a real mode interrupt.
+****************************************************************************/
+int PMAPI PM_int86x(
+ int intno,
+ RMREGS *in,
+ RMREGS *out,
+ RMSREGS *sregs)
+{
+ DWORD inBuf[4]; /* Buffer to send data to VxD */
+ DWORD outBuf[1]; /* Buffer to receive data from VxD */
+ DWORD count; /* Count of bytes returned from VxD */
+
+ if (!inited)
+ PM_init();
+ inBuf[0] = intno;
+ inBuf[1] = (ulong)in;
+ inBuf[2] = (ulong)out;
+ inBuf[3] = (ulong)sregs;
+ CHECK_FOR_PMHELP();
+ if (DeviceIoControl(_PM_hDevice, PMHELP_INT86X32, inBuf, sizeof(inBuf),
+ outBuf, sizeof(outBuf), &count, NULL))
+ return outBuf[0];
+ return 0;
+}
+
+/****************************************************************************
+REMARKS:
+Call a real mode far function.
+****************************************************************************/
+void PMAPI PM_callRealMode(
+ uint seg,
+ uint off,
+ RMREGS *in,
+ RMSREGS *sregs)
+{
+ DWORD inBuf[4]; /* Buffer to send data to VxD */
+ DWORD count; /* Count of bytes returned from VxD */
+
+ if (!inited)
+ PM_init();
+ inBuf[0] = seg;
+ inBuf[1] = off;
+ inBuf[2] = (ulong)in;
+ inBuf[3] = (ulong)sregs;
+ CHECK_FOR_PMHELP();
+ DeviceIoControl(_PM_hDevice, PMHELP_CALLREALMODE32, inBuf, sizeof(inBuf),
+ NULL, 0, &count, NULL);
+}
+
+/****************************************************************************
+REMARKS:
+Return the amount of available memory.
+****************************************************************************/
+void PMAPI PM_availableMemory(
+ ulong *physical,
+ ulong *total)
+{
+ /* We don't support this under Win32 at the moment */
+ *physical = *total = 0;
+}
+
+/****************************************************************************
+REMARKS:
+Allocate a block of locked, physical memory for DMA operations.
+****************************************************************************/
+void * PMAPI PM_allocLockedMem(
+ uint size,
+ ulong *physAddr,
+ ibool contiguous,
+ ibool below16M)
+{
+ DWORD inBuf[4]; /* Buffer to send data to VxD */
+ DWORD outBuf[1]; /* Buffer to receive data from VxD */
+ DWORD count; /* Count of bytes returned from VxD */
+
+ if (!inited)
+ PM_init();
+ inBuf[0] = size;
+ inBuf[1] = (ulong)physAddr;
+ inBuf[2] = (ulong)contiguous;
+ inBuf[3] = (ulong)below16M;
+ CHECK_FOR_PMHELP();
+ if (DeviceIoControl(_PM_hDevice, PMHELP_ALLOCLOCKED32, inBuf, sizeof(inBuf),
+ outBuf, sizeof(outBuf), &count, NULL))
+ return (void*)outBuf[0];
+ return NULL;
+}
+
+/****************************************************************************
+REMARKS:
+Free a block of locked physical memory.
+****************************************************************************/
+void PMAPI PM_freeLockedMem(
+ void *p,
+ uint size,
+ ibool contiguous)
+{
+ DWORD inBuf[3]; /* Buffer to send data to VxD */
+ DWORD count; /* Count of bytes returned from VxD */
+
+ if (!inited)
+ PM_init();
+ inBuf[0] = (ulong)p;
+ inBuf[1] = size;
+ inBuf[2] = contiguous;
+ CHECK_FOR_PMHELP();
+ DeviceIoControl(_PM_hDevice, PMHELP_FREELOCKED32, inBuf, sizeof(inBuf),
+ NULL, 0, &count, NULL);
+}
+
+/****************************************************************************
+REMARKS:
+Allocates a page aligned and page sized block of memory
+****************************************************************************/
+void * PMAPI PM_allocPage(
+ ibool locked)
+{
+ DWORD inBuf[2]; /* Buffer to send data to VxD */
+ DWORD outBuf[1]; /* Buffer to receive data from VxD */
+ DWORD count; /* Count of bytes returned from VxD */
+
+ if (!inited)
+ PM_init();
+ inBuf[0] = locked;
+ CHECK_FOR_PMHELP();
+ if (DeviceIoControl(_PM_hDevice, PMHELP_ALLOCPAGE32, inBuf, sizeof(inBuf),
+ outBuf, sizeof(outBuf), &count, NULL))
+ return (void*)outBuf[0];
+ return NULL;
+}
+
+/****************************************************************************
+REMARKS:
+Free a page aligned and page sized block of memory
+****************************************************************************/
+void PMAPI PM_freePage(
+ void *p)
+{
+ DWORD inBuf[1]; /* Buffer to send data to VxD */
+ DWORD count; /* Count of bytes returned from VxD */
+
+ if (!inited)
+ PM_init();
+ inBuf[0] = (ulong)p;
+ CHECK_FOR_PMHELP();
+ DeviceIoControl(_PM_hDevice, PMHELP_FREEPAGE32, inBuf, sizeof(inBuf),
+ NULL, 0, &count, NULL);
+}
+
+/****************************************************************************
+REMARKS:
+Lock linear memory so it won't be paged.
+****************************************************************************/
+int PMAPI PM_lockDataPages(void *p,uint len,PM_lockHandle *lh)
+{
+ DWORD inBuf[2]; /* Buffer to send data to VxD */
+ DWORD outBuf[1]; /* Buffer to receive data from VxD */
+ DWORD count; /* Count of bytes returned from VxD */
+
+ inBuf[0] = (ulong)p;
+ inBuf[1] = len;
+ inBuf[2] = (ulong)lh;
+ CHECK_FOR_PMHELP();
+ if (DeviceIoControl(_PM_hDevice, PMHELP_LOCKDATAPAGES32, inBuf, sizeof(inBuf),
+ outBuf, sizeof(outBuf), &count, NULL))
+ return outBuf[0];
+ return 0;
+}
+
+/****************************************************************************
+REMARKS:
+Unlock linear memory so it won't be paged.
+****************************************************************************/
+int PMAPI PM_unlockDataPages(void *p,uint len,PM_lockHandle *lh)
+{
+ DWORD inBuf[2]; /* Buffer to send data to VxD */
+ DWORD outBuf[1]; /* Buffer to receive data from VxD */
+ DWORD count; /* Count of bytes returned from VxD */
+
+ inBuf[0] = (ulong)p;
+ inBuf[1] = len;
+ inBuf[2] = (ulong)lh;
+ CHECK_FOR_PMHELP();
+ if (DeviceIoControl(_PM_hDevice, PMHELP_UNLOCKDATAPAGES32, inBuf, sizeof(inBuf),
+ outBuf, sizeof(outBuf), &count, NULL))
+ return outBuf[0];
+ return 0;
+}
+
+/****************************************************************************
+REMARKS:
+Lock linear memory so it won't be paged.
+****************************************************************************/
+int PMAPI PM_lockCodePages(void (*p)(),uint len,PM_lockHandle *lh)
+{
+ DWORD inBuf[2]; /* Buffer to send data to VxD */
+ DWORD outBuf[1]; /* Buffer to receive data from VxD */
+ DWORD count; /* Count of bytes returned from VxD */
+
+ inBuf[0] = (ulong)p;
+ inBuf[1] = len;
+ inBuf[2] = (ulong)lh;
+ CHECK_FOR_PMHELP();
+ if (DeviceIoControl(_PM_hDevice, PMHELP_LOCKCODEPAGES32, inBuf, sizeof(inBuf),
+ outBuf, sizeof(outBuf), &count, NULL))
+ return outBuf[0];
+ return 0;
+}
+
+/****************************************************************************
+REMARKS:
+Unlock linear memory so it won't be paged.
+****************************************************************************/
+int PMAPI PM_unlockCodePages(void (*p)(),uint len,PM_lockHandle *lh)
+{
+ DWORD inBuf[2]; /* Buffer to send data to VxD */
+ DWORD outBuf[1]; /* Buffer to receive data from VxD */
+ DWORD count; /* Count of bytes returned from VxD */
+
+ inBuf[0] = (ulong)p;
+ inBuf[1] = len;
+ inBuf[2] = (ulong)lh;
+ CHECK_FOR_PMHELP();
+ if (DeviceIoControl(_PM_hDevice, PMHELP_UNLOCKCODEPAGES32, inBuf, sizeof(inBuf),
+ outBuf, sizeof(outBuf), &count, NULL))
+ return outBuf[0];
+ return 0;
+}
+
+/****************************************************************************
+REMARKS:
+Call the VBE/Core software interrupt to change display banks.
+****************************************************************************/
+void PMAPI PM_setBankA(
+ int bank)
+{
+ RMREGS regs;
+ regs.x.ax = 0x4F05;
+ regs.x.bx = 0x0000;
+ regs.x.dx = bank;
+ PM_int86(0x10,&regs,&regs);
+}
+
+/****************************************************************************
+REMARKS:
+Call the VBE/Core software interrupt to change display banks.
+****************************************************************************/
+void PMAPI PM_setBankAB(
+ int bank)
+{
+ RMREGS regs;
+ regs.x.ax = 0x4F05;
+ regs.x.bx = 0x0000;
+ regs.x.dx = bank;
+ PM_int86(0x10,&regs,&regs);
+ regs.x.ax = 0x4F05;
+ regs.x.bx = 0x0001;
+ regs.x.dx = bank;
+ PM_int86(0x10,&regs,&regs);
+}
+
+/****************************************************************************
+REMARKS:
+Call the VBE/Core software interrupt to change display start address.
+****************************************************************************/
+void PMAPI PM_setCRTStart(
+ int x,
+ int y,
+ int waitVRT)
+{
+ RMREGS regs;
+ regs.x.ax = 0x4F07;
+ regs.x.bx = waitVRT;
+ regs.x.cx = x;
+ regs.x.dx = y;
+ PM_int86(0x10,&regs,&regs);
+}
+
+/****************************************************************************
+REMARKS:
+Enable write combining for the memory region.
+****************************************************************************/
+ibool PMAPI PM_enableWriteCombine(
+ ulong base,
+ ulong length,
+ uint type)
+{
+ DWORD inBuf[3]; /* Buffer to send data to VxD */
+ DWORD outBuf[1]; /* Buffer to receive data from VxD */
+ DWORD count; /* Count of bytes returned from VxD */
+
+ if (!inited)
+ PM_init();
+ inBuf[0] = base;
+ inBuf[1] = length;
+ inBuf[2] = type;
+ CHECK_FOR_PMHELP();
+ if (DeviceIoControl(_PM_hDevice, PMHELP_ENABLELFBCOMB32, inBuf, sizeof(inBuf),
+ outBuf, sizeof(outBuf), &count, NULL))
+ return outBuf[0];
+ return false;
+}
+
+/****************************************************************************
+REMARKS:
+Get the page directory base register value
+****************************************************************************/
+ulong PMAPI _PM_getPDB(void)
+{
+ DWORD outBuf[1]; /* Buffer to receive data from VxD */
+ DWORD count; /* Count of bytes returned from VxD */
+
+ CHECK_FOR_PMHELP();
+ if (DeviceIoControl(_PM_hDevice, PMHELP_GETPDB32, NULL, 0,
+ outBuf, sizeof(outBuf), &count, NULL))
+ return outBuf[0];
+ return 0;
+}
+
+/****************************************************************************
+REMARKS:
+Flush the translation lookaside buffer.
+****************************************************************************/
+void PMAPI PM_flushTLB(void)
+{
+ CHECK_FOR_PMHELP();
+ DeviceIoControl(_PM_hDevice, PMHELP_FLUSHTLB32, NULL, 0, NULL, 0, NULL, NULL);
+}
+
+/****************************************************************************
+REMARKS:
+Execute the POST on the secondary BIOS for a controller.
+****************************************************************************/
+ibool PMAPI PM_doBIOSPOST(
+ ushort axVal,
+ ulong BIOSPhysAddr,
+ void *mappedBIOS,
+ ulong BIOSLen)
+{
+ /* This is never done by Win32 programs, but rather done by the VxD
+ * when the system boots.
+ */
+ (void)axVal;
+ (void)BIOSPhysAddr;
+ (void)mappedBIOS;
+ (void)BIOSLen;
+ return false;
+}
+
+/****************************************************************************
+REMARKS:
+Load an OS specific shared library or DLL. If the OS does not support
+shared libraries, simply return NULL.
+****************************************************************************/
+PM_MODULE PMAPI PM_loadLibrary(
+ const char *szDLLName)
+{
+ return (PM_MODULE)LoadLibrary(szDLLName);
+}
+
+/****************************************************************************
+REMARKS:
+Get the address of a named procedure from a shared library.
+****************************************************************************/
+void * PMAPI PM_getProcAddress(
+ PM_MODULE hModule,
+ const char *szProcName)
+{
+ return (void*)GetProcAddress((HINSTANCE)hModule,szProcName);
+}
+
+/****************************************************************************
+REMARKS:
+Unload a shared library.
+****************************************************************************/
+void PMAPI PM_freeLibrary(
+ PM_MODULE hModule)
+{
+ FreeLibrary((HINSTANCE)hModule);
+}
+
+/****************************************************************************
+REMARKS:
+Internal function to convert the find data to the generic interface.
+****************************************************************************/
+static void convertFindData(
+ PM_findData *findData,
+ WIN32_FIND_DATA *blk)
+{
+ ulong dwSize = findData->dwSize;
+
+ memset(findData,0,findData->dwSize);
+ findData->dwSize = dwSize;
+ if (blk->dwFileAttributes & FILE_ATTRIBUTE_READONLY)
+ findData->attrib |= PM_FILE_READONLY;
+ if (blk->dwFileAttributes & FILE_ATTRIBUTE_DIRECTORY)
+ findData->attrib |= PM_FILE_DIRECTORY;
+ if (blk->dwFileAttributes & FILE_ATTRIBUTE_ARCHIVE)
+ findData->attrib |= PM_FILE_ARCHIVE;
+ if (blk->dwFileAttributes & FILE_ATTRIBUTE_HIDDEN)
+ findData->attrib |= PM_FILE_HIDDEN;
+ if (blk->dwFileAttributes & FILE_ATTRIBUTE_SYSTEM)
+ findData->attrib |= PM_FILE_SYSTEM;
+ findData->sizeLo = blk->nFileSizeLow;
+ findData->sizeHi = blk->nFileSizeHigh;
+ strncpy(findData->name,blk->cFileName,PM_MAX_PATH);
+ findData->name[PM_MAX_PATH-1] = 0;
+}
+
+/****************************************************************************
+REMARKS:
+Function to find the first file matching a search criteria in a directory.
+****************************************************************************/
+void *PMAPI PM_findFirstFile(
+ const char *filename,
+ PM_findData *findData)
+{
+ WIN32_FIND_DATA blk;
+ HANDLE hfile;
+
+ if ((hfile = FindFirstFile(filename,&blk)) != INVALID_HANDLE_VALUE) {
+ convertFindData(findData,&blk);
+ return (void*)hfile;
+ }
+ return PM_FILE_INVALID;
+}
+
+/****************************************************************************
+REMARKS:
+Function to find the next file matching a search criteria in a directory.
+****************************************************************************/
+ibool PMAPI PM_findNextFile(
+ void *handle,
+ PM_findData *findData)
+{
+ WIN32_FIND_DATA blk;
+
+ if (FindNextFile((HANDLE)handle,&blk)) {
+ convertFindData(findData,&blk);
+ return true;
+ }
+ return false;
+}
+
+/****************************************************************************
+REMARKS:
+Function to close the find process
+****************************************************************************/
+void PMAPI PM_findClose(
+ void *handle)
+{
+ FindClose((HANDLE)handle);
+}
+
+/****************************************************************************
+REMARKS:
+Function to determine if a drive is a valid drive or not. Under Unix this
+function will return false for anything except a value of 3 (considered
+the root drive, and equivalent to C: for non-Unix systems). The drive
+numbering is:
+
+ 1 - Drive A:
+ 2 - Drive B:
+ 3 - Drive C:
+ etc
+
+****************************************************************************/
+ibool PMAPI PM_driveValid(
+ char drive)
+{
+ char buf[5];
+ int type;
+
+ sprintf(buf,"%c:\\", drive);
+ return ((type = GetDriveType(buf)) != 0 && type != 1);
+}
+
+/****************************************************************************
+REMARKS:
+Function to get the current working directory for the specififed drive.
+Under Unix this will always return the current working directory regardless
+of what the value of 'drive' is.
+****************************************************************************/
+void PMAPI PM_getdcwd(
+ int drive,
+ char *dir,
+ int len)
+{
+ // NT stores the current directory for drive N in the magic environment
+ // variable =N: so we simply look for that environment variable.
+ char envname[4];
+
+ envname[0] = '=';
+ envname[1] = drive - 1 + 'A';
+ envname[2] = ':';
+ envname[3] = '\0';
+ if (GetEnvironmentVariable(envname,dir,len) == 0) {
+ // The current directory or the drive has not been set yet, so
+ // simply set it to the root.
+ dir[0] = envname[1];
+ dir[1] = ':';
+ dir[2] = '\\';
+ dir[3] = '\0';
+ SetEnvironmentVariable(envname,dir);
+ }
+}
+
+/****************************************************************************
+REMARKS:
+Function to change the file attributes for a specific file.
+****************************************************************************/
+void PMAPI PM_setFileAttr(
+ const char *filename,
+ uint attrib)
+{
+ DWORD attr = 0;
+
+ if (attrib & PM_FILE_READONLY)
+ attr |= FILE_ATTRIBUTE_READONLY;
+ if (attrib & PM_FILE_ARCHIVE)
+ attr |= FILE_ATTRIBUTE_ARCHIVE;
+ if (attrib & PM_FILE_HIDDEN)
+ attr |= FILE_ATTRIBUTE_HIDDEN;
+ if (attrib & PM_FILE_SYSTEM)
+ attr |= FILE_ATTRIBUTE_SYSTEM;
+ SetFileAttributes((LPSTR)filename, attr);
+}
+
+/****************************************************************************
+REMARKS:
+Function to get the file attributes for a specific file.
+****************************************************************************/
+uint PMAPI PM_getFileAttr(
+ const char *filename)
+{
+ DWORD attr = GetFileAttributes(filename);
+ uint attrib = 0;
+
+ if (attr & FILE_ATTRIBUTE_READONLY)
+ attrib |= PM_FILE_READONLY;
+ if (attr & FILE_ATTRIBUTE_ARCHIVE)
+ attrib |= PM_FILE_ARCHIVE;
+ if (attr & FILE_ATTRIBUTE_HIDDEN)
+ attrib |= PM_FILE_HIDDEN;
+ if (attr & FILE_ATTRIBUTE_SYSTEM)
+ attrib |= PM_FILE_SYSTEM;
+ return attrib;
+}
+
+/****************************************************************************
+REMARKS:
+Function to create a directory.
+****************************************************************************/
+ibool PMAPI PM_mkdir(
+ const char *filename)
+{
+ return CreateDirectory(filename,NULL);
+}
+
+/****************************************************************************
+REMARKS:
+Function to remove a directory.
+****************************************************************************/
+ibool PMAPI PM_rmdir(
+ const char *filename)
+{
+ return RemoveDirectory(filename);
+}
+
+/****************************************************************************
+REMARKS:
+Function to get the file time and date for a specific file.
+****************************************************************************/
+ibool PMAPI PM_getFileTime(
+ const char *filename,
+ ibool gmTime,
+ PM_time *time)
+{
+ HFILE f;
+ OFSTRUCT of;
+ FILETIME utcTime,localTime;
+ SYSTEMTIME sysTime;
+ ibool status = false;
+
+ of.cBytes = sizeof(of);
+ if ((f = OpenFile(filename,&of,OF_READ)) == HFILE_ERROR)
+ return false;
+ if (!GetFileTime((HANDLE)f,NULL,NULL,&utcTime))
+ goto Exit;
+ if (!gmTime) {
+ if (!FileTimeToLocalFileTime(&utcTime,&localTime))
+ goto Exit;
+ }
+ else
+ localTime = utcTime;
+ if (!FileTimeToSystemTime(&localTime,&sysTime))
+ goto Exit;
+ time->year = sysTime.wYear;
+ time->mon = sysTime.wMonth-1;
+ time->day = sysTime.wYear;
+ time->hour = sysTime.wHour;
+ time->min = sysTime.wMinute;
+ time->sec = sysTime.wSecond;
+ status = true;
+
+Exit:
+ CloseHandle((HANDLE)f);
+ return status;
+}
+
+/****************************************************************************
+REMARKS:
+Function to set the file time and date for a specific file.
+****************************************************************************/
+ibool PMAPI PM_setFileTime(
+ const char *filename,
+ ibool gmTime,
+ PM_time *time)
+{
+ HFILE f;
+ OFSTRUCT of;
+ FILETIME utcTime,localTime;
+ SYSTEMTIME sysTime;
+ ibool status = false;
+
+ of.cBytes = sizeof(of);
+ if ((f = OpenFile(filename,&of,OF_WRITE)) == HFILE_ERROR)
+ return false;
+ sysTime.wYear = time->year;
+ sysTime.wMonth = time->mon+1;
+ sysTime.wYear = time->day;
+ sysTime.wHour = time->hour;
+ sysTime.wMinute = time->min;
+ sysTime.wSecond = time->sec;
+ if (!SystemTimeToFileTime(&sysTime,&localTime))
+ goto Exit;
+ if (!gmTime) {
+ if (!LocalFileTimeToFileTime(&localTime,&utcTime))
+ goto Exit;
+ }
+ else
+ utcTime = localTime;
+ if (!SetFileTime((HANDLE)f,NULL,NULL,&utcTime))
+ goto Exit;
+ status = true;
+
+Exit:
+ CloseHandle((HANDLE)f);
+ return status;
+}
+
diff --git a/board/MAI/bios_emulator/scitech/src/pm/win32/vflat.c b/board/MAI/bios_emulator/scitech/src/pm/win32/vflat.c
new file mode 100644
index 0000000000..70491cdb80
--- /dev/null
+++ b/board/MAI/bios_emulator/scitech/src/pm/win32/vflat.c
@@ -0,0 +1,53 @@
+/****************************************************************************
+*
+* SciTech OS Portability Manager 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: Any
+*
+* Description: Dummy module; no virtual framebuffer for this OS
+*
+****************************************************************************/
+
+#include "pmapi.h"
+
+ibool PMAPI VF_available(void)
+{
+ return false;
+}
+
+void * PMAPI VF_init(
+ ulong baseAddr,
+ int bankSize,
+ int codeLen,
+ void *bankFunc)
+{
+ (void)baseAddr;
+ (void)bankSize;
+ (void)codeLen;
+ (void)bankFunc;
+ return NULL;
+}
+
+void PMAPI VF_exit(void)
+{
+}
diff --git a/board/MAI/bios_emulator/scitech/src/pm/win32/ztimer.c b/board/MAI/bios_emulator/scitech/src/pm/win32/ztimer.c
new file mode 100644
index 0000000000..318929a2c0
--- /dev/null
+++ b/board/MAI/bios_emulator/scitech/src/pm/win32/ztimer.c
@@ -0,0 +1,136 @@
+/****************************************************************************
+*
+* Ultra Long Period Timer
+*
+* ========================================================================
+*
+* 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: OS specific implementation for the Zen Timer functions.
+*
+****************************************************************************/
+
+/*---------------------------- Global variables ---------------------------*/
+
+static CPU_largeInteger countFreq;
+static ibool havePerformanceCounter;
+static ulong start,finish;
+
+/*----------------------------- Implementation ----------------------------*/
+
+/****************************************************************************
+REMARKS:
+Initialise the Zen Timer module internals.
+****************************************************************************/
+void __ZTimerInit(void)
+{
+#ifdef NO_ASSEMBLER
+ havePerformanceCounter = false;
+#else
+ havePerformanceCounter = QueryPerformanceFrequency((LARGE_INTEGER*)&countFreq);
+#endif
+}
+
+/****************************************************************************
+REMARKS:
+Start the Zen Timer counting.
+****************************************************************************/
+static void __LZTimerOn(
+ LZTimerObject *tm)
+{
+ if (havePerformanceCounter)
+ QueryPerformanceCounter((LARGE_INTEGER*)&tm->start);
+ else
+ tm->start.low = timeGetTime();
+}
+
+/****************************************************************************
+REMARKS:
+Compute the lap time since the timer was started.
+****************************************************************************/
+static ulong __LZTimerLap(
+ LZTimerObject *tm)
+{
+ CPU_largeInteger tmLap,tmCount;
+
+ if (havePerformanceCounter) {
+ QueryPerformanceCounter((LARGE_INTEGER*)&tmLap);
+ _CPU_diffTime64(&tm->start,&tmLap,&tmCount);
+ return _CPU_calcMicroSec(&tmCount,countFreq.low);
+ }
+ else {
+ tmLap.low = timeGetTime();
+ return (tmLap.low - tm->start.low) * 1000L;
+ }
+}
+
+/****************************************************************************
+REMARKS:
+Stop the Zen Timer counting.
+****************************************************************************/
+static void __LZTimerOff(
+ LZTimerObject *tm)
+{
+ if (havePerformanceCounter)
+ QueryPerformanceCounter((LARGE_INTEGER*)&tm->end);
+ else
+ tm->end.low = timeGetTime();
+}
+
+/****************************************************************************
+REMARKS:
+Compute the elapsed time in microseconds between start and end timings.
+****************************************************************************/
+static ulong __LZTimerCount(
+ LZTimerObject *tm)
+{
+ CPU_largeInteger tmCount;
+
+ if (havePerformanceCounter) {
+ _CPU_diffTime64(&tm->start,&tm->end,&tmCount);
+ return _CPU_calcMicroSec(&tmCount,countFreq.low);
+ }
+ else
+ return (tm->end.low - tm->start.low) * 1000L;
+}
+
+/****************************************************************************
+REMARKS:
+Define the resolution of the long period timer as microseconds per timer tick.
+****************************************************************************/
+#define ULZTIMER_RESOLUTION 1000
+
+/****************************************************************************
+REMARKS:
+Read the Long Period timer from the OS
+****************************************************************************/
+static ulong __ULZReadTime(void)
+{ return timeGetTime(); }
+
+/****************************************************************************
+REMARKS:
+Compute the elapsed time from the BIOS timer tick. Note that we check to see
+whether a midnight boundary has passed, and if so adjust the finish time to
+account for this. We cannot detect if more that one midnight boundary has
+passed, so if this happens we will be generating erronous results.
+****************************************************************************/
+ulong __ULZElapsedTime(ulong start,ulong finish)
+{ return finish - start; }
OpenPOWER on IntegriCloud