Mail Archives: djgpp/1996/09/30/23:27:43
From: | Eric Rudd <rudd AT cyberoptics DOT com>
|
Newsgroups: | comp.os.msdos.djgpp
|
Subject: | Linear Frame Buffer Programming
|
Date: | 30 Sep 1996 16:13:00 GMT
|
Organization: | CyberOptics Corp
|
Lines: | 95
|
Message-ID: | <52oric$hop@hagar.cyberoptics.com>
|
NNTP-Posting-Host: | rudd.cyberoptics.com
|
Mime-Version: | 1.0
|
To: | djgpp AT delorie DOT com
|
DJ-Gateway: | from newsgroup comp.os.msdos.djgpp
|
There seem to be a lot of DJGPP users interested in writing directly to
video memory, and I am one of them. For most users, SciTech Software's
UniVBE is probably the best solution, but there are copyright issues if I
place my programs up on the intranet at work, as well as the nuisance of
encapsulating each program within a batch file which loads the TSR,
launches the program, then finally unloads the TSR. This whole issue will
eventually become moot, when cards with built-in VBE 2.0 support become
more prevalent, but for now the problems remain.
So I wrote a set of low-level routines which enable the linear frame
buffer and switch to the appropriate video mode. The interface is similar
to the old "simple graphics library," LIBGR, from DJGPP v1.xx. The
writing of the driver for my ET4000/W32p-based card at home was fairly
easy; the driver for the S3 cards we use at work was a bear, especially
enabling the 8-bit DAC mode, but I have finally arrived at reasonable
functionality. I would make the code available, except that it's such a
brittle hack it's not really presentable in its present form. I based
most of the card-specific code on the information that I gleaned from Finn
Thoergersen's VGADOC4B, with some additional information from Dietmar
Meschede's "S3UNIT3.ZIP":
ftp://x2ftp.oulu.fi/pub/msdos/programming/pmode/s3unit3.zip
I have several outstanding questions regarding this type of programming:
1. I am using near pointers to access the video memory. I had been given
the impression that this effectively disables memory protection, but I
found that if I wrote so much as one byte beyond the limit requested from
DPMI, I got a page fault dump, which indicates that, at least on my
machine, memory protection is not entirely disabled. I welcome this
protection, but am puzzled as to why it exists. Short excerpts of the
relevant portions of the code, which is adapted from Charles W Sandmann's
VBETEST.C, follow:
int _crt0_startup_flags = _CRT0_FLAG_NEARPTR | _CRT0_FLAG_NONMOVE_SBRK;
.
.
.
info.size = width*height*BytesPerPixel;
info.address = (int) PhysBasePtr;
if (__dpmi_physical_address_mapping(&info) == -1) {
return 2; /* Physical mapping of address PhysBasePtr failed. */
}
VideoBase = (void *) info.address; /* Updated by above call */
(char *) VideoBase += __djgpp_conventional_base;
I then access video memory by references like
((char *) VideoBase)[offset] = GrayValue;
2. On my home computer, if a program bombs while the linear frame buffer
is enabled, the DJGPP cleanup routines (wherever they are) do not reset
the video mode to anything useful, probably due to a deficiency in the
card's BIOS. Thus, the dump goes off into the ether, and I have to re-run
the program with REDIR.EXE just in order to capture the error output. This
is manifestly inconvenient, and I wonder how best to deal with this
problem. (After a couple of such bombs, I got wise and wrote a short
command-line utility to reset the video mode, which I invoke by blindly
typing it in, as the screen flashes garbage. This at least saves me from
re-booting.) I have thought of three solutions, besides the obvious one
(get a new video card):
1. Patch the cleanup code, so that it properly resets the video mode.
The problem with this approach is that I have no idea where the
cleanup source code is, and the patch would probably have to be
re-written for each new release of DJGPP.
2. Write an interrupt-service routine that traps the calls to the video
BIOS and performs the mode switch. The problem with this, beyond the
general problems of writing interrupt-service routines, is that I
would have to deal with *every* BIOS call that came through.
3. Write bullet-proof code that never crashes. Alas, I'm a mere
mortal, and this seems a bit beyond my reach. Besides, the most
bullet-proof code can be made to bomb simply by hitting
<CNTL-BREAK>.
3. After allocating physical address space with
__dpmi_physical_address_mapping(__dpmi_meminfo *_info);
it would seem logical to free it before exiting the program, by calling
__dpmi_free_physical_address_mapping(__dpmi_meminfo *_info);
but I find this function listed only in the DPMI 1.0 spec, in spite of the
fact that the documentation in the DJGPP v2.00 file DPMI.H seems to
suggest it exists under DPMI 0.9. I am calling it anyway, and there seem
to be no ill effects, even in a DOS box under Windows, but I don't know if
I am doing the right thing.
Has anyone out there dealt successfully with these problems?
-Eric Rudd
- Raw text -