How to Write Directly to Video Memory Under OS/2

ID Number: Q59837

5.10

OS/2

Question:

I am porting an application from DOS to OS/2 that writes directly to

screen memory. If I run it from OS/2, it gives me a protection

violation whenever I attempt to write directly to screen memory. How

is this done under OS/2?

Response:

Under OS/2, you can use the VioGetPhysBuf API call to obtain a 16-bit

segment selector to the physical screen buffer. You can then use the

MAKEP macro to obtain a 32-bit far pointer to screen memory.

It is important to note that your program MUST be the current

foreground session when writing to the screen buffer obtained by

VioGetPhysBuf. If you switch the program to the background, OS/2

temporarily invalidates the selectors to protect the integrity of the

display. Any attempt to write to these selectors when the process is

not in the foreground results in a general protection violation. You

can use the VioScrLock API to ensure that your process will not be

swapped to the background while writing to the video buffer.

More Information:

The following program demonstrates how to write directly to the

monochrome screen buffer under OS/2.

Sample Code

-----------

/*

* MONO.C

*

* Writes directly to the monochrome screen buffer.

*

* Uses VioScrLock and VioScrUnlock to ensure that the program doesn't

* get swapped to the background while writing to the video buffer.

*

* This program basically clears the monochrome screen buffer.

*

*/

#define INCL_VIO

#define INCL_DOSPROCESS

#define MONOBUF (char far *) 0xB0000L /* Address of mono screen

/* buffer */

#define BYTE_SIZE 4000 /* 80x25 * 2 */

#include <os2.h>

#include <stdio.h>

#include <conio.h>

void main (void)

{

VIOPHYSBUF viopbBuf;

PCH pchScreen;

USHORT usStatus;

int i;

viopbBuf.pBuf = MONOBUF;

viopbBuf.cb = BYTE_SIZE;

/* Lock the video buffer so bad things don't happen. */

VioScrLock(LOCKIO_NOWAIT, (PBYTE) &usStatus, 0);

if (usStatus != LOCK_SUCCESS) {

printf ("ERROR: Somebody else has the video buffer.\n");

DosExit (EXIT_PROCESS, usStatus);

}

/* Grab the video buffer. */

usStatus = VioGetPhysBuf(&viopbBuf, 0);

if (usStatus) {

printf ("VioGetPhysBuf failed returncode %d.\n",usStatus);

DosExit (EXIT_PROCESS, usStatus);

}

/* Make a 32 bit pointer from a segment selector. */

pchScreen = MAKEP(viopbBuf.asel[0], 0);

/* Loop through memory writing spaces. Jump over attribute byte.*/

for (i=0; i < BYTE_SIZE; i+=2)

pchScreen[i] = ' ';

/* We're done, so we can unlock the video buffer. */

VioScrUnLock(0);

}