delorie.com/archives/browse.cgi   search  
Mail Archives: djgpp/1999/09/01/19:56:20

Date: Wed, 01 Sep 1999 09:11:29 -0500
From: Eric Rudd <rudd AT cyberoptics DOT com>
Subject: Re: Nearptr putpixel method?
To: Eli Zaretskii <eliz AT is DOT elta DOT co DOT il>
Cc: djgpp AT delorie DOT com
Message-id: <37CD3410.A9D2C9B7@cyberoptics.com>
Organization: CyberOptics
MIME-version: 1.0
X-Mailer: Mozilla 4.08 [en] (Win95; U)
References: <Pine DOT SUN DOT 3 DOT 91 DOT 990901131648 DOT 3663F-100000 AT is>
Reply-To: djgpp AT delorie DOT com

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 -


  webmaster     delorie software   privacy  
  Copyright 2019   by DJ Delorie     Updated Jul 2019