home *** CD-ROM | disk | FTP | other *** search
- Unit MCGA04;
-
- interface
-
- type
- PCXHeaderPtr= ^PCXHeader;
- PCXHeader = record
- Signature : Char;
- Version : Char;
- Encoding : Char;
- BitsPerPixel : Char;
- XMin,YMin,
- XMax,YMax : Integer;
- HRes,VRes : Integer;
- Palette : Array [0..47] of byte;
- Reserved : Char;
- Planes : Char;
- BytesPerLine : Integer;
- PaletteType : Integer;
- Filler : Array [0..57] of byte;
- end;
-
- Procedure SetGraphMode (Num:Byte);
- Procedure SetPixel (X,Y:Integer;Color:Byte);
-
- Procedure LineEqu (X1,Y1,X2,Y2:Integer;Color:Byte);
- Procedure LineIndiv (X1,Y1,X2,Y2:Integer;Color:Byte);
- Procedure Line (X1,Y1,X2,Y2:Integer;Color:Byte);
-
- Procedure DisplayPCXPas (X,Y:Integer;Buf:Pointer);
- Procedure DisplayPCXAsm (X,Y:Integer;Buf:Pointer);
-
- implementation
-
- uses
- Dos;
-
- var
- ScreenWide : Integer;
- ScreenAddr : Word;
-
- Procedure SetGraphMode (Num:Byte);
- begin
- asm
- mov al,Num
- mov ah,0
- int 10h
- end;
- Case Num of
- $13 : ScreenWide := 320;
- end;
- ScreenAddr := $A000;
- end;
-
- Procedure SetPixel (X,Y:Integer;Color:Byte);
- begin
- asm
- push ds
- mov ax,ScreenAddr
- mov ds,ax
-
- mov ax,Y
- mov bx,320
- mul bx
- mov bx,X
- add bx,ax
-
- mov al,Color
- mov byte ptr ds:[bx],al
- pop ds
- end;
- end;
-
- Procedure LineEqu (X1,Y1,X2,Y2:Integer;Color:Byte);
- var
- Slope : Real;
- D,X,Y : Integer;
- begin
- If (X1 = X2) or (Y1 = Y2) then Exit;
- If X1 > X2 then begin
- D := X1;
- X1 := X2;
- X2 := D;
- D := Y1;
- Y1 := Y2;
- Y2 := D;
- end;
- Slope := (Y2-Y1)/(X2-X1);
- If Abs(Y2-Y1) > Abs(X2-X1) then begin
- Slope := (X2-X1)/(Y2-Y1);
- For Y := Y1 to X2 do
- SetPixel (Trunc(Slope*(Y-Y1)+X1),Y,Color);
- end
- Else begin
- Slope := (Y2-Y1)/(X2-X1);
- For X := X1 to X2 do
- SetPixel (X,Trunc(Slope*(X-X1)+Y1),Color);
- end;
- end;
-
- Procedure LineIndiv (X1,Y1,X2,Y2:Integer;Color:Byte);
- var
- X,Y,
- YIncr,
- D,DX,DY,
- AIncr,BIncr : Integer;
- Ofs : Word;
- begin
- If X1 > X2 then begin
- D := X1;
- X1 := X2;
- X2 := D;
- D := Y1;
- Y1 := Y2;
- Y2 := D;
- end;
- If Y2 > Y1 then YIncr := 1
- else YIncr := -1;
- DX := X2 - X1;
- DY := Abs (Y2-Y1);
- D := 2 * DY - DX;
- AIncr := 2 * (DY - DX);
- BIncr := 2 * DY;
-
- X := X1;
- Y := Y1;
- SetPixel (X,Y,Color);
-
- For X := X1 + 1 to X2 do begin
- If D >= 0 then begin
- Inc (Y,YIncr);
- Inc (D,AIncr);
- end
- Else Inc (D,BIncr);
- SetPixel (X,Y,Color);
- end;
- end;
-
- Procedure Line (X1,Y1,X2,Y2:Integer;Color:Byte);
- var
- I,
- YIncr,
- D,DX,DY,
- AIncr,BIncr : Integer;
- Ofs : Word;
- begin
- If X1 > X2 then begin
- D := X1;
- X1 := X2;
- X2 := D;
- D := Y1;
- Y1 := Y2;
- Y2 := D;
- end;
- If Y2 > Y1 then YIncr := 320
- else YIncr := -320;
- DX := X2 - X1;
- DY := Abs (Y2-Y1);
- D := 2 * DY - DX;
- AIncr := 2 * (DY - DX);
- BIncr := 2 * DY;
-
- Ofs := Word(Y1) * 320 + Word(X1);
-
- Mem [$A000:Ofs] := Color;
-
- For I := X1 + 1 to X2 do begin
- If D >= 0 then begin
- Inc (Ofs,YIncr);
- Inc (D,AIncr);
- end
- Else Inc (D,BIncr);
- Inc (Ofs);
- Mem [$A000:Ofs] := Color;
- end;
- end;
-
- Procedure ExtractLinePas (BytesWide:Integer;Var Source,Dest:Pointer);
- var
- DestIdx,
- SourceIdx : Integer;
- InCode,
- RunCount : Byte;
- begin
- DestIdx := 0;
- SourceIdx := 0;
-
- While DestIdx < BytesWide do begin
- InCode := Mem [Seg(Source^):Ofs(Source^)+SourceIdx];
- Inc (SourceIdx);
-
- If (InCode and $C0) = $C0 then begin
- RunCount := InCode and $3F;
- InCode := Mem [Seg(Source^):Ofs(Source^)+SourceIdx];
- Inc (SourceIdx);
- FillChar (Mem[Seg(Dest^):Ofs(Dest^)+DestIdx],RunCount,InCode);
- Inc (DestIdx,RunCount);
- end
- Else begin
- Mem [Seg(Dest^):Ofs(Dest^)+DestIdx] := InCode;
- Inc (DestIdx);
- end;
- end;
- If Odd (BytesWide) then Source := Ptr(Seg(Source^),Ofs(Source^)+SourceIdx+2)
- else Source := Ptr(Seg(Source^),Ofs(Source^)+SourceIdx);
- Dest := Ptr(Seg(Dest^),Ofs(Dest^)+DestIdx);
- end;
-
- Procedure ExtractLineASM (BytesWide:Integer;Var Source,Dest:Pointer);
- var
- DestSeg,
- DestOfs,
- SourceSeg,
- SourceOfs : Word;
- begin
- SourceSeg := Seg (Source^);
- SourceOfs := Ofs (Source^);
- DestSeg := Seg (Dest^);
- DestOfs := Ofs (Dest^);
-
- asm
- push ds
- push si
-
- mov ax,DestSeg
- mov es,ax
- mov di,DestOfs { es:di -> destination pointer }
- mov ax,SourceSeg
- mov ds,ax
- mov si,SourceOfs { ds:si -> source buffer }
-
- mov bx,di
- add bx,BytesWide { bx holds position to stop for this row }
- xor cx,cx
-
- @@GetNextByte:
- cmp bx,di { are we done with the line }
- jbe @@ExitHere
-
- lodsb { al contains next byte }
-
- mov ah,al
- and ah,0C0h
- cmp ah,0C0h
- jne @@SingleByte
- { must be a run of bytes }
- mov cl,al
- and cl,3Fh
- lodsb
- rep stosb
- jmp @@GetNextByte
-
- @@SingleByte:
- stosb
- jmp @@GetNextByte
-
- @@ExitHere:
- mov SourceSeg,ds
- mov SourceOfs,si
- mov DestSeg,es
- mov DestOfs,di
-
- pop si
- pop ds
- end;
-
- If Odd(BytesWide) then Source := Ptr (SourceSeg,SourceOfs+2)
- else Source := Ptr (SourceSeg,SourceOfs);
-
- Dest := Ptr (DestSeg,DestOfs);
- end;
-
- Procedure DisplayPCXAsm (X,Y:Integer;Buf:Pointer);
- var
- I,NumRows,
- BytesWide : Integer;
- Header : PCXHeaderPtr;
- DestPtr : Pointer;
- Offset : Word;
- begin
- Header := Ptr (Seg(Buf^),Ofs(Buf^));
- Buf := Ptr (Seg(Buf^),Ofs(Buf^)+128);
- Offset := Y * 320 + X;
- NumRows := Header^.YMax - Header^.YMin + 1;
- BytesWide := Header^.XMax - Header^.XMin + 1;
- For I := 1 to NumRows do begin
- DestPtr := Ptr ($A000,Offset);
- ExtractLineASM (BytesWide,Buf,DestPtr);
- Inc (Offset,320);
- end;
- end;
-
- Procedure DisplayPCXPas (X,Y:Integer;Buf:Pointer);
- var
- I,NumRows,
- BytesWide : Integer;
- Header : PCXHeaderPtr;
- DestPtr : Pointer;
- Offset : Word;
- begin
- Header := Ptr (Seg(Buf^),Ofs(Buf^));
- Buf := Ptr (Seg(Buf^),Ofs(Buf^)+128);
- Offset := Y * 320 + X;
- NumRows := Header^.YMax - Header^.YMin + 1;
- BytesWide := Header^.XMax - Header^.XMin + 1;
- For I := 1 to NumRows do begin
- DestPtr := Ptr ($A000,Offset);
- ExtractLinePas (BytesWide,Buf,DestPtr);
- Inc (Offset,320);
- end;
- end;
-
- end.
-