/* *********************************************************************** * * * Video Graphics Array Driver * * * * By * * * * Larry Sharp * * * * And * * * * Christopher D. Watkins * * * * * * (c) 1991 Larry Sharp and Christopher D. Watkins * * * *********************************************************************** Plot - place pixel to screen Set_Palette - set palette register Init_Palette - 64 levels of grey, red, green and blue Init_Palette2 - 7 colors with 35 intensities each - use with Pixel Cycle_Palette - cycle through palette Circle - circle draw routine Draw - line draw routine Init_Graphics - initialize graphics Wait_For_Key - wait for key press Exit_Graphics - sound and wait for keypress before exiting graphics Title - set up text screen colors */ #include "stdio.h" #include "dos.h" #include "conio.h" #include "math.h" #include "malloc.h" #include "defs.h" #include "mathb.h" #include "graphb.h" union REGS reg; struct SREGS inreg; void Set_Mode(int Mode) { reg.h.ah=0; reg.h.al=Mode; int86(0x10,®,®); } Word X_Off, Y_Off; static Word far *Pre_Calc_Y1; static DWord far *Pre_Calc_Y2; static Byte Res; #define Low_Res 1 #define Medium_Res 2 #define High_Res 3 void Calc_Offsets() { Word tmp, tmp2; if(XRes>1; tmp2=XRes>>1; X_Off=tmp-tmp2; } else X_Off=0; if(YRes>1; tmp2=YRes>>1; Y_Off=tmp-tmp2; } else Y_Off=0; } void Pre_Calc() { Word j; for(j=0; j<=MaxYRes; j++) { if(Res==Medium_Res) Pre_Calc_Y2[j]=(DWord)MaxXRes*(DWord)j; else Pre_Calc_Y1[j]=MaxXRes*j; } } static Word Old_Page, Old_Page_2; void Plot(Word x, Word y, Byte color) { long L_Offset; Word Offset, Page; char far *address; if((x>6; if(Page!=Old_Page) { outpw(0x3CD, Page|64); Old_Page=Page; } address=(char far *)(0xA0000000L+Offset); *address=color; break; case Medium_Res : x+=X_Off; y+=Y_Off; L_Offset=Pre_Calc_Y2[y]+x; Page=(L_Offset>>16); Offset=L_Offset&65535; if(Page!=Old_Page) { outpw(0x3CD, Page|64); Old_Page=Page; } address=(char far *)(0xA0000000L+Offset); *address=color; break; case Low_Res : Offset=Pre_Calc_Y1[y+Y_Off]+x+X_Off; address=(char far *)(0xA0000000L+Offset); *address=color; break; } } } static Palette_Register Color; void Set_Palette(Palette_Register Hue) { reg.x.ax=0x1012; segread(&inreg); inreg.es=inreg.ds; reg.x.bx=0; reg.x.cx=256; reg.x.dx=(int)&Hue[0]; int86x(0x10,®,®,&inreg); } void Init_Palette(Palette_Register Color) { Word i; for(i=0; i<64; i++) { Color[i].Red=i; Color[i].Grn=i; Color[i].Blu=i; } for(i=64; i<128; i++) { Color[i].Red=i-64; Color[i].Grn=0; Color[i].Blu=0; } for(i=128; i<192; i++) { Color[i].Red=0; Color[i].Grn=i-128; Color[i].Blu=0; } for(i=192; i<=255; i++) { Color[i].Red=0; Color[i].Grn=0; Color[i].Blu=i-192; } } void Init_Palette_2(Palette_Register Color) { Word i; for(i=0; i<36; i++) { Color[i].Red=0; Color[i].Grn=0; Color[i].Blu=Round(1.8*i); } for(i=36; i<72; i++) { Color[i].Red=0; Color[i].Grn=Round(1.8*(i-36)); Color[i].Blu=0; } for(i=72; i<108; i++) { Color[i].Red=0; Color[i].Grn=Round(1.8*(i-72)); Color[i].Blu=Round(1.8*(i-72)); } for(i=108; i<144; i++) { Color[i].Red=Round(1.8*(i-108)); Color[i].Grn=0; Color[i].Blu=0; } for(i=144; i<180; i++) { Color[i].Red=Round(1.8*(i-144)); Color[i].Grn=0; Color[i].Blu=Round(1.8*(i-144)); } for(i=180; i<216; i++) { Color[i].Red=Round(1.8*(i-180)); Color[i].Grn=Round(1.8*(i-180)); Color[i].Blu=0; } for(i=216; i<252; i++) { Color[i].Red=Round(1.8*(i-216)); Color[i].Grn=Round(1.8*(i-216)); Color[i].Blu=Round(1.8*(i-216)); } } void Cycle_Palette(Palette_Register Hue) { Word i; RGB tmp; tmp=Hue[0]; memcpy(&Hue[0], &Hue[1], 765); Hue[255]=tmp; Set_Palette(Hue); } void Swap(int *first, int *second) { int temp; temp=*first; *first=*second; *second=temp; } void Circle(Word x, Word y, Word radius, Byte color) { int a, af, b, bf, target, r2, asp; if(Res==High_Res) asp=100; else asp=120; target=0; a=radius; b=0; r2=Sqr(radius); while(a>=b) { b=Round(sqrt(r2-Sqr(a))); Swap(&target,&b); while(b>1; while(xx1!=xx2) { Plot(xx1, yy1, color); Cycle+=ShDelta; if(Cycle>LgDelta) { Cycle-=LgDelta; yy1+=ShStep; } xx1+=LgStep; } Plot(xx1, yy1, color); } else { Cycle=ShDelta >> 1; Swap(&LgDelta, &ShDelta); Swap(&LgStep, &ShStep); while(yy1 != yy2) { Plot(xx1, yy1, color); Cycle+=ShDelta; if(Cycle>LgDelta) { Cycle-=LgDelta; xx1+=ShStep; } yy1+=LgStep; } Plot(xx1, yy1, color); } } int CentreX, CentreY; void Init_Graphics(Byte Mode) { switch(Mode) { case 19 : Res=Low_Res; MaxXRes=320; MaxYRes=200; break; case 45 : Res=Medium_Res; MaxXRes=640; MaxYRes=350; break; case 120 : Res=Medium_Res; MaxXRes=640; MaxYRes=400; break; case 46 : Res=Medium_Res; MaxXRes=640; MaxYRes=480; break; case 48 : Res=Medium_Res; MaxXRes=800; MaxYRes=600; break; case 56 : Res=High_Res; MaxXRes=1024; MaxYRes=768; break; default : printf("Mode %d is not a valid graphics mode\n\n",Mode); puts("Hit any key to exit"); getch(); exit(1); break; } MaxX=MaxXRes-1; MaxY=MaxYRes-1; if(XRes==0) XRes=MaxXRes; if(YRes==0) YRes=MaxYRes; Calc_Offsets(); if(Res==Medium_Res) Pre_Calc_Y2=farcalloc(768, sizeof(DWord)); else Pre_Calc_Y1=farcalloc(768, sizeof(Word)); CentreX=XRes/2; CentreY=YRes/2; Asp=(1024.0/768.0)*((float)YRes/(float)XRes); Pre_Calc(); Set_Mode(Mode); Init_Palette_2(Color); Set_Palette(Color); } void Set_Graphics_Mode(Word xRes, Word yRes) { XRes=xRes; YRes=yRes; if((XRes<321) && (YRes<201)) Init_Graphics(19); else if((XRes<641) && (YRes<351)) Init_Graphics(45); else if((XRes<641) && (YRes<401)) Init_Graphics(120); else if((XRes<641) && (YRes<481)) Init_Graphics(46); else if((XRes<801) && (YRes<601)) Init_Graphics(48); else Init_Graphics(56); } void Wait_For_Key() { char k; while(!(k=getch())); } void Exit_Graphics() { sound(1000); delay(500); nosound(); if(Pre_Calc_Y1>0) farfree(Pre_Calc_Y1); if(Pre_Calc_Y2>0) farfree(Pre_Calc_Y2); Wait_For_Key(); Set_Mode(3); } void Title() { textcolor(YELLOW); textbackground(BLUE); clrscr(); } /* ********************************************************************** * * * Three Dimensional Plotting Routines * * * ********************************************************************** InitPlotting - rotation and tilt angles InitPerspective - observer location and distances MapCoordinates - maps 3D space onto the 2D screen CartesianPlot - plot a cartesian system point CylindricalPlot3D - plot a cylindrical system point SphericalPlot3D - plot a spherical system point DrawLine3D - plots a line from 3D coordinates */ float CosA, SinA; float CosB, SinB; float CosACosB, SinASinB; float CosASinB, SinACosB; void Init_Plotting(int Ang, int Tlt) { CentreX=XRes/2; CentreY=YRes/2; Angl=Ang; Tilt=Tlt; CosA=CosD(Angl); SinA=SinD(Angl); CosB=CosD(Tilt); SinB=SinD(Tilt); CosACosB=CosA*CosB; SinASinB=SinA*SinB; CosASinB=CosA*SinB; SinACosB=SinA*CosB; } void Init_Perspective(Boolean Perspective, float x, float y, float z, float m) { PerspectivePlot=Perspective; Mx=x; My=y; Mz=z; ds=m; } void Map_Coordinates(float X, float Y, float Z, int *Xp, int *Yp) { float Xt, Yt, Zt; float OneOverZt; Xt=(Mx+X*CosA-Y*SinA); Yt=(My+X*SinASinB+Y*CosASinB+Z*CosB); if(PerspectivePlot) { Zt=Mz+X*SinACosB+Y*CosACosB-Z*SinB; OneOverZt=1.0/Zt; *Xp=CentreX+Round(ds*Xt*OneOverZt); if(Res!=Low_Res) *Yp=CentreY-Round(ds*Yt*OneOverZt); else *Yp=CentreY-Round(ds*Yt*OneOverZt*Asp); } else { *Xp=CentreX+Round(Xt); if(Res!=Low_Res) *Yp=CentreY-Round(Yt); else *Yp=CentreY-Round(Yt*Asp); } } void Cartesian_Plot_3D(float X, float Y, float Z, Byte Color) { int Xp, Yp; Map_Coordinates(X, Y, Z, &Xp, &Yp); Plot(Xp, Yp, Color); } void Cylindrical_Plot_3D(float Rho, float Theta, float Z, Byte Color) { float X, Y; Theta=Radians(Theta); X=Rho*cos(Theta); Y=Rho*sin(Theta); Cartesian_Plot_3D(X, Y, Z, Color); } void Spherical_Plot_3D(float R, float Theta, float Phi, Byte Color) { float X, Y, Z; Theta=Radians(Theta); Phi=Radians(Phi); X=R*sin(Theta)*cos(Phi); Y=R*sin(Theta)*sin(Phi); Z=R*cos(Theta); Cartesian_Plot_3D(X, Y, Z, Color); } void Draw_Line_3D(TDA Pnt1, TDA Pnt2, Byte Color) { int Xp1, Yp1; int Xp2, Yp2; float x1, y1, z1; float x2, y2, z2; UnVec(Pnt1, &x1, &y1, &z1); UnVec(Pnt2, &x2, &y2, &z2); Map_Coordinates(x1, y1, z1, &Xp1, &Yp1); Map_Coordinates(x2, y2, z2, &Xp2, &Yp2); Draw(Xp1, Yp1, Xp2, Yp2, Color); } /* *********************************************************************** * * * Pixel * * * *********************************************************************** PutPixel - plots pixel GetPixel - gets pixel Color 1 - Blue 2 - Green 3 - Cyan 4 - Red 5 - Magenta 6 - Brown/Yellow 7 - Gray Scale Intensity levels (0..35) for each color */ void Put_Pixel(int x, int y, Byte Color, Byte Intensity) { Byte Col; if(Intensity>MaxInten) exit(1); Col=((MaxInten+1)*(Color-1)+Intensity) & 255; Plot(x, y, Col); } Byte Get_Pixel(Word x, Word y) { long L_Offset; Word Offset, Page; char far *address; Byte color; if((x>6)&15; if(Page!=Old_Page_2) { outpw(0x3CD, (Page<<4)|Old_Page); Old_Page_2=Page; } address=(char far *)(0xA0000000L+Offset); color=*address; break; case Medium_Res : x+=X_Off; y+=Y_Off; L_Offset=Pre_Calc_Y2[y]+x; Page=(L_Offset>>16); Offset=L_Offset&65535; if(Page!=Old_Page_2) { outpw(0x3CD, (Page<<4)|Old_Page); Old_Page_2=Page; } address=(char far *)(0xA0000000L+Offset); color=*address; break; case Low_Res : Offset=Pre_Calc_Y1[y+Y_Off]+x+X_Off; address=(char far *)(0xA0000000L+Offset); color=*address; break; } } return(color); } Byte Get_Pixel_2(Word x, Word y) { x+=X_Off; y+=Y_Off; reg.x.ax=3328; reg.x.dx=y; reg.x.cx=x; int86(0x10,®,®); outpw(0x3CD, Old_Page|64); return(reg.x.ax&255); } /* *********************************************************************** * * * Setup of Coordinate Axes and Color Palette * * * *********************************************************************** PutAxisAndPalette - toggle for Axis and Palette AxisAndPalette - places Axis and Color Palette on screen */ void Put_Axis_And_Palette(Boolean PlaceOnScreen) { if(PlaceOnScreen) Draw_Axis_And_Palette=true; else Draw_Axis_And_Palette=false; } void Display_Axis() { int x, y, z, sx, sy; sx=XRes/320; sy=YRes/200; for(x=-100*sx; x<101*sx; x++) { Cartesian_Plot_3D(x, 0, 0, 35); Cartesian_Plot_3D(100*sx, 0, 0, 251); } for(y=-100*sy; y<101*sy; y++) { Cartesian_Plot_3D(0, y, 0, 71); Cartesian_Plot_3D(0, 100*sy, 0,251); } for(z=-100*sx; z<101*sx; z++) { Cartesian_Plot_3D(0, 0, z, 107); Cartesian_Plot_3D(0, 0, 100*sx, 251); } } void Display_Palette() { int X, Y, sx, sy; Byte Color; Byte Intensity; sx=XRes/320; sy=YRes/200; for(Color=1; Color<=MaxCol; Color++) { for(Intensity=0; Intensity<=MaxInten; Intensity++) { for(X=0; X<4*sx; X++) { for(Y=0; Y<4*sy; Y++) Put_Pixel(X+(5*sx)*Color, (190*sy)-Y-(5*sy)*Intensity, Color, Intensity); } } } } void Axis_And_Palette() { if(Draw_Axis_And_Palette) { Display_Axis(); Display_Palette(); } }