/* Copyright 1990 by Gary R. Olhoeft
* This code may be freely copied for personal,
* non-commercial use. compile using MicroWay's
* NDP C-386 compiler:
* cc graphics.c -w -v -rt2 -n2 -n3 -lGREX.LIB
*/
#include <stdio.h>
#include <dos.h>
#include <grex.h>
void plot_pixel();
void graphics();
void spectrum();
void ext_palette();
union REGS reg; /* required by inline assembly */
int v_mode, v_color, v_rowy, v_colx, page;
unsigned short ati_extreg;
char ega_palette[17] = (0,1,9,11,3,19,2,18,6,54,38,
52,4,36,41,13,0};
int modes[] = {0x0d,0x0e,0x10,0x12,0x13,0x54,
0x62,0x63,0x65};
void main()
{
int i,x,y,key;
unsigned char color;
for (i=0; i<9; i++)
{
graphics(modes[i]); /* cycle through ATI VGA
Wonder graphics modes */
printf("Mode %d %dx%dx%d\n",v_mode,v_colx+1,
v_rowy+1,v_color+1);
/* printing shrinks as pixel count increases */
spectrum();
/* draw banded color lines on screen */
for (x = 0; x<=v_colx>>2; x++)
{
for (y = 0; y<=v_rowy; y++)
{
color = y % v_color;
plot_pixel(x+y,y,color);
}
}
/* pause loop until keypress;
exit with ^C or Esc */
if ((key=pauseb())==27) {
set_video_mode(0x02); exit();
}
}
set_video_mode(0x02); /* restore text mode */
exit();
}
void graphics(mode)
unsigned char mode;
{
unsigned char buffer[2];
switch (mode) /* note: not all possible modes shown */
{
case 0x0d: /* EGA */
v_colx = 320;
v_rowy = 200;
v_color = 16;
break;
case 0x0e: /* EGA */
v_colx = 640;
v_rowy = 200;
v_color= 16;
break;
case 0x10: /* EGA high resolution */
v_colx = 640;
v_rowy = 350;
v_color = 16;
break;
case 0x12: /* VGA */
v_colx = 640;
v_rowy = 480;
v_color = 16;
break;
case 0x13: /* MCGA */
v_colx = 320;
v_rowy = 200;
v_color = 256;
break;
case 0x54: /* ATI SVGA */
v_colx = 800;
v_rowy = 600;
v_color = 16;
break;
case 0x62: /* ATI SVGA */
v_colx = 640;
v_rowy = 480;
v_color = 256;
break;
case 0x63: /* ATI SVGA */
v_colx = 800;
v_rowy = 600;
v_color = 256;
break;
case 0x65: /* ATI SVGA */
v_colx = 1024;
v_rowy = 768;
v_color = 16;
break;
default:
mode = 0x02; /* text mode */
v_colx = 80;
v_rowy = 25;
v_color = 1;
break;
}
v_mode = mode;
v_colx--; /* set ranges 0 to pixels-1 */
v_rowy--;
v_color--;
reg.b.ah = 0;
reg.b.al = mode;
int386(0x10,®,®); /* call BIOS video
interrupt to set mode */
blk_mb(buffer, 0x34, 786448, 2);
ati_extreg = buffer[0]+256*buffer[1];
/* find ATI extended_reg address
(could use peek() instead)*/
page = 99; /* force paging first plot cycle */
}
/* plot pixel of color at (x,y) display units */
void plot_pixel(x,y, color)
int x,y;
unsigned char color;
{
#define peek(addr, val) asm(" push es"); \
asm(" mov ax, 034h"); asm(" mov \
es, ax"); ebx = addr; asm(ebx, " mov \
cl, byte ptr es:[ebx]", cl); val = cl; asm\
(" pop es")
#define poke(addr, val) asm(" push es"); \
cl = val; asm(" mov ax, 034h"); \
asm(" mov es, ax"); ebx = addr; \
asm(ebx, cl, " mov byte ptr es:[ebx], \
cl"); asm(" pop es")
/* required by inline assembly */
reg$eax unsigned short ax;
reg$eax unsigned char al;
reg$ah unsigned char ah;
reg$ecx unsigned short cx;
reg$ch unsigned char ch;
reg$ecx unsigned char cl;
reg$edx unsigned short dx;
reg$edx unsigned char dl, val;
reg$ebx unsigned ebx, addr;
int i,vcol,yvx;
if ((y < 0) || (y > v_rowy) || (x < 0) ||
(x > v_colx)) return;
/* clip physical display boundaries */
y = v_rowy-y; /* put (0,0) at lower left corner of plotter */
vcol = v_colx+1;
yvx = y*vcol + x;
switch (v_mode)
{
case 0x65: /* ATI 1024x768x16 */
ch = (char)(y >> 6);
if (ch!=page) /* only change page if different */
{
dx = ati_extreg; /* location of ATI card external register */
asm(" cli "); /* disable interrupts */
asm(" mov al,0b2h"); /* page select */
asm(dx," out dx,al"); /* ATI extended register */
asm(" inc dl");
asm(" in al,dx");
asm(" mov ah,al");
asm(" and ah,0e1h"); /* page mask */
asm(ch," or ah, ch"); /* ch = memory page desired */
asm(" mov al,0b2h"); /* page select */
asm(" dec dl");
asm(" out dx,ax");
asm(" sti "); /* enable interrupts */
page = ch;
}
addr = 655360 + ((y << 9) % 65536) + (x >> 1);
peek(addr, val); /* read existing color of pixel pair */
if (x % 2) val = color | (val & 0xF0); /* change addressed pixel */
else val = (color << 4) | (val & 0x0F);
poke(addr, val); /* write pixel pair */
break;
case 0x13: /* MCGA 320x200x256 */
addr = 655360 + yvx;
poke(addr, color); /* write direct to real video memory */
break;
case 0x62: /* ATI 640x480x256 */
case 0x63: /* ATI 800x600x256 */
ch = (unsigned char)(yvx >> 15);
if (ch!=page)
{
dx = ati_extreg; /* location of ATI card external register */
asm(" cli "); /* disable interrupts */
asm(" mov al,0b2h"); /* page select */
asm(dx," out dx,al"); /* ATI extended register */
asm(" inc dl");
asm(" in al,dx");
asm(" mov ah,al");
asm(" and ah,0e1h"); /* page mask */
asm(ch," or ah,ch"); /* ch = memory page desired */
asm(" mov al,0b2h"); /* page select */
asm(" dec dl");
asm(" out dx,ax");
asm(" sti "); /* enable interrupts */
page = ch;
}
addr = 655360 + (yvx % 65536);
poke(addr, color); /* write direct to real video memory */
break;
default:
/ * 0x10 EGA 640x350x16, 0x12 VGA 640x480x16, 0x54 ATI 800x600x16 */
asm(" push es"); /* save segment register */
asm(" mov ax, 034h"); /* use Phar Lap LDT to */
asm(" mov es, ax"); /* access real memory */
dx = 0x3ce; /* EGA graphics register */
ebx= 655360 + (yvx >> 3); /* memory position of pixel */
asm(ebx," mov cl, byte ptr es:[ebx]"); */ load EGA registers */
ax = color << 8;
asm(dx, ax, " out dx, ax"); /* set color */
ax = 0x0F01;
asm(dx, ax," out dx, ax"); /* enable */
ax = 0x0003; /* 0x00 = replace, 0x10 OR, 0x18 XOR, 0x08 AND */
asm(dx, ax," out dx, ax"); /* pixel write mode */
ax = ((0x80 >> (x%8)) << 8 ) + 8;
asm(dx, ax," out dx, ax"); /* bit mask (8 pixels/byte) */
asm(ebx," mov byte ptr es:[ebx], 255"); /* write EGA regs */
asm(" pop es"); /* restore segment register */
}
}
void spectrum() /* create color spectrum palette */
{
int i;
if (v_mode == 0x65) /* 1024x768x16 mode only */
{
ext_palette( 0, 0, 0, 0); /* black */
ext_palette( 1, 63, 0, 0); /* red */
ext_palette( 2, 63, 21, 0);
ext_palette( 3, 63, 42, 0);
ext_palette( 4, 63, 63, 0); /* yellow */
ext_palette( 5, 42, 63, 0);
ext_palette( 6, 21, 63, 0);
ext_palette( 7, 0, 63, 0); /* green */
ext_palette( 8, 0, 63, 21);
ext_palette( 9, 0, 63, 42);
ext_palette(10, 0, 63, 63); /* cyan */
ext_palette(11, 0, 42, 63);
ext_palette(12, 0, 21, 63);
ext_palette(13, 0, 0, 63); /* blue */
ext_palette(14, 21, 0, 63);
ext_palette(15, 42, 0, 63); /* magenta */
}
else
{
if (v_color == 255) /* all 256 color modes */
{
vga_palette(0,0,0,0);
for (i=1; i<=64; i++) { vga_palette(i,63,i-1,0); }
for (i=65; i<=128; i++) { vga_palette(i,128-i,63,0); }
for (i=129; i<=192; i++) { vga_palette(i,0,63,i-129); }
for (i=193; i<=255; i++) { vga_palette(i,0,255-i,63); }
}
else
{ /* 16 color EGA modes except 1024x768 */
set_palette(ega_palette);
}
}
}
void ext_palette(i,r,g,b) /* write to external palette registers */
unsigned char i,r,g,b;
{
#define outp(p,v) dx = p; al = v; asm(dx,al," out dx,al")
reg$eax unsigned char al,v;
reg$edx unsigned short dx,p;
outp(0x3C8, i);
outp(0x3C9, r);
outp(0x3C9, g);
outp(0x3C9, b);
outp(0x3C8, i<<4);
outp(0x3C9, r);
outp(0x3C9, g);
outp(0x3C9, b);
}