pm.c

来自「适合KS8695X」· C语言 代码 · 共 1,995 行 · 第 1/5 页

C
1,995
字号
		     * (but GRADD won't run on them so this is superfluous ;-).
		     */
		    INITVDM InitVDM = {VDM_INITIALIZE,NULL,NULL};
		    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 it
first.
****************************************************************************/
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 that
the 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 a
session save/restore should be performed. Since we receive such notifications
asyncronously, 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 our
fullscreen 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 fatal
error 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.
****************************************************************************/

⌨️ 快捷键说明

复制代码Ctrl + C
搜索代码Ctrl + F
全屏模式F11
增大字号Ctrl + =
减小字号Ctrl + -
显示快捷键?