Will Perone

Most of you will probably think I'm crazy for including this one from way back when DOS and SVGA were popular. This code is something I wrote back in 1997 and includes how to set and work with 320x200x16 mode and how to trick the 16bit C compiler to do 32bit svga screen writes.

The true svga modes, 2 pages are needed in Real Mode because you can not allocate more than 64k at a time (per page).
unsigned long  *dbdw[2];      // this is our double buffer (our virtual screen)
unsigned short *db[2];        // a 16bit pointer to the same address 
unsigned short  Gmode= 0x10E; // graphics mode to set


// this is how to get into 320x200x16bpp in SVGA DOS
void initgfx()
{
	  if (_dos_allocmem(4096, &dbseg[0])) exit(1);  // *8 = 32768 bytes
	  db[0]= (unsigned far *)MK_FP(dbseg[0], 0);
	  dbdw[0]= (unsigned long far *)MK_FP(dbseg[0], 0);
	  if (_dos_allocmem(3950, &dbseg[1])) exit(1);  // the remaining memory (320x200x2 - 32768 bytes)
	  db[1]= (unsigned far *)MK_FP(dbseg[1], 0);
	  dbdw[1]= (unsigned long far *)MK_FP(dbseg[1], 0);
	  
	  
	  cprintf("Autodetecting 320x200x16bpp\r\n");

	  unsigned char *temp;
	  unsigned S;
	  unsigned *temp2, *temp3;
	  _dos_allocmem(64, &S);
	  temp= (unsigned char *)MK_FP(S, 0);

	  asm {
		 push es
		 mov ax, 0x4F00
		 mov bx, S //get vram seg
		 mov es, bx //point extra segment to vram
		 int 0x10
	  }
	  temp2= (unsigned *)MK_FP(_ES, _DI);
	  unsigned char *n= (unsigned char *)temp2;
	  asm pop es;

	  cprintf("    Signature: %c%c%c%c  ver %i.%i\r\n", n[0], n[1], n[2], n[3], n[5], n[4]);
	  n= (unsigned char *)MK_FP(temp2[4], temp2[3]);
	  cprintf("    manufacturer: %s \r\n", n);
	  cprintf("    testing supported modes...\r\n");
	  temp2= (unsigned *)MK_FP(temp2[8], temp2[7]);
	  for (int i= 0; i < 256 && temp2[i]!=0xFFFF; i++) {
			 unsigned int M= temp2[i];
			 asm {
				push es //save whatever is in ES
				mov ax, 0x4F01
				mov cx, M //mode
				mov bx, S //get vram seg
				mov es, bx //point extra segment to vram
				int 0x10
			 }
			 temp3= (unsigned int *)MK_FP(_ES, _DI);
			 asm pop es;
			 if (temp3[9]==320 && temp3[10]==200 &&
				  (temp3[12]>>8)==16 && temp3[8]==640) {
				  cprintf("    FOUND: mode 0x%X  %ix%ix%ibpp  %ibytes per scanline\r\n", temp2[i], temp3[9], temp3[10], (temp3[12]>;>8), temp3[8]);
				  Gmode= temp2[i];
			 }
	  }
	  _dos_freemem(S);
	  	  
	  // actually go into 320x200x16 mode!
	  asm {             
		  mov ax, 0x4F02  //32blue  64green 32red
		  mov bx, Gmode   //0x66 for vesa 1.xx, 0x10E for 2.xx+
	  	  int 0x10        // call interrupt 0x10 to do it
	  }
}


// this is how to copy our double buffer to screen
void vcopy()
{
	  asm {
		mov ax, 0x4F05;  //0x4F: call svga regs   function 5: set page
		mov bx, 0;       //subfunction 0: set write bank
		mov dx, 0;       //(subfunction 1 gets which bank you're currently in)
		int 0x10;
	  }
	  if (Vsync) {
		while (inp(0x3DA)&0x08);
		while (!inp(0x3DA)&0x08);
	  }
	  
	  unsigned long far *dbtemp= dbdw[0];
	  asm {
		push ds       //save regs
		push es
		push bx
		mov bx, 0xA000  //get vram seg
		mov es, bx      //point extra segment to vram
		lds si, dbtemp //get buffer location
		mov di, 0       //start at offset 0
		mov cx, 16384   //dwords to copy
		cld             //set dir to forward
	  }
	  __emit__(102,243, 165); //32bit movsd (trick compiler)

	  asm {
		pop bx
		pop es
		pop ds       //restore regs

		mov ax, 0x4F05  //0x4F: call svga regs   function 5: set page
		mov bx, 0  //subfunction 0: set write bank
		mov dx, 1;  //(subfunction 1 gets which bank you're currently in)
		int 0x10
	  }
	  if (Vsync) {
		while (inp(0x3DA)&0x08);
		while (!inp(0x3DA)&0x08);
	  }
	  dbtemp= dbdw[1];
	  asm {
		 push ds       //save regs
		 push es
		 push bx

		 mov bx, 0xA000  //get vram seg
		 mov es, bx      //point extra segment to vram
		 lds si, dbtemp //get buffer location
		 mov di, 0       //start at offset 0
		 mov cx, 15616   //dwords to copy
		 cld             //set dir to forward
	  }
	  __emit__(102,243, 165); //32bit movsd (trick compiler)
	  asm {
		pop bx
		pop es
		pop ds      //restore regs
	  }
//	  for (unsigned i= 0; i < 16384; i++) //copy to vram
//		   vb[i]= dbtemp[i];
}

// this is how to draw a pixel to the double buffer
void pxl(unsigned x, unsigned y, uchar r, uchar g, uchar b)
{
	  unsigned C= x+(y<<6)+(y<<8);     // x + y*320
	  db[C>>15][C]= (r<<11)+(g<<5)+b;  // 16bpp is a 5-6-5 mode
}
No Comments yet, be the first!
<- for private contact