delorie.com/archives/browse.cgi   search  
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, &regs);
	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, &regs);
	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,&regs);
	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,&regs);
	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,&regs);
	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 -


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