Mail Archives: djgpp/1997/05/30/22:51:09
From: | Henrik Baarnhielm <Henrik DOT Baarnhielm AT abc DOT se>
|
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
|
To: | djgpp AT delorie DOT com
|
DJ-Gateway: | from newsgroup comp.os.msdos.djgpp
|
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 <iostream.h>
#include <conio.h>
#if !defined(__DPMI_H)
#include <dpmi.h>
#endif
#if !defined(__STRING_H)
#include <string.h>
#endif
#if !defined(__GO32_H)
#include <go32.h>
#endif
#if !defined(__FARPTR_H)
#include <sys\farptr.h>
#endif
#if !defined(__NEARPTR_H)
#include <sys\nearptr.h>
#endif
#if !defined(__MATH_H)
#include <math.h>
#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
***************************************
- Raw text -