delorie.com/archives/browse.cgi   search  
Mail Archives: djgpp/1996/12/24/19:03:26

To: djgpp AT delorie DOT com
Date: Tue, 24 Dec 1996 07:36:51 c:\
Subject: Allocating and using memory with the dpmi functions
Message-ID: <19961224.063720.8439.1.aclemmer@juno.com>
From: aclemmer AT juno DOT com (Aaron m Clemmer)

	I'm trying to use virtual screens in my graphics lib.  As they
vary in size from 64k to several megabytes, I decided that using the dpmi
functions was the best way to go.  Anyways, the buffer appears to
allocate properly, but when I try to write to it, I get a GPF.  And if I
skip the writes and just free the buffer after allocating, I freeze the
computer.  If anyone can explain what is wrong with how I'm doing this,
I'd appreciate it.

// this function allocates a buffer to a size calculated from 'info', a
struct.
// in the class 'videoCard', both 'bufexists' and 'buffer' (which is
__dpmi_meminfo) are // members.
unsigned long videoCard::makeBuffer(_modeInfo *info)
{
if(bufexists==TRUE) // don't allocate the buffer twice...
 return 0;

// dividing the number of bits-per-pixel by 8 gives you bytes per
pixel... so I allocate
//enough mem for 24bit modes...
// I'm filling in the number of bytes I want here, as it says in the
docs...
buffer.size = info->xRes * info->yRes * (info->bitsPerPixel/8);

// 'buffer' isn't a pointer... It is declared as '__dpmi_meminfo buffer;'
if(__dpmi_allocate_memory(&buffer) == -1) { // allocate the buffer
 error = NOMEM; return 0; }

__dpmi_lock_linear_region(&buffer); // lock it, so it won't get paged to
disk  =)
bufexists = TRUE; // mark it as existing

// return it's address.  Ok, is 'buffer.address' really what I want to be
returning to a
// pointer (unsigned char *p), or should I be converting this address in
some way
// first?
return buffer.address;
}

// this is called to free the buffer after we're done using it, it
freezes up the computer
bool videoCard::killBuffer()
{
if(bufexists==TRUE) { // if we've actually allocated it...
  __dpmi_unlock_linear_region(&buffer);	// unlock it. (do I need
to?)
 if(__dpmi_free_memory(buffer.handle) == -1) // free it
  return 0;
}
  return 1;
}

void putPixel(short x, short y, _color color, unsigned char *bufptr)
{
  if(x > 0 && x < 320 && y > 0 && y < 200) { // clipping

// if it is in convention mem, we use _dos_ds as the selector.
   if(bufptr == 0xA0000) {
     unsigned long offset = (x + ((y<<6) + (y<<8)));
      _farpokeb(_dos_ds, 0xA0000+offset, color.red);
  }
 else {
    unsigned long offset = (((int)bufptr) & 0xFFFFF) + (x + ((y<<6) +
(y<<8)));

// ok, I assume buffer::handle is a selector... is it?  I tried looking
through the info files
// and the faq, but there wasn't any explanation.  And if it isn't the
selector, how would
// I make one for my buffer?
     _farpokeb(buffer.handle, offset, color.red); 
  }
}
}

// this flips the buffer to vga mem...
void flipToScreen(_modeInfo *info, unsigned char *bufptr)
{
  unsigned long size = (unsigned long)info->xRes * (unsigned
long)info->yRes *
                                         (unsigned
long)(info->bitsPerPixel/8);

  // same thing here, am I using buffer::handle correctly?
   movedata(buffer.handle, ((int)bufptr)&0xFFFFF, _dos_ds, 0xA0000,
size);
}

Ok, and here is how I'm calling these functions...

void whatever()
{
  unsigned char *bufptr=0; // this will point to the address returned by
'makeBuffer'
  _vidInfo vInfo;   // just some info about the video card
 _modeInfo mInfo;  // and info about a video mode, filling in has been
omitted
...
  videoCard video(&vInfo);     // initialize video
  if(!(bufptr = video.makeBuffer(&mInfo))) { // make a offscreen buffer,
telling it
    printf("no mem"); return; } // about the video mode we are in

   putPixel(1,1, (_color){15,0,0}, bufptr); // pass the address that
'bufptr' points to...
   flipToScreen(&mInfo, bufptr); // flip it to the vga....
   video.killBuffer(); // free the buffer
}

aaron

- Raw text -


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