Mail Archives: djgpp/1999/09/01/19:56:20
Eli Zaretskii wrote:
> On Tue, 31 Aug 1999, Eric Rudd wrote:
>
> > If one is using a linear frame buffer (usually located high in 32-bit memory
> > space), one other option is to write a modified __djgpp_nearptr_enable() that
> > opens the segment limit just wide enough to include the video card address.
I was a little careless in my wording; of course, the segment limit must include the
last byte in video memory.
> > This at least prevents a stray pointer from wrapping and accessing DOS memory.
> > Thus, a buggy program may crash, but at least it's unlikely to bring down DOS.
> > I have been using this technique for several years now (both under DOS and
> > under Win95), and have yet to have a problem with it.
>
> Care to post some minimal code that demonstrates this? It could be a
> valuable addition to the FAQ.
For comparison purposes, here is an excerpt from the file "nearptr.c" in the
official distribution:
int __djgpp_nearptr_enable(void)
{
if(!__dpmi_set_segment_limit(_my_ds(), 0xffffffffU)) {
if(__dpmi_get_segment_limit(_my_ds()) != 0xffffffffU)
return 0; /* We set it but DPMI ignored/truncated it */
__dpmi_set_segment_limit(__djgpp_ds_alias, 0xffffffffU);
__dpmi_set_segment_limit(_my_cs(), 0xffffffffU);
_crt0_startup_flags |= _CRT0_FLAG_NEARPTR;
return 1;
}
return 0;
}
...and here is my simple modification:
int var_nearptr_enable(unsigned long limit)
{
if(!__dpmi_set_segment_limit(_my_ds(), limit)) {
if(__dpmi_get_segment_limit(_my_ds()) != limit)
return 0; /* We set it but DPMI ignored/truncated it */
__dpmi_set_segment_limit(__djgpp_ds_alias, limit);
__dpmi_set_segment_limit(_my_cs(), limit);
_crt0_startup_flags |= _CRT0_FLAG_NEARPTR;
return 1;
}
return 0;
}
Here are some code fragments that illustrate how to use var_nearptr_enable() to set
the segment limit appropriately:
unsigned long LFBaddress; /* Physical address of linear frame buffer */
if (LFBaddress < __djgpp_base_address) {
/* LFB is located below __djgpp_base_address -- must allow wrap. */
var_nearptr_enable(0xFFFFFFFF);
} else {
/* LFB is located above __djgpp_base_address -- open up segment limit
just enough to include video memory, but still trap stray pointers
that try to access DOS memory. */
unsigned long curlim, reqlim;
curlim = __dpmi_get_segment_limit(_my_ds());
/* VideoMemorySize is the maximum size of the video memory space.
Either query the video card, or put in something big,
such as 16 MB. */
reqlim = LFBaddress - __djgpp_base_address + VideoMemorySize;
/* If current segment limit is big enough, leave it alone. */
if (reqlim > curlim) var_nearptr_enable(reqlim);
}
I have omitted the rest of the code, since it is based on Charles Sandmann's vbe.zip
code.
-Eric Rudd
- Raw text -