📄 pm.c
字号:
PM_VIDEOPMI32Request(&Adapter,PMIREQUEST_SOFTWAREINT,&InitVDM,NULL); haveInt10 = true; } } } else { /* A GRADD driver isn't loaded, hence we can't use VIDEOPMI. But we will try * to access the mini-VDM directly, first verifying that the support is * available in the kernel (it should be for kernels that support GRADD). * This may be needed in a command line boot or if non-GRADD driver is * used (Matrox or classic VGA). * Note: because of problems with mini-VDM support in the kernel, we have to * spawn a daemon process that will do the actual mini-VDM access for us. */ /* Try to open shared semaphore to see if our daemon is already up */ if (DosOpenEventSem(SHAREDSEM, &hevDaemon) == NO_ERROR) { if (DosWaitEventSem(hevDaemon, 1) == NO_ERROR) { /* If semaphore is posted, all is well */ useVPMI = false; haveInt10 = true; } } else { /* Create shared event semaphore */ if (DosCreateEventSem(SHAREDSEM, &hevDaemon, DC_SEM_SHARED, FALSE) == NO_ERROR) { PM_findBPD(DAEMON_NAME, path); strcat(path, DAEMON_NAME); if (DosExecPgm(buf, sizeof(buf), EXEC_BACKGROUND, (PSZ)DAEMON_NAME, NULL, &resCodes, (PSZ)path) == NO_ERROR) { /* The daemon was successfully spawned, now give it a sec to come up */ if (DosWaitEventSem(hevDaemon, 2000) == NO_ERROR) { /* It's up! */ useVPMI = false; haveInt10 = true; } } } } } } return haveInt10;}/****************************************************************************REMARKS:We "probably" have BIOS access under OS/2 but we have to verify/initialize itfirst.****************************************************************************/ibool PMAPI PM_haveBIOSAccess(void){ return InitInt10();}/****************************************************************************REMARKS:Return the operating system type identifier.****************************************************************************/long PMAPI PM_getOSType(void){ return _OS_OS2;}/****************************************************************************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){ /* Be prepare to be called recursively (failed to fail situation :-) */ static int fatalErrorCount = 0; if (fatalErrorCount++ == 0) { if (fatalErrorCleanup) fatalErrorCleanup(); } fprintf(stderr,"%s\n", msg); 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){ if (!VESABuf_ptr) { /* Allocate a global buffer for communicating with the VESA VBE */ if ((VESABuf_ptr = PM_allocRealSeg(VESABuf_len, &VESABuf_rseg, &VESABuf_roff)) == NULL) return NULL; } *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){ KBDKEYINFO key; /* Must not cross a 64K boundary */ KbdPeek(&key, 0); return (key.fbStatus & KBDTRF_FINAL_CHAR_IN);}/****************************************************************************REMARKS:Wait for and return the next keypress.****************************************************************************/int PMAPI PM_getch(void){ KBDKEYINFO key; /* Must not cross a 64K boundary */ KbdCharIn(&key,IO_WAIT,0); return key.chChar;}/****************************************************************************REMARKS:Open a fullscreen console for output to the screen. This requires thatthe application be a fullscreen VIO program.****************************************************************************/PM_HWND PMAPI PM_openConsole( PM_HWND hwndUser, int device, int xRes, int yRes, int bpp, ibool fullScreen){ (void)hwndUser; (void)device; (void)xRes; (void)yRes; (void)bpp; (void)fullScreen; return 0;}/****************************************************************************REMARKS:Find the size of the console state buffer.****************************************************************************/int PMAPI PM_getConsoleStateSize(void){ VIOMODEINFO vmi; vmi.cb = sizeof (VIOMODEINFO); VioGetMode (&vmi, (HVIO)0); return sizeof (CONSOLE_SAVE) - 1 + vmi.col * vmi.row * 2;}/****************************************************************************REMARKS:Save the state of the console.****************************************************************************/void PMAPI PM_saveConsoleState( void *stateBuf, PM_HWND hwndConsole){ USHORT fblen; CONSOLE_SAVE *cs = (CONSOLE_SAVE*)stateBuf; VIOMODEINFO vmi; /* The reason for the VIOMODEINFO juggling is 16-bit code. Because the user * allocates the state buffer, cd->vmi might be crossing the 64K boundary and * the 16-bit API would fail. If we create another copy on stack, the compiler * should ensure that the 64K boundary will not be crossed (it adjusts the stack * if it should cross). */ vmi.cb = sizeof(VIOMODEINFO); VioGetMode(&vmi,(HVIO)0); memcpy(&cs->vmi, &vmi, sizeof(VIOMODEINFO)); VioGetCurPos(&cs->CursorY, &cs->CursorX, (HVIO)0); fblen = cs->vmi.col * cs->vmi.row * 2; VioReadCellStr((PCH)cs->FrameBuffer, &fblen, 0, 0, (HVIO)0);}/* Global variable to communicate between threads */static SESWITCHREC SesSwitchRec = { -1 };/****************************************************************************REMARKS:Called by external routines at least once per frame to check whenever asession save/restore should be performed. Since we receive such notificationsasyncronously, we can't perform all required operations at that time.****************************************************************************/void __PM_checkConsoleSwitch(void){ int Flags, Mode; PM_saveState_cb Callback; /* Quick optimized path for most common case */ if (SesSwitchRec.Flags == -1) return;again: if (DosRequestMutexSem(SesSwitchRec.Mutex, 100)) return; Flags = SesSwitchRec.Flags; Callback = SesSwitchRec.Callback; SesSwitchRec.Flags = -1; DosReleaseMutexSem(SesSwitchRec.Mutex); isSessionSwitching = true; /* Prevent VIO calls */ Mode = Callback(Flags); isSessionSwitching = false; DosPostEventSem(SesSwitchRec.Event); if (Flags == PM_DEACTIVATE && Mode == PM_SUSPEND_APP) /* Suspend application until we switch back to our application */ for (;;) { DosSleep (500); /* SesSwitchRec.Flags is volatile so optimizer * won't load it into a register */ if (SesSwitchRec.Flags != -1) goto again; }}/****************************************************************************REMARKS:Waits until main thread processes the session switch event.****************************************************************************/static void _PM_SessionSwitchEvent( PM_saveState_cb saveState, int flags){ ULONG Count; if (DosRequestMutexSem(SesSwitchRec.Mutex, 10000)) return; /* We're going to wait on that semaphore */ DosResetEventSem(SesSwitchRec.Event, &Count); SesSwitchRec.Callback = saveState; SesSwitchRec.Flags = flags; DosReleaseMutexSem(SesSwitchRec.Mutex); /* Now wait until all required operations are complete */ DosWaitEventSem (SesSwitchRec.Event, 10000);}/****************************************************************************REMARKS:This is the thread responsible for tracking switches back to ourfullscreen session.****************************************************************************/static void _PM_ConsoleSwitch( PM_saveState_cb saveState){ USHORT NotifyType; for (;;) { if (VioModeWait(VMWR_POPUP, &NotifyType, 0) != 0) break; _PM_SessionSwitchEvent(saveState, PM_REACTIVATE); } VioModeUndo(UNDOI_RELEASEOWNER, UNDOK_ERRORCODE, (HVIO)0);}/****************************************************************************REMARKS:This is the thread responsible for tracking screen popups (usually fatalerror handler uses them).****************************************************************************/static void _PM_ConsolePopup( PM_saveState_cb saveState){ USHORT NotifyType; for (;;) { if (VioSavRedrawWait(VSRWI_SAVEANDREDRAW, &NotifyType, 0) != 0) break; if (NotifyType == VSRWN_SAVE) _PM_SessionSwitchEvent(saveState, PM_DEACTIVATE); else if (NotifyType == VSRWN_REDRAW) _PM_SessionSwitchEvent(saveState, PM_REACTIVATE); } VioSavRedrawUndo(UNDOI_RELEASEOWNER, UNDOK_ERRORCODE, (HVIO)0);}/****************************************************************************REMARKS:Set the suspend application callback for the fullscreen console.****************************************************************************/void PMAPI PM_setSuspendAppCallback( PM_saveState_cb saveState){ /* If PM isn't loaded, this stuff will cause crashes! */ if (__isShellLoaded()) { if (saveState) { /* Create the threads responsible for tracking console switches */ SesSwitchRec.Flags = -1; DosCreateMutexSem(NULL, &SesSwitchRec.Mutex, 0, FALSE); DosCreateEventSem(NULL, &SesSwitchRec.Event, 0, FALSE); _beginthread ((void(*)(void*))_PM_ConsoleSwitch,NULL,SESSION_SWITCH_STACK_SIZE, (void*)saveState); _beginthread ((void(*)(void*))_PM_ConsolePopup,NULL,SESSION_SWITCH_STACK_SIZE, (void*)saveState); } else { /* Kill the threads responsible for tracking console switches */ VioModeUndo(UNDOI_RELEASEOWNER, UNDOK_TERMINATE, (HVIO)0); VioSavRedrawUndo(UNDOI_RELEASEOWNER, UNDOK_TERMINATE, (HVIO)0); DosCloseEventSem(SesSwitchRec.Event); DosCloseMutexSem(SesSwitchRec.Mutex); } }}/****************************************************************************REMARKS:Restore the console state.****************************************************************************/void PMAPI PM_restoreConsoleState( const void *stateBuf, PM_HWND hwndConsole){ CONSOLE_SAVE *cs = (CONSOLE_SAVE *)stateBuf; VIOMODEINFO vmi; if (!cs) return; memcpy(&vmi, &cs->vmi, sizeof (VIOMODEINFO)); VioSetMode(&vmi, (HVIO)0); VioSetCurPos(cs->CursorY, cs->CursorX, (HVIO)0); VioWrtCellStr((PCH)cs->FrameBuffer, cs->vmi.col * cs->vmi.row * 2,0, 0, (HVIO)0);}/****************************************************************************REMARKS:Close the fullscreen console.****************************************************************************/void PMAPI PM_closeConsole( PM_HWND hwndConsole){ /* Kill the threads responsible for tracking console switches */ PM_setSuspendAppCallback(NULL); (void)hwndConsole;}/****************************************************************************REMARKS:Set the location of the OS console cursor.****************************************************************************/void PM_setOSCursorLocation( int x, int y){ /* If session switch is in progress, calling into VIO causes deadlocks! */ /* Also this call to VIO screws up our console library on DBCS boxes... */ if (!isSessionSwitching && !__IsDBCSSystem()) VioSetCurPos(y,x,0);}/****************************************************************************REMARKS:Set the width of the OS console.****************************************************************************/void PM_setOSScreenWidth( int width, int height){ /* Nothing to do in here */ (void)width;
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -