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