Mail Archives: djgpp/1996/12/24/19:03:26
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 -