Pascal Xlib
Pascal
Download (.zip)
unit Xlib; interface type ColorType = record Red,Green,Blue:byte; end; {record}
TableType = array[0..45,0..300] of integer;
SpeedRangeType = 0..10;
SizeSubRange = 1..10;
ImageType = record deltaX,deltaY:longint; vSegment,vOffset:word; Image:pointer; end; {record}
FontEnumeratedType = (Regular);
FontType = record Size:SizeSubRange; end; {record}
SomePaletteType = array[0..255] of ColorType;
PictureType = record picture:ImageType; Palette:^SomePaletteType; end; {record}
ColorRecordType = record Color:ColorType; IsAPoint:Boolean; Location:byte; end; {record}
GradatedPalType = array[0..255] of ColorRecordType;
GradatedPaletteType = ^GradatedPalType;
procedure InitGraph; procedure CloseGraph;
procedure SetColor(AColor:byte); function GetColor:byte;
procedure PutPixel(x,y:word); function GetPixel(x,y:word):byte;
procedure SetPalette(ColorNumber:byte;AColor:ColorType); procedure GetPalette(ColorNumber:byte;var TheColor:ColorType); procedure FadeScreen(Speed:SpeedRangeType);
procedure ClearScreen; procedure Circle(x,y,Radius:word); procedure Line(x1,y1,x2,y2:word); procedure Bar(BeginX,BeginY,EndX,EndY:word); procedure Rectangle(BeginX,BeginY,EndX,EndY:word); procedure Fill(x,y:word;FillColor,Border:byte);
procedure GetImage(var Image:ImageType;x1,y1,x2,y2:word); procedure PutImage(Image:ImageType;x1,y1:word); procedure KillImage(var Image:ImageType);
procedure PutChar(Font:FontEnumeratedType;xc,yc:word;AChar:char); procedure WriteStringXY(Font:FontEnumeratedType;xc,yc:word;Thing:string); procedure WriteString(Font:FontEnumeratedType;Thing:string);
procedure LoadTGA(var Image:PictureType;FileName:string); procedure DrawPicture(x1,y1:word;Image:PictureType;BeginPart,EndPart:byte); procedure KillPicture(var Image:PictureType);
procedure InitGradatedPalette(var SomePalette:GradatedPaletteType); procedure AddKeyPoint(var SomePalette:GradatedPaletteType;Location:byte;Color:ColorType); procedure GeneratePalette(SomePalette:GradatedPaletteType); procedure KillGradatedPalette(var SomePalette:GradatedPaletteType);
implementation uses CRT;
const PI = 3.1415926; VGA:Word = $a000; IOOk=0; Video=$10; Crtc_addr=$3d4; Sequ_addr=$3c4; TGASize:longint = 64000;
type ByteBitType = array[1..8] of boolean;
PCXFileType = file of char;
EGAPalType = array[0..47] of byte;
JunkType = array[0..57] of byte;
PCXHeaderType = record Manufacturer:char; {for some reason, always 10} Version:char; {who cares} Encoding:char; {always 1 for RLE} BitDepth:char; {should be eight - wierd things if not} x,y:word; {upper left corner of the image} width,height:word; {Duh} HRes,VRes:word; {Number of pixels in x & y direction} EGAPalette:EGAPalType; {who cares, we use MCGA+} Reserved:char; {Nothing} ColorPlanes:char; {Number of color planes in the image} BytesPerLine:word; {Number of bytes per line} PaletteType:word; {Unimportant} Padding:JunkType; {Fat at the end of the file} end; {PCXHeaderType}
PaletteFileType = file of ColorType;
PortLookUpType = array[0..640] of word; yLookUpType = array[0..400] of word;
var SinRadiusTable,CosRadiusTable:TableType; CurrentDrawingColor:byte; HasBeenInitialized:boolean; CurrentTextX,CurrentTextY:word; PortLookUp:PortLookUpType; yLookUp:yLookUpType; CurrentPort:word;
function Abs(x:integer):word; begin if x<0 then Abs:=-x else Abs:=x; end; {Abs}
procedure AnnoyingErrorMessage; begin if not HasBeenInitialized then begin writeln('Error #666: The screen has not be initialized. Please call InitGraph;'); halt; end; {if} end; {AnnoyingErrorMessage}
procedure SetXtended; begin asm mov ax, $4F02 mov bx, $100 int VIDEO end;
{ Turn the VGA screen off } Port[SEQU_ADDR] := 1; Port[SEQU_ADDR + 1] := Port[SEQU_ADDR + 1] or $20;
{ Turn off the Chain-4 bit (bit 3 at index 4, port 0x3c4) } PortW[SEQU_ADDR] := $0604;
{ Turn off word mode, by setting the Mode Control register of the CRT Controller (index 0x17, port 0x3d4) } PortW[CRTC_ADDR] := $E317;
{ Turn off doubleword mode, by setting the Underline Location register (index 0x14, port 0x3d4) } PortW[CRTC_ADDR] := $0014;
{ Clear entire video memory, by selecting all four planes, then writing color 0 to the entire segment. Stoopid FillChar fills 1 byte too short! } PortW[SEQU_ADDR] := $0F02; FillChar(Mem[$A000 : 0], $8000, 0); FillChar(Mem[$A000 : $8000], $8000, 0);
{ Give a small delay to let the screen sort itself out } Delay(100);
{ Turn the screen back on } Port[SEQU_ADDR] := 1; Port[SEQU_ADDR + 1] := Port[SEQU_ADDR + 1] and $DF; end; {SetXtended}
procedure InitGraph; var x,Radius:integer; Constant:real; ymov,tymov:word; begin HasBeenInitialized:=TRUE; Constant:=PI/180; writeln('Computing port lookup table...'); for x:=0 to 640 do PortLookUp[x]:=$100 shl (x and 3) + 2; writeln('Computing y lookup table...'); for x:=0 to 400 do yLookUp[x]:=x shl 7 + x shl 5; writeln('Computing sine and cosine lookup tables...'); for Radius:=0 to 300 do for x:=0 to 45 do begin SinRadiusTable[x,Radius]:=trunc(sin(x*Constant)*Radius); CosRadiusTable[x,Radius]:=trunc(cos(x*Constant)*Radius); end; {for} CurrentTextX:=0; CurrentTextY:=0; SetXtended; SetColor(15); CurrentPort:=PortLookUp[0]; end; {InitGraph}
procedure CloseGraph; begin AnnoyingErrorMessage; asm mov ax,0003h int 10h end; {asm} writeln('This program uses Mark Rosen''s graphics library.'); writeln('Send E-Mail to mrosen@peganet.com for more information'); end; {CloseGraph}
procedure SetColor(AColor:byte); begin AnnoyingErrorMessage; CurrentDrawingColor:=AColor mod 256; end; {SetColor}
function GetColor:byte; begin AnnoyingErrorMessage; GetColor:=CurrentDrawingColor; end; {GetColor}
procedure PutPixel(x,y:word); var t:word; begin if CurrentPort<>PortLookUp[x] then begin PortW[SEQU_ADDR] := PortLookUp[x]; CurrentPort:=PortLookUp[x]; end; {if}
{ Calculate address (y * 160 + x div 4) and write pixel } Mem[$A000 : yLookUp[y]+x shr 2] := CurrentDrawingColor; end; {PutPixel}
function GetPixel(x,y:word):byte; var t:word; begin PortW[SEQU_ADDR] := PortLookUp[x];
{ Calculate address (y * 160 + x div 4) and write pixel } GetPixel:=Mem[$A000 : yLookUp[y]+x shr 2]; end; {GetPixel}
procedure SetPalette(ColorNumber:byte;AColor:ColorType); begin AnnoyingErrorMessage; asm mov dx,3c8h mov al,[ColorNumber] out dx,al inc dx mov al,[AColor.Red] out dx,al mov al,[AColor.Green] out dx,al mov al,[AColor.Blue] out dx,al end; {asm} end; {SetAPaletteEntry}
procedure GetPalette(ColorNumber:byte;var TheColor:ColorType); var Rt,Gt,Bt:byte; begin AnnoyingErrorMessage; Rt:=TheColor.Red; Gt:=TheColor.Green; Bt:=TheColor.Blue; asm mov dx, 3c7h mov al, [ColorNumber] out dx, al inc dx inc dx in al, dx mov [Rt],al in al, dx mov [Gt],al in al, dx mov [Bt],al end; {asm} TheColor.Red:=Rt; TheColor.Green:=Gt; TheColor.Blue:=Bt; end; {GetAPaletteEntry}
procedure FadeScreen(Speed:SpeedRangeType); var HaveChangedSomething:boolean; CurrentColor:ColorType; x,Counter:integer; begin AnnoyingErrorMessage; HaveChangedSomething:=TRUE; while HaveChangedSomething do begin Delay(5*(10-Speed)); HaveChangedSomething:=FALSE; for x:=0 to 255 do begin GetPalette(x,CurrentColor); if CurrentColor.Red<>0 then begin dec(CurrentColor.Red); HaveChangedSomething:=TRUE; end; {if} if CurrentColor.Green<>0 then begin dec(CurrentColor.Green); HaveChangedSomething:=TRUE; end; {if} if CurrentColor.Blue<>0 then begin dec(CurrentColor.Blue); HaveChangedSomething:=TRUE; end; {if} SetPalette(x,CurrentColor); end; {for} end; {while} end; {FadeScreen}
procedure Line(x1, y1, x2, y2 : word); var i,DeltaX,DeltaY,numpixels, d,dinc1,dinc2, x,xinc1,xinc2, y,yinc1,yinc2:integer; begin DeltaX:=abs(x2-x1); DeltaY:=abs(y2-y1); if DeltaX>=deltay then begin numpixels:=DeltaX+1; d:= (2*deltay)-DeltaX; dinc1:=deltay shl 1; dinc2:=(deltay-DeltaX) shl 1; xinc1:=1; xinc2:=1; yinc1:=0; yinc2:=1; end {if} else begin numpixels:=deltay+1; d:=(2*DeltaX)-deltay; dinc1:=DeltaX shl 1; dinc2:=(DeltaX-deltay) shl 1; xinc1:= 0; xinc2:= 1; yinc1:=1; yinc2:=1; end; {else} if x1 > x2 then begin xinc1:=-xinc1; xinc2:=-xinc2; end; {if} if y1>y2 then begin yinc1:=-yinc1; yinc2:=-yinc2; end; {if} x:=x1; y:=y1; for i := 1 to numpixels do begin PutPixel(x,y); if d < 0 then begin d:= d+dinc1; x:= x+xinc1; y:= y+yinc1; end {f} else begin d:= d+dinc2; x:= x+xinc2; y:= y+yinc2; end; {else} end; {for} end; {Line}
procedure Bar(BeginX,BeginY,EndX,EndY:word); var y,x:word; size:word; begin AnnoyingErrorMessage; for x:=BeginX to EndX do for y:=BeginY to EndY do putpixel(x,y); end; {Box}
procedure Rectangle(BeginX,BeginY,EndX,EndY:word); begin AnnoyingErrorMessage; Line(BeginX,EndX,BeginY,EndY); Line(BeginX,EndX,BeginY,EndY); Line(BeginX,EndX,BeginY,EndY); Line(BeginX,EndX,BeginY,EndY); end; {Rectangle}
procedure Circle(x,y,Radius:word); var Angle,RealX,RealY, XPlusRealX,XMinusRealX,XPlusRealY,XMinusRealY, YPlusRealY,YMinusRealY,YPlusRealX,YMinusRealX:word; begin for Angle:=0 to 45 do begin RealX:=CosRadiusTable[Angle,Radius]; RealY:=SinRadiusTable[Angle,Radius];
XPlusRealX:=x+RealX; XPlusRealY:=x+RealY; XMinusRealX:=x-RealX; XMinusRealY:=x-RealY;
YPlusRealY:=y+RealY; YPlusRealX:=y+RealX; YMinusRealY:=y-RealY; YMinusRealX:=y-RealX;
putpixel(XPlusRealX,YPlusRealY); putpixel(XPlusRealX,YMinusRealY); putpixel(XMinusRealX,YPlusRealY); putpixel(XMinusRealX,YMinusRealY);
putpixel(XPlusRealY,YPlusRealX); putpixel(XPlusRealY,YMinusRealX); putpixel(XMinusRealY,YPlusRealX); putpixel(XMinusRealY,YMinusRealX); end; {for} end; {Circle}
procedure RecursiveFill(x,y:word;FillColor,Border:byte); var Direction:byte; begin if (GetPixel(x,y)<>FillColor) and (GetPixel(x,y)<>Border) then begin putpixel(x,y); for Direction:=1 to 4 do begin if (Direction=1) and (y>0) then RecursiveFill(x,y-1,FillColor,Border) else if (Direction=2) and (x<319) then RecursiveFill(x+1,y,FillColor,Border) else if (Direction=3) and (y<199) then RecursiveFill(x,y+1,FillColor,Border) else if (Direction=4) and (x>0) then RecursiveFill(x-1,y,FillColor,Border); end; {for} end; {if} end; {RecursiveFill}
procedure Fill(x,y:word;FillColor,Border:byte); begin setcolor(FillColor); RecursiveFill(x,y,FillColor,Border); end; {Fill}
procedure GetImage(var Image:ImageType;x1,y1,x2,y2:word); var yImg,yShl,x,y,size,vSeg,vOfs:word; begin Image.DeltaX:=abs(x1-x2); Image.DeltaY:=abs(y1-y2); GetMem(Image.Image,(Image.DeltaX+1)*(Image.DeltaY+1)); Image.vSegment:=seg(Image.Image^); vSeg:=Image.vSegment; Image.vOffset:=ofs(Image.Image^); vOfs:=Image.vOffset;
for x:=x1 to x2 do begin for y:=y1 to y2 do begin Mem[Image.vSegment:Image.vOffset+((y-y1)*(Image.DeltaX+1))+(x-x1)]:=GetPixel(x,y); end; {for} end; {for} end; {GetImage}
procedure PutImage(Image:ImageType;x1,y1:word); var yImg,yShl:word; x,y:word; begin for x:=0 to Image.DeltaX do begin for y:=0 to Image.DeltaY do begin setcolor(Mem[Image.vSegment:Image.vOffset+(y*(Image.DeltaX+1))+x]); putpixel(x+x1,y+y1); end; {for} end; {for} end; {PutImage}
procedure KillImage(var Image:ImageType); begin AnnoyingErrorMessage; FreeMem(Image.Image,(Image.DeltaX+1)*(Image.DeltaY+1)); end; {KillImage}
function Exp(base,exponent:word):word; var Temp,x:word; begin Temp:=1; for x:=1 to exponent do Temp:=Temp*base; Exp:=Temp; end; {Exp}
procedure ConvertDecimalToBinary(Something:word;var Bin:ByteBitType); var x:byte; temp:word; begin for x:=1 to 8 do Bin[x]:=FALSE; for x:=7 downto 0 do begin temp:=trunc(Something div Exp(2,x)); if temp>0 then Something:=Something-Exp(2,x); if temp=1 then Bin[x+1]:=TRUE; end; {for} end; {ConvertDecimalToBinary}
procedure PutChar(Font:FontEnumeratedType;xc,yc:word;AChar:char); var x,y:word; Line:byte; Temp:ByteBitType; begin AnnoyingErrorMessage; for y:=0 to 7 do begin Line:=Mem[$F000:$FA6E+(ord(AChar)*8)+y]; ConvertDecimalToBinary(Line,Temp); for x:=1 to 8 do if Temp[x] then putpixel((9-x)+xc,y+yc); end; end; {PutChar}
procedure WriteStringXY(Font:FontEnumeratedType;xc,yc:word;Thing:string); var TempX,TempY:word; x:byte; begin AnnoyingErrorMessage; TempX:=xc; TempY:=yc; for x:=1 to ord(Thing[0]) do begin PutChar(Font,TempX,TempY,Thing[x]); TempX:=TempX+8; if TempX>311 then begin TempX:=1; TempY:=TempY+8; end; {if} end; {for} end; {WriteStringXY}
procedure WriteString(Font:FontEnumeratedType;Thing:string); var TempX,TempY:word; x:byte; begin AnnoyingErrorMessage; TempX:=CurrentTextX; TempY:=CurrentTextY; for x:=1 to ord(Thing[0]) do begin PutChar(Font,TempX,TempY,Thing[x]); TempX:=TempX+8; if TempX>311 then begin TempX:=1; TempY:=TempY+8; end; {if} end; {for} CurrentTextX:=CurrentTextX+TempX; CurrentTextY:=CurrentTextY+TempY; end; {WriteString}
procedure FlipImage(var SomeImage:ImageType); var ey,by,HalfY,x,y:word; p1seg,p1ofs,p2seg,p2ofs:word; DeltaXPlus,DeltaYPlus:word; Temp:byte; begin DeltaXPlus:=SomeImage.DeltaX+1; DeltaYPlus:=SomeImage.DeltaY+1; HalfY:=((DeltaYPlus) div 2)-1; by:=SomeImage.vOffset; ey:=SomeImage.vOffset+(DeltaXPlus*DeltaYPlus); p1seg:=SomeImage.vSegment; p2seg:=SomeImage.vSegment; for y:=0 to HalfY do begin ey:=ey-DeltaXPlus; for x:=0 to SomeImage.DeltaX do begin Temp:=Mem[p1seg:by]; Mem[p1seg:by]:=Mem[p2seg:ey]; Mem[p2seg:ey]:=Temp; inc(ey); inc(by); end; {for} ey:=ey-DeltaXPlus; end; {for} end; {FlipImage}
procedure LoadTGA(var Image:PictureType;FileName:string); var fp:file; TempPalAndHeadPtr:pointer; TempImage:ImageType; vSeg,vOfs,x:word; TempColor:ColorType; Size,CurSize:longint; t,tOfs:longint; begin assign(fp,FileName); reset(fp,1); {no error checking as of yet}
GetMem(TempPalAndHeadPtr,786); new(Image.Palette);
BlockRead(fp,TempPalAndHeadPtr^,786); vSeg:=seg(TempPalAndHeadPtr^); vOfs:=ofs(TempPalAndHeadPtr^); Image.Picture.DeltaX:=(Mem[vSeg:vOfs+13] shl 8)+Mem[vSeg:vOfs+12]-1; Image.Picture.DeltaY:=(Mem[vSeg:vOfs+15] shl 8)+Mem[vSeg:vOfs+14]-1; vOfs:=vOfs+18; for x:=0 to 255 do begin TempColor.Blue:=Mem[vSeg:vOfs] shr 2; vOfs:=vOfs+1; TempColor.Green:=Mem[vSeg:vOfs] shr 2; vOfs:=vOfs+1; TempColor.Red:=Mem[vSeg:vOfs] shr 2; vOfs:=vOfs+1; Image.Palette^[x]:=TempColor; end; {for}
T:=filesize(fp); Size:=(Image.Picture.DeltaX+1)*(Image.Picture.DeltaY+1); GetMem(Image.Picture.Image,(Image.Picture.DeltaX+1)*(Image.Picture.DeltaY+1)); Image.Picture.vSegment:=seg(Image.Picture.Image^); Image.Picture.vOffset:=ofs(Image.Picture.Image^); seek(fp,786); { blockread(fp,Image.picture.image^,size);} if (Image.Picture.DeltaX+1)*(Image.Picture.DeltaY+1)<=TGASize then begin BlockRead(fp,Image.picture.image^,size); end {if} else begin tOfs:=Image.picture.vOffset; CurSize:=0; for x:=1 to size div (TGASize) do begin blockread(fp,ptr(Image.Picture.vSegment,tOfs)^,TGASize-2); tOfs:=tOfs+TGASize; CurSize:=CurSize+TGASize; end; {for} blockread(fp,ptr(Image.Picture.vSegment,tOfs)^,Size-CurSize); end; {else} FreeMem(TempPalAndHeadPtr,786);
FlipImage(Image.Picture); close(fp); end; {LoadTGA}
procedure DrawPicture(x1,y1:word;Image:PictureType;BeginPart,EndPart:byte); var x,vSeg,vOfs:word; Color:byte; begin for x:=BeginPart to EndPart do setpalette(x,Image.Palette^[x]); PutImage(Image.Picture,x1,y1); end; {DrawPicture}
procedure KillPicture(var Image:PictureType); begin KillImage(Image.Picture); dispose(Image.Palette); end; {KillPicture}
procedure ClearScreen; var x,y:word; begin setcolor(0); for x:=0 to 639 do for y:=0 to 479 do putpixel(x,y); end; {ClearScreen}
procedure InitGradatedPalette(var SomePalette:GradatedPaletteType); var Black:ColorType; x:byte; begin AnnoyingErrorMessage; new(SomePalette); Black.Red:=0; Black.Green:=0; Black.Blue:=0; for x:=0 to 255 do begin SomePalette^[x].Color:=Black; SomePalette^[x].IsAPoint:=FALSE; end; {for} end; {InitGradatedPalette}
procedure AddKeyPoint(var SomePalette:GradatedPaletteType;Location:byte; Color:ColorType); begin AnnoyingErrorMessage; SomePalette^[Location].Color:=Color; SomePalette^[Location].IsAPoint:=TRUE; SomePalette^[Location].Location:=Location; end; {AddKeyPoint}
procedure GeneratePalette(SomePalette:GradatedPaletteType); var TempColor:ColorType; Temp1,Temp2:ColorRecordType; Location1,Location2:byte; x,y:byte; Number:byte; Temp:array[0..255] of ColorRecordType; RealRed,RealGreen,RealBlue, IncRed,IncGreen,IncBlue:real; DeltaLoc:word; begin AnnoyingErrorMessage; Number:=0; {Condense the palette into only hot points} for x:=0 to 255 do begin if SomePalette^[x].IsAPoint then begin Temp[Number]:=SomePalette^[x]; Number:=Number+1; end; {if} end; {for} {actually gradate the palette} for x:=0 to Number-1 do begin Location1:=Temp[x].Location; Location2:=Temp[x+1].Location; DeltaLoc:=abs(Location2-Location1); RealRed:=Temp[x].Color.Red; RealGreen:=Temp[x].Color.Green; RealBlue:=Temp[x].Color.Blue; IncRed:=(Temp[x+1].Color.Red-Temp[x].Color.Red)/DeltaLoc; IncGreen:=(Temp[x+1].Color.Green-Temp[x].Color.Green)/DeltaLoc; IncBlue:=(Temp[x+1].Color.Blue-Temp[x].Color.Blue)/DeltaLoc; for y:=Location1 to Location2 do begin TempColor.Red:=trunc(RealRed); TempColor.Green:=trunc(RealGreen); TempColor.Blue:=trunc(RealBlue); setpalette(y,TempColor); RealRed:=RealRed+IncRed; RealGreen:=RealGreen+IncGreen; RealBlue:=RealBlue+IncBlue; end; {for} end; {for} end; {GeneratePalette}
procedure KillGradatedPalette(var SomePalette:GradatedPaletteType); begin AnnoyingErrorMessage; dispose(SomePalette); end; {KillGradatedPalette}
end. {Xlib}
|