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 + -
显示快捷键?