From: Henrik Baarnhielm Newsgroups: comp.os.msdos.programmer,alt.msdos.programmer,rec.games.programmer,comp.os.msdos.djgpp Subject: VBE Bankswitch in Pmode Date: Fri, 30 May 1997 20:50:27 +0200 Organization: ABC-Klubben Lines: 249 Message-ID: <338F2173.15CA7275@abc.se> NNTP-Posting-Host: pm2-03.abc.se Mime-Version: 1.0 Content-Type: text/plain; charset=us-ascii Content-Transfer-Encoding: 7bit To: djgpp AT delorie DOT com DJ-Gateway: from newsgroup comp.os.msdos.djgpp Precedence: bulk I am trying to make a VBE C++-class in DJGPP. It shall support both bankswitch and linear buffers and I have trouble calling the bankswitch. If I use the interrupt it works but it is too slow. I have got the code to the Pmode bankswitch using VBE function 0ah but when I call it I get a Segment Violation. I have tried to map memory locations, got with the same function, to the programs address-space but it doesn't seem to work. I would be very grateful if someone could help me because I am really stuck and it's not fun. Thank you My code... #include #include #if !defined(__DPMI_H) #include #endif #if !defined(__STRING_H) #include #endif #if !defined(__GO32_H) #include #endif #if !defined(__FARPTR_H) #include #endif #if !defined(__NEARPTR_H) #include #endif #if !defined(__MATH_H) #include #endif #include "vesa.h" vesascreen::vesascreen() { union __dpmi_regs regs; regs.x.ax=0x4f00; regs.x.es=__tb >> 4; regs.x.di=0; strcpy(vesainfo.signatur,"VBE2"); dosmemput(&vesainfo,sizeof(vesainfo),__tb); __dpmi_int(0x10, ®s); dosmemget(__tb, sizeof(vesainfo),&vesainfo); if(regs.h.al==0x4f) { vesadetected=1; } else vesadetected=0; invesamode=0; } inline int vesascreen::isvesadetected() { return vesadetected; } int vesascreen::ismodesupported(unsigned int x,unsigned int y,unsigned long ncolors) { unsigned long colors; unsigned short modenum; unsigned long modepointer; if(!isvesadetected()) return 0; modepointer=(unsigned long)vesainfo.videomodes; _farsetsel(_dos_ds); while((modenum=_farnspeekw(modepointer))!=(unsigned)-1) { getvesamodeinfo(modenum,width,height,colors); if(width==x && height==y && colors==ncolors) break; modepointer++; } if(modenum==(unsigned)-1) return 0; return modenum; } void vesascreen::getmodeinfo(int mode,modeinfotyp *info) { union __dpmi_regs regs; regs.x.ax=0x4f01; regs.x.cx=mode; regs.x.di=0; regs.x.es=__tb >> 4; __dpmi_int(0x10, ®s); dosmemget(__tb, sizeof(modeinfo),&modeinfo); } int vesascreen::setmode(unsigned int x, unsigned int y, unsigned long ncolors) { int shift=0; unsigned long colors,modepointer; union __dpmi_regs regs; __dpmi_meminfo memory; pminfo *buffer; unsigned short *mem; void *memorylocs; unsigned int modenum; if(!isvesadetected()) return 0; if(!(modenum=ismodesupported(x,y,ncolors))) return 0; regs.x.ax=0x4f0a; regs.h.bl=0; __dpmi_int(0x10,®s); if(regs.h.al !=0x4f && regs.h.ah != 0) return 0; buffer=(pmfunc *)new unsigned char[regs.x.cx]; dosmemget(regs.x.es << 4 + regs.x.di,regs.x.cx,buffer); mem=(unsigned short *)(buffer+buffer->table); while(*mem != 0xffff) mem++; mem++; __djgpp_map_physical_memory(memorylocs,*(unsigned long *)mem,(unsigned long)(mem[2])); getmodeinfo(modenum,&modeinfo); if(!(modeinfo.modeattr & 0x80)) { bankshift=0; while((unsigned)(64 >> bankshift) != modeinfo.granularity) bankshift++; screenptr=(char*)((((unsigned long)modeinfo.winasegment) << 4)+__djgpp_conventional_base); currentbank=-1; banking=1; } else { memory.size=modeinfo.width*modeinfo.height*modeinfo.bitsperpixel/8; memory.address=modeinfo.physicaladdress; if(__dpmi_physical_address_mapping(&memory)) return 0; lineaddress=(char*)(memory.address-__djgpp_base_address); shift=0x4000; banking=0; } regs.x.ax=0x4f02; regs.x.bx=(modenum | shift); __dpmi_int(0x10,®s); if (regs.h.al != 0x4f && regs.h.ah != 0) return 0; regs.x.ax=0x4f06; regs.h.bl=0; regs.x.cx=modeinfo.width; __dpmi_int(0x10,®s); if (regs.h.al == 0x4f && regs.h.ah==0) { width=modeinfo.width; height=modeinfo.height; bytesperline=modeinfo.bytesperline; invesamode=1; currentmode=modenum; return 1; } else return 0; } void vesascreen::setbank(unsigned int bank) { __dpmi_regs regs; if(currentbank!=bank) { currentbank=bank; bank <<=bankshift; for(int temp=0;temp<2;temp++) { asm volatile ("movw %%bx,%0 movw %%dx,%1 call %2" : : "g" (temp),"g" (bank),"g" (switchbank) : "%bx","%dx"); } } } int vesascreen::putpixel(unsigned int x,unsigned int y,unsigned char color) { if(!invesamode) return 0; unsigned long offset; offset=(long)y*bytesperline+x; if(banking) { setbank((int)(offset >> 16)); if(__djgpp_nearptr_enable()) { screenptr[offset & 0xffff]=color; __djgpp_nearptr_disable(); } return 1; } if(__djgpp_nearptr_enable()) { lineaddress[offset]=color; __djgpp_nearptr_disable(); } return 1; } int vesascreen::getvesamodeinfo(unsigned int mode,unsigned int &screenwidth,unsigned int &screenheight,unsigned long &ncolors) { getmodeinfo(mode,&modeinfo); screenwidth=modeinfo.width; screenheight=modeinfo.height; ncolors=(unsigned long)pow2(modeinfo.bitsperpixel); return 1; } int main() { vesascreen scr; int x=0,y=0; int temp; if (!scr.isvesadetected()) { cout << "VESA isn't there.\n"; return 0; } if(!scr.setmode(800,600,256)) { cout << "Couldn't change mode.\n"; return 0; } for(x=0;x<799;x++) { for(y=0;y<599;y++) scr.putpixel(x,y,y); } getch(); textmode(C80); } -- *************************************** Internet : Henrik DOT Baarnhielm AT abc DOT se Fidonet : Henrik Baarnhielm, 2:201/235 ***************************************