Vgautil
Unit VgaUtil;
Interface
{$G+,R-}
Uses Crt;
{-$DEFINE CLIPADDPUT}
Const
Long = $66;
display1 : word = $0000;
display2 : word = $4000;
{ Vga card 64k bank select }
BankOfs : Array[0..3] of Word = (0, $4000, $8000, $A000);
BankNum : Array[0..3] of Byte = (0, 1, 2, 3);
Width = 80;
Numsins = 255;
HiNumsins = Numsins shl 6;
Pi = 3.1415;
MovPut = 0;
AddPut = 1;
SubPut = 2;
AndPut = 3;
OrPut = 4;
XorPut = 5;
TPut = 6;
Type AnyString = String[127];
RGB = Record
r, g, b : Byte;
End;
PaletteType = Array[0..255] of RGB;
P2dType = Record
x, y : Integer;
End;
P3dType = Record
x, y, z : Integer;
End;
P2dArray = Array[0..255] of P2dType;
P3dArray = Array[0..255] of P3dType;
Var
SinTable,CosTable: Array[0..Numsins] of integer;
Sin2Table,Cos2Table: Array[0..Numsins] of integer;
PageOffset : Word;
OldScreenMode, CurPage : Byte;
VLU : array[0..199] of word;
OldExitProc : pointer;
Pal : PaletteType;
{ For procedure comments you will have to hunt around, sorry... }
Procedure CalcSine;
Procedure CalcVLU;
Procedure SetGraphicsMode(Mode : Byte);
Procedure RefreshWait;
Procedure SetSingleColor(Var TPal : PaletteType; Col, R, G, B : Byte);
Procedure SetRGB(ColNum, R, G, B : Byte);
Procedure SetSPalette(Palette : PaletteType);
Procedure Fadepals(Startpal, Endpal : Palettetype; Steps : Integer);
Procedure Fadepalsstep(Startpal, Endpal : Palettetype; TotalSteps, CurStep : Integer);
Procedure GraphCLS;
Procedure VgaGetPic(x1, y1, x2, y2 : Integer; DestPtr : Pointer);
Procedure OldVgaPutPic(Mode : Byte; x1, y1: Integer; SrcPtr, DestPtr
: Pointer);
Procedure VGAClipPic(Mode : Byte; X1, Y1, XClip, YClip : Integer;
SrcPtr, DestPtr : Pointer);
Procedure VGAPutPic(Mode : Byte; X1, Y1 : Integer; SrcPtr, DestPtr :
Pointer);
Procedure RestoreBackground(X1, Y1, XSize, YSize : Integer; SrcPtr,
DestPtr : Pointer);
Procedure RestoreBackgroundVertical(Y1, Y2 : Integer; SrcPtr,
DestPtr : Pointer);
Procedure LoadPcx(FileName : AnyString; Var TPal : PaletteType; Orig
: Pointer);
Procedure LoadPcxPalette(FileName : AnyString; Var TPal :
PaletteType);
Procedure ClearPage(P : Pointer);
Procedure CopyPage(P : Pointer);
Procedure CopyPageOffset(P : Pointer; POffset : Word);
Procedure Copy2Pages(SrcP, DestP : Pointer);
Procedure SetStart(p:word);
Procedure SetBank(bank:byte);
Procedure Vgaline(const x1,y1,x2,y2,where:word;const c:byte);
function LongDiv(x : longint; y : integer) : integer;
inline($59/$58/$5A/$F7/$F9);
function LongMul(x, y : integer) : longint;
inline($5A/$58/$F7/$EA);
procedure SetBitplanes(planes : byte);
inline(
$BA/$C4/$03/ {mov dx,$3C4}
$58/ {pop ax}
$88/$C4/ {mov ah,al}
$B0/$02/ {mov al,$02}
$EF); {out dx,ax}
Implementation
procedure CLI; inline($FA);
procedure STI; inline($FB);
Procedure CalcSine; {Creates sin/cos tables}
Var direction:integer;
angle:real;
begin
For Direction:=0 to Numsins do begin {use 256 degrees in
circle}
angle:=Direction;
angle:=angle*3.14159265/128;
SinTable[Direction]:=round(Sin(angle)*256);
CosTable[Direction]:=round(Cos(angle)*256);
Sin2Table[Direction]:=round(Sin(angle+3.14159265/2)*256*1.2);
Cos2Table[Direction]:=round(Cos(angle+3.14159265/2)*256*1.2);
end; { the 1.2 accounts for pixel aspect ratio }
end;
{ Makes an array that speeds up pixel offset calculations }
{ Use like this...
Mov bx, (Y value here)
Shl bx, 1
Mov di, Word Ptr Vlu[bx]
Add di, (X value here)
DI now holds proper offset.
>> CONTINUED IN NEXT MESSAGE <<
================================================================================
Area: PASCAL
Date: 24 Jul 96 21:11:56 Public
From: Ryan Stowers
To: All
Subject: HERE IT IS FINALLY!!!!!!!!!! [2]
ÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄ
>> CONTINUED FROM PREVIOUS MESSAGE <<
VERY fast!!!
}
Procedure CalcVlu;
Var
A : Integer;
Begin
For a := 0 to 199 do
Vlu[A] := A * 320;
End;
{ Works for any graphics mode }
Procedure SetGraphicsMode(Mode : Byte); Assembler;
asm
Mov al, Mode
Xor ah, ah
Int 10H
end;
{ One of Bjarke's routines }
{$F+}
procedure ScreenExitProc;
{$F-}
begin
ExitProc := OldExitProc;
If (ExitCode <> 0) then
Begin
SetGraphicsMode($03); {if runtime error, restore screen}
Writeln('Mega screw up error #',ExitCode);
End;
end;
{ Wait for vertical retrace }
Procedure RefreshWait; Assembler;
Asm
Mov dx,$3da
@Looper:
In al,dx
And al,8
Jz @Looper
End;
Procedure SetSingleColor(Var TPal : PaletteType; Col, R, G, B :
Byte);
Begin
Pal[Col].r := R;
Pal[Col].g := G;
Pal[Col].b := B;
End;
{ One of Bjarke's routines. Very useful. }
Procedure SetRGB(ColNum, R, G, B : Byte); assembler;
Asm
Mov dx, $3c8
Mov al, ColNum
Out dx, al
Inc dx
Mov al, R
Out dx, al
Mov al, G
Out dx, al
Mov al, B
Out dx, al
End;
{ One of Bjarke's routines, but i modified it to use a static array
insted
of a pointer. }
Procedure SetSPalette(Palette : PaletteType);
Var
Count : Integer;
Begin
Asm
Mov dx,$3c8
Xor al,al
Out dx,al
Inc dx
Mov si,0
Mov cx,768
@Looper:
Mov al,Byte Ptr [Palette+si]
Out dx,al
Inc si
Dec cx
Jnz @Looper
End;
End;
Procedure Fadepals(Startpal, Endpal : Palettetype; Steps : Integer);
Var
Temppal : PaletteType;
MCount, PCount : Integer;
Begin
For MCount := Steps downto 0 do
Begin
For PCount := 0 to 255 do
Begin
Temppal[PCount].r := ((startpal[PCount].r * MCount) div
Steps)+
((endpal[PCount].r *
(Steps-MCount)) div Steps);
Temppal[PCount].g := ((startpal[PCount].g * MCount) div
Steps)+
((endpal[PCount].g *
(Steps-MCount)) div Steps);
Temppal[PCount].b := ((startpal[PCount].b * MCount) div
Steps)+
((endpal[PCount].b *
(Steps-MCount)) div Steps);
End;
SetSpalette(Temppal);
RefreshWait;
end;
SetSPalette(Endpal);
End;
Procedure Fadepalsstep(Startpal, Endpal : Palettetype; TotalSteps,
CurStep : Integer);
Var
Temppal : PaletteType;
PCount : Integer;
Begin
For PCount := 0 to 255 do
Begin
SetRGB(PCount,
((startpal[PCount].r * CurStep) div TotalSteps)+
((endpal[PCount].r * (TotalSteps-CurStep)) div
TotalSteps),
((startpal[PCount].g * CurStep) div TotalSteps)+
((endpal[PCount].g * (TotalSteps-CurStep)) div
TotalSteps),
((startpal[PCount].b * CurStep) div TotalSteps)+
((endpal[PCount].b * (TotalSteps-CurStep)) div
TotalSteps));
End;
End;
{ Ummm..... What does this procedure do... }
Procedure GraphCLS;
Begin
Fillchar(Mem[Sega000:0], 64000, 0);
End;
{ Just like GET in BASIC for grabbing screen images, but you dont
need a
{ static array like in BASIC. Just use a pointer }
{ NOT optimized, but works. Just make sure you used GETMEM with
DestPtr.}
{ x1,y1,x2,y2 = Coordinates of the screen you want to get }
Procedure VgaGetPic(x1, y1, x2, y2 : Integer; DestPtr : Pointer);
Var
VCount, HCount, DestSeg, DestOfs, CurOfs, W, H :Integer;
Begin
DestSeg := Seg(DestPtr^);
DestOfs := Ofs(DestPtr^);
W := (x2 - x1);
H := (y2 - y1);
CurOfs := 0;
MemW[DestSeg:DestOfs + CurOfs] := W;
Inc(CurOfs,2);
MemW[DestSeg:DestOfs + CurOfs] := H;
Inc(CurOfs,2);
For VCount := y1 to y2 do
Begin
For HCount := x1 to x2 do
Begin
Mem[DestSeg:DestOfs + CurOfs] := Mem[$a000:HCount + VCount
* 320];
Inc(CurOfs);
End;
End;
End;
{ Just like PUT in BASIC for putting images on the screen. Im
pretty sure
this one does all the clipping you need, but its older and slower
than
the newer one (look below)
Mode = Use one of the constants for MOV, ADD, SUB, etc, etc
x1,y1 = coordinates
SrcPtr = source bitmap
DestPtr = destination bitmap can be either direct video or a
virtual page
}
Procedure OldVgaPutPic(Mode : Byte; x1, y1: Integer; SrcPtr, DestPtr
: Pointer);
Var DestSeg, Bytes, WordsLeft, BytesLeft : Word;
DestStartx, DestStarty, XWriteLen, YWriteLen, SrcOfs : Integer;
PicW, PicH, DestStartYOfs, StartYOfs, DestXerror, Xerror, Tilt :
Integer;
Begin
PicW := MemW[Seg(SrcPtr^):Ofs(SrcPtr^) + 0] + 1;
PicH := MemW[Seg(SrcPtr^):Ofs(SrcPtr^) + 2] + 1;
If X1 > 319 then exit;
If Y1 > 199 then Exit;
If X1 < -PicW then exit;
If Y1 < -PicH then exit;
SrcOfs := Ofs(SrcPtr^);
Asm
Mov Tilt, 0
Mov ax, 16
Sub ax, PicW
Mov Xerror, 0 { Xerror := (16 - PicW)}
Mov ax, X1 { DestStartX := X1 }
Mov DestStartx, ax
Mov ax, Y1 { DestStarty := Y1 }
Mov DestStartY, ax
Mov ax, PicW { XWriteLen := PicW }
Mov XWriteLen, ax
Mov ax, PicH { YWriteLen := PicH }
Mov YWriteLen, ax
Mov StartYOfs, 4
Cmp Y1, 0 { If Y1 < 0 then }
Jg @SkipY11
Mov ax, PicH
Add ax, Y1
Mov YWriteLen, ax
Mov DestStartY, 0 { DestStartY := 0 }
Mov ax, Y1 { StartYOfs := StartYOfs + Abs(y1) * PicW }
Not ax
Add ax, 1
Mul PicW
Add StartYOfs, ax
@SkipY11:
Mov ax, Y1 { If (Y1 + YWriteLen) > 199 then }
Add ax, YWriteLen
Cmp ax, 199
Jl @SkipY12
Mov ax, 200 { YWriteLen := 200 - Y1 }
Sub ax, Y1
Mov YWriteLen, ax
@SkipY12:
Cmp X1, 0 { If X < 0 then }
Jg @SkipX11
Mov ax, X1 { Xerror := Abs(X1) }
Not ax
add ax, 1
Mov Xerror, ax
Mov ax, X1 { XWriteLen := XWriteLen + X1 }
Add XWriteLen, ax
Mov ax, Xerror { StartYofs := StartYOfs + Xerror }
Add StartYOfs, ax
Mov DestStartX, 0 { DestStartX := 0 }
@SkipX11:
Mov ax, X1 { If (X1 + XWriteLen) > 319 then }
Add ax, XWriteLen
Cmp ax, 319
Jl @SkipX12
Mov ax, 320 { XWriteLen := 320 - X1 }
Sub ax, X1
Mov XWriteLen, ax
Mov ax, 320 { Xerror := X1 - (320 - PicW) }
Sub ax, PicW
Mov bx, X1
Sub bx, ax
Mov Xerror, bx
@SkipX12:
Cmp XWriteLen, 0
Jg @Oops1
Mov Tilt, 1
@Oops1:
Cmp YWriteLen, 0
Jg @Oops2
Mov Tilt, 1
@Oops2:
{ Dest start coordinates computer }
Mov ax, DestStartY { Y coordinate }
Mov bx, ax
Shl ax, 6
Add ah, bl
Add ax, DestStartX { X coordinate }
Mov DestStartYOfs, ax
Mov ax, 320 { DestXError := 320 - XwriteLen }
Sub ax, XwriteLen
Mov DestXError, ax
End;
If Tilt <> 0 Then Exit;
Case Mode of
{ MOV }
0:Begin
Bytes := Word(XWriteLen div 4);
WordsLeft := (Xwritelen mod 4) and 2;
BytesLeft := (Xwritelen mod 4) and 1;
If DestPtr = Nil then
DestSeg := $a000
else
DestSeg := Seg(DestPtr^);
Asm
Mov ax, 0 {Y Loop Count}
Mov es, DestSeg {Dest segment }
Mov si, StartYOfs {Src offset}
Mov di, DestStartYOfs {Dest offset}
Push ds {Save ds}
Lds cx, SrcPtr {Load SrcPtr into ds}
@YLooper:
db 66h; Mov cx, Bytes; { Move double words at one to
increase speed }
db 66h; Rep Movsw
Mov cx, WordsLeft
Jcxz @SkipZero1
Movsw
@SkipZero1:
Mov cx, BytesLeft
Jcxz @SkipZero2
Movsb
@SkipZero2:
Add si, XError {Fix offscreen clipping errors}
Add di, DestXError
Inc Ax {Increment Ax}
Cmp ax, YWriteLen {If ax < YWritelen then.. }
Jl @YLooper {Goto @YLooper}
Pop Ds {All done, restore ds to prevent stack errors}
End;
End;
{ Addition PUT }
1:Begin
If DestPtr = Nil then
DestSeg := $a000
else
DestSeg := Seg(DestPtr^);
Asm
Mov ax, 0 {Init Y Count }
Mov es, DestSeg { Init dest segment }
Mov si, StartYOfs { Init source offset }
Mov di, DestStartYOfs
{Get source segment and figure source start coordinates}
Push Ds
Lds cx, SrcPtr {Load SrcPtr into ds}
@YLooper:
{ Loop length computer }
Mov cx, XWriteLen
Shr cx,1
Jnc @SkipSingle
Mov dl, es:[di]
Add dl, ds:[si]
Mov es:[di], dl
Inc di; Inc si
@SkipSingle:
Jcxz @Exit
@XLooper:
Mov dl, es:[di]
Add dl, ds:[si]
Mov dh, es:[di+1]
Add dh, ds:[si+1]
Mov es:[di], dx
Add si, 2; Add di, 2
Loop @XLooper
@Exit:
Add si, XError {Fix offscreen clipping errors}
Add di, DestXError
Inc Ax {Increment ax counter}
Cmp ax, YWriteLen {If y < YWriteLen then... }
Jl @YLooper {Goto YLooper}
Pop Ds { All done, restore Ds to prevent stack errors }
End;
End;
{ Subtraction PUT }
2:Begin
If DestPtr = Nil then
DestSeg := $a000
else
DestSeg := Seg(DestPtr^);
Asm
Mov ax, 0 {Init Y Count }
Mov es, DestSeg { Init dest segment }
Mov si, StartYOfs { Init source offset }
Mov di, DestStartYofs
{Get source segment and figure source start coordinates}
Push Ds
Lds cx, SrcPtr {Load SrcPtr into ds}
@YLooper:
{ Loop length computer }
Mov cx, XWriteLen
Shr cx,1
Jnc @SkipSingle
Mov dl, es:[di]
Sub dl, ds:[si]
Mov es:[di], dl
Inc di; Inc si
@SkipSingle:
Jcxz @Exit
@XLooper:
Mov dl, es:[di]
Sub dl, ds:[si]
Mov dh, es:[di+1]
Sub dh, ds:[si+1]
Mov es:[di], dx
Add si, 2; Add di, 2
Loop @XLooper
@Exit:
Add si, XError {Fix offscreen clipping errors}
Add di, DestXerror
Inc Ax {Increment ax counter}
Cmp ax, YWriteLen {If y < YWriteLen then... }
Jl @YLooper {Goto YLooper}
Pop Ds { All done, restore Ds to prevent stack errors }
End;
End;
{ XOR PUT }
3:Begin
If DestPtr = Nil then
DestSeg := $a000
else
DestSeg := Seg(DestPtr^);
Asm
Mov ax, 0 {Init Y Count }
Mov es, DestSeg { Init dest segment }
Mov si, StartYOfs { Init source offset }
Mov di, DestStartYofs
{Get source segment and figure source start coordinates}
Push Ds
Lds cx, SrcPtr {Load SrcPtr into ds}
@YLooper:
{ Loop length computer }
Mov cx, XWriteLen
Shr cx,1
Jnc @SkipSingle
Mov dl, es:[di]
Xor dl, ds:[si]
Mov es:[di], dl
Inc di; Inc si
@SkipSingle:
Jcxz @Exit
@XLooper:
Mov dl, es:[di]
Xor dl, ds:[si]
Mov dh, es:[di+1]
Xor dh, ds:[si+1]
Mov es:[di], dx
Add si, 2; Add di, 2
Loop @XLooper
@Exit:
Add si, XError {Fix offscreen clipping errors}
Add di, DestXError
Inc Ax {Increment ax counter}
Cmp ax, YWriteLen {If y < YWriteLen then... }
Jl @YLooper {Goto YLooper}
Pop Ds { All done, restore Ds to prevent stack errors }
End;
End;
{ AND PUT }
4:Begin
If DestPtr = Nil then
DestSeg := $a000
else
DestSeg := Seg(DestPtr^);
Asm
Mov ax, 0 {Init Y Count }
Mov es, DestSeg { Init dest segment }
Mov si, StartYOfs { Init source offset }
Mov di, DestStartYofs
{Get source segment and figure source start coordinates}
Push Ds
Lds cx, SrcPtr {Load SrcPtr into ds}
@YLooper:
{ Loop length computer }
Mov cx, XWriteLen
Shr cx,1
Jnc @SkipSingle
Mov dl, es:[di]
And dl, ds:[si]
Mov es:[di], dl
Inc di; Inc si
@SkipSingle:
Jcxz @Exit
@XLooper:
Mov dl, es:[di]
And dl, ds:[si]
Mov dh, es:[di+1]
And dh, ds:[si+1]
Mov es:[di], dx
Add si, 2; Add di, 2
Loop @XLooper
@Exit:
Add si, XError {Fix offscreen clipping errors}
Add di, DestXError
Inc Ax {Increment ax counter}
Cmp ax, YWriteLen {If y < YWriteLen then... }
Jl @YLooper {Goto YLooper}
Pop Ds { All done, restore Ds to prevent stack errors }
End;
End;
{ NOT PUT - This is good for some strange effects if used
correctly }
5:Begin
If DestPtr = Nil then
DestSeg := $a000
else
DestSeg := Seg(DestPtr^);
Asm
Mov ax, 0 {Init Y Count }
Mov es, DestSeg { Init dest segment }
Mov si, StartYOfs { Init source offset }
Mov di, DestStartYofs
{Get source segment and figure source start coordinates}
Push Ds
Lds cx, SrcPtr {Load SrcPtr into ds}
@YLooper:
{ Loop length computer }
Mov cx, XWriteLen
Shr cx,1
Jnc @SkipSingle
Mov dl, es:[di]
Add dl, ds:[si]; Not dl
Mov es:[di], dl
Inc di; Inc si
@SkipSingle:
Jcxz @Exit
@XLooper:
Mov dl, es:[di]
Add dl, ds:[si]; Not dl
Mov dh, es:[di+1]
Add dh, ds:[si+1]; Not dh
Mov es:[di], dx
Add si, 2; Add di, 2
Loop @XLooper
@Exit:
Add si, XError {Fix offscreen clipping errors}
Add di, DestXerror
Inc Ax {Increment ax counter}
Cmp ax, YWriteLen {If y < YWriteLen then... }
Jl @YLooper {Goto YLooper}
Pop Ds { All done, restore Ds to prevent stack errors }
End;
End;
{ Transparent MOV }
6:Begin
If DestPtr = Nil then
DestSeg := $a000
else
DestSeg := Seg(DestPtr^);
Asm
Mov ax, 0 {Init Y Count }
Mov es, DestSeg { Init dest segment }
Mov si, StartYOfs { Init source offset }
Mov di, DestStartYOfs
{Get source segment and figure source start coordinates}
Push Ds
Lds cx, SrcPtr {Load SrcPtr into ds}
@YLooper:
{ Loop length computer }
Mov cx, XWriteLen
Shr cx,1
Jnc @SkipSingle
Mov dl, ds:[si]
Or dl, dl
Jz @SkipZero1
Mov es:[di], dl
@SkipZero1:
Inc di; Inc si
@SkipSingle:
Jcxz @Exit
@XLooper:
Mov dx, ds:[si]
Or dl, dl
Jnz @SkipZero2
Mov dl, es:[di]
@SkipZero2:
Or dh, dh
Jnz @SkipZero3
Mov dh, es:[di+1]
@SkipZero3:
Mov es:[di], dx
Add si, 2; Add di, 2
Loop @XLooper
@Exit:
Add si, XError {Fix offscreen clipping errors}
Add di, DestXerror
Inc Ax {Increment ax counter}
Cmp ax, YWriteLen {If y < YWriteLen then... }
Jl @YLooper {Goto YLooper}
Pop Ds { All done, restore Ds to prevent stack errors }
End;
End;
End; {Case}
End;
{ Same thing as OldVGAPutPic, this one (sort of) clips. Clipping not
quite
finished yet. Use this PUTPIC only if you know that a bitmap will
go off
screen. Routines are quicker (i think?) since I tried to use less
local
variables and more registers
Mode = Use predefined constants from the top of the program
X1 = X position of picture
Y1 = Y position of picture
Next two are user clip functions! I found this useful in
displaying a fuse
that is burning it self down (i.e. show less and less of the fuse
as time
goes on)
XClip = Number of pixels to clip from X size
YClip = Number of pixels to clip from Y size
SrcPtr, DestPtr = Source and destination virtual pages }
Procedure VGAClipPic(Mode : Byte; X1, Y1, XClip, YClip : Integer;
SrcPtr, DestPtr : Pointer);
Label _StopDraw;
Var OutSeg, YSize, XSize, YOfs, XDiff, XSiDiff : Word;
Begin
If DestPtr = Nil then OutSeg := SegA000 else OutSeg :=
Seg(DestPtr^);
If XClip < 0 then XClip := 0;
If YClip < 0 then YClip := 0;
Asm
{ ----- Determine start adress ----- }
Mov XSiDiff, 0
Mov bx, Y1; Shl bx, 1;
Mov ax, Word Ptr [Vlu+bx]; Mov Yofs, ax
{ ----- Load X and Y sizes ----- }
Les di, SrcPtr
Mov ax, es:[di]; Inc ax;
Mov XSize, ax
Mov bx, 320; Sub bx, XSize; Mov XDiff, bx
Mov ax, es:[di+2]; Inc ax
Mov YSize, ax
Mov ax, OutSeg
Mov es, ax
{ ----- Range checking ----- }
Cmp Y1, 200
Jae _StopDraw
Cmp X1, 320
Jae _StopDraw
{ ----- Clipping routines ----- }
Mov dx, 200; Sub dx, YSize
Cmp Y1, dx
Jbe @SkipMaxY
Mov ax, Y1
Sub ax, dx
Sub YSize, ax
@SkipMaxY:
Mov dx, 320; Sub dx, XSize
Cmp X1, dx
Jbe @SkipMaxX
Mov ax, X1
Sub ax, dx
Sub XSize, ax
Add XDiff, ax
Mov XSiDiff, ax
@SkipMaxX:
{ ----- User clip. sometimes VERY useful! ----- }
Mov ax, XClip
Sub XSize, ax
Add XDiff, ax
Add XSiDiff, ax
Mov ax, YClip
Sub YSize, ax
{ ----- if we aint even gonna see a sprite, exit for godsake!
----- }
Mov ax, XSize
And ax, ax
Js _StopDraw
And ax, ax
Jz _StopDraw
Mov ax, YSize
And ax, ax
Js _StopDraw
And ax, ax
Jz _StopDraw
{ ----- Misc stuff ----- }
Mov di, Yofs
Add di, X1
@Stop:
End;
Case Mode of
{ ----- MOV PUT ----- }
0: Asm
Push ds
Lds si, SrcPtr; Add si, 4
Mov cx, YSize
Cld
@YLooper:
Push cx
Mov cx, XSize;
Shr cx, 1
Jnc @SkipSingleByte
Movsb
@SkipSingleByte:
Jcxz @Exit
Shr cx, 1
Jnc @SkipSingleWord
Movsw
@SkipSingleWord:
Jcxz @Exit
Db 66h; Rep Movsw
@Exit:
Add di, XDiff
Add si, XSiDiff
Pop cx
Dec cx
Jnz @YLooper
Pop ds
End;
{ ----- ADD PUT ----- }
1: Asm
Push ds
Cld
Lds si, SrcPtr; Add si, 4
Mov cx, YSize
@YLooper:
Push cx
Mov cx, XSize;
Shr cx, 1
Jnc @SkipSingle
Mov bl, [es:di]
Mov al, [ds:si]
Add al, bl;
Mov [es:di], al; Inc di; Inc si
@SkipSingle:
Jcxz @Exit
@XLooper:
Mov ax, [ds:si]
Mov bx, [es:di]
Add al, bl;
{$IFDEF CLIPADDPUT}
Jnc @ResetAL
Mov al, 255;
@ResetAL:
{$ENDIF}
Add ah, bh;
{$IFDEF CLIPADDPUT}
Jnc @ResetAH
Mov ah, 255;
@ResetAH:
{$ENDIF}
Mov [es:di], ax; Add di, 2; Add si, 2
Dec cx
Jnz @XLooper
@Exit:
Add di, XDiff
Add si, XSiDiff
Pop cx
Dec cx
Jnz @YLooper
Pop ds
End;
{ ----- SUB PUT ----- }
2: Asm
Push ds
Cld
Lds si, SrcPtr; Add si, 4
Mov cx, YSize
@YLooper:
Push cx
Mov cx, XSize;
Shr cx, 1
Jnc @SkipSingle
Mov bl, [es:di]
Mov al, [ds:si]
Sub al, bl;
Mov [es:di], al; Inc di; Inc si
@SkipSingle:
Jcxz @Exit
@XLooper:
Mov bx, [es:di]
Mov ax, [ds:si]
Sub al, bl; Sub ah, bh
Mov [es:di], ax; Add di, 2; Add si, 2
Dec cx
Jnz @XLooper
@Exit:
Add di, XDiff
Add si, XSiDiff
Pop cx
Dec cx
Jnz @YLooper
Pop ds
End;
{ ----- AND PUT ----- }
3: Asm
Push ds
Cld
Lds si, SrcPtr; Add si, 4
Mov cx, YSize
@YLooper:
Push cx
Mov cx, XSize;
Shr cx, 1
Jnc @SkipSingle
Mov bl, [es:di]
Mov al, [ds:si]
And al, bl;
Mov [es:di], al; Inc di; Inc si
@SkipSingle:
Jcxz @Exit
@XLooper:
Mov bx, [es:di]
Mov ax, [ds:si]
And al, bl; And ah, bh
Mov [es:di], ax; Add di, 2; Add si, 2
Dec cx
Jnz @XLooper
@Exit:
Add di, XDiff
Add si, XSiDiff
Pop cx
Dec cx
Jnz @YLooper
Pop ds
End;
{ ----- OR PUT ----- }
4: Asm
Push ds
Cld
Lds si, SrcPtr; Add si, 4
Mov cx, YSize
@YLooper:
Push cx
Mov cx, XSize;
Shr cx, 1
Jnc @SkipSingle
Mov bl, [es:di]
Mov al, [ds:si]
Or al, bl;
Mov [es:di], al; Inc di; Inc si
@SkipSingle:
Jcxz @Exit
@XLooper:
Mov bx, [es:di]
Mov ax, [ds:si]
Or al, bl; Or ah, bh
Mov [es:di], ax
Add di, 2; Add si, 2
Dec cx
Jnz @XLooper
@Exit:
Add di, XDiff
Add si, XSiDiff
Pop cx
Dec cx
Jnz @YLooper
Pop ds
End;
{ ----- XOR PUT ----- }
5: Asm
Push ds
Cld
Lds si, SrcPtr; Add si, 4
Mov cx, YSize
@YLooper:
Push cx
Mov cx, XSize;
Shr cx, 1
Jnc @SkipSingle
Mov bl, [es:di]
Mov al, [ds:si]
Xor al, bl;
Mov [es:di], al; Inc di; Inc si
@SkipSingle:
Jcxz @Exit
@XLooper:
Mov bx, [es:di]
Mov ax, [ds:si]
Xor al, bl; Xor ah, bh
Mov [es:di], ax; Add di, 2; Add si, 2
Dec cx
Jnz @XLooper
@Exit:
Add di, XDiff
Add si, XSiDiff
Pop cx
Dec cx
Jnz @YLooper
Pop ds
End;
{ ----- TRANSPARENT PUT ----- }
6: Asm
Push ds
Cld
Lds si, SrcPtr; Add si, 4
Mov cx, YSize
@YLooper:
Push cx
Mov cx, XSize;
Shr cx, 1
Jnc @TSkipSingle
Mov al, [ds:si]
Or al, al
Jz @TSkipZeroB
Mov [es:di], al
@TSkipZeroB:
Inc di; Inc si
@TSkipSingle:
Jcxz @TExit
@XLooper:
Mov ax, [ds:si];
Or al, al
Je @TSkipZeroWL
Mov [es:di], al
@TSkipZeroWL:
Or ah, ah
Je @TSkipZeroWH
Mov [es:di+1], ah
@TSkipZeroWH:
Add di, 2; Add si, 2
Dec cx
Jnz @XLooper
@TExit:
Add di, XDiff
Add si, XSiDiff
Pop cx
Dec cx
Jnz @YLooper
Pop ds
End;
End;
_StopDraw:;
End;
{ DOES NOT CLIP AT ALL! Just does renage checking. Use this for
faster
PUTs if your bitmap will stay within the screen boundaries }
Procedure VGAPutPic(Mode : Byte; X1, Y1 : Integer; SrcPtr, DestPtr :
Pointer);
Label _StopDraw;
Var OutSeg, YSize, XSize, YOfs, XDiff : Word;
Begin
If DestPtr = Nil then OutSeg := SegA000 else OutSeg :=
Seg(DestPtr^);
Asm
{ ----- Determine start adress ----- }
Mov bx, Y1; Shl bx, 1;
Mov ax, Word Ptr [Vlu+bx]; Mov Yofs, ax
{ ----- Load X and Y sizes ----- }
Les di, SrcPtr
Mov ax, es:[di]; Inc ax;
Mov XSize, ax
Mov bx, 320; Sub bx, XSize; Mov XDiff, bx
Mov ax, es:[di+2]; Inc ax
Mov YSize, ax
Mov ax, OutSeg
Mov es, ax
{ ----- Range checking ----- }
{ Upper limit check (down and right) }
Mov ax, Y1
Add ax, YSize
Cmp ax, 200
Jae _StopDraw
Mov ax, X1
Add ax, XSize
Cmp ax, 320
Jae _StopDraw
{ Lower limit (up and left) }
Mov ax, Y1
Cmp ax, 200
Jae _StopDraw
Mov ax, X1
Cmp ax, 320
Jae _StopDraw
{ No clipping routines here!!! }
{ ----- Misc stuff ----- }
Mov di, Yofs
Add di, X1
@Stop:
End;
Case Mode of
{ ----- MOV PUT ----- }
0: Asm
Push ds
Lds si, SrcPtr; Add si, 4
Mov cx, YSize
Cld
@YLooper:
Push cx
Mov cx, XSize;
Shr cx, 1
Jnc @SkipSingleByte
Movsb
@SkipSingleByte:
Jcxz @Exit
Shr cx, 1
Jnc @SkipSingleWord
Movsw
@SkipSingleWord:
Jcxz @Exit
Db 66h; Rep Movsw
@Exit:
Add di, XDiff
Pop cx
Dec cx
Jnz @YLooper
Pop ds
End;
{ ----- ADD PUT ----- }
1: Asm
Push ds
Cld
Lds si, SrcPtr; Add si, 4
Mov cx, YSize
@YLooper:
Push cx
Mov cx, XSize;
Shr cx, 1
Jnc @SkipSingle
Mov bl, [es:di]
Mov al, [ds:si]
Add al, bl;
Mov [es:di], al; Inc di; Inc si
@SkipSingle:
Jcxz @Exit
@XLooper:
Mov ax, [ds:si]
Mov bx, [es:di]
Add al, bl;
{$IFDEF CLIPADDPUT}
Jnc @ResetAL
Mov al, 255;
@ResetAL:
{$ENDIF}
Add ah, bh;
{$IFDEF CLIPADDPUT}
Jnc @ResetAH
Mov ah, 255;
@ResetAH:
>> CONTINUED IN NEXT MESSAGE <<
================================================================================
Area: PASCAL
Date: 24 Jul 96 21:14:55 Public
From: Ryan Stowers
To: All
Subject: VGAUTIL 4/7 [2]
ÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄ
>> CONTINUED FROM PREVIOUS MESSAGE <<
{$ENDIF}
Mov [es:di], ax; Add di, 2; Add si, 2
Dec cx
Jnz @XLooper
@Exit:
Add di, XDiff
Pop cx
Dec cx
Jnz @YLooper
Pop ds
End;
{ ----- SUB PUT ----- }
2: Asm
Push ds
Cld
Lds si, SrcPtr; Add si, 4
Mov cx, YSize
@YLooper:
Push cx
Mov cx, XSize;
Shr cx, 1
Jnc @SkipSingle
Mov bl, [es:di]
Mov al, [ds:si]
Sub al, bl;
Mov [es:di], al; Inc di; Inc si
@SkipSingle:
Jcxz @Exit
@XLooper:
Mov bx, [es:di]
Mov ax, [ds:si]
Sub al, bl; Sub ah, bh
Mov [es:di], ax; Add di, 2; Add si, 2
Dec cx
Jnz @XLooper
@Exit:
Add di, XDiff
Pop cx
Dec cx
Jnz @YLooper
Pop ds
End;
{ ----- AND PUT ----- }
3: Asm
Push ds
Cld
Lds si, SrcPtr; Add si, 4
Mov cx, YSize
@YLooper:
Push cx
Mov cx, XSize;
Shr cx, 1
Jnc @SkipSingle
Mov bl, [es:di]
Mov al, [ds:si]
And al, bl;
Mov [es:di], al; Inc di; Inc si
@SkipSingle:
Jcxz @Exit
@XLooper:
Mov bx, [es:di]
Mov ax, [ds:si]
And al, bl; And ah, bh
Mov [es:di], ax; Add di, 2; Add si, 2
Dec cx
Jnz @XLooper
@Exit:
Add di, XDiff
Pop cx
Dec cx
Jnz @YLooper
Pop ds
End;
{ ----- OR PUT ----- }
4: Asm
Push ds
Cld
Lds si, SrcPtr; Add si, 4
Mov cx, YSize
@YLooper:
Push cx
Mov cx, XSize;
Shr cx, 1
Jnc @SkipSingle
Mov bl, [es:di]
Mov al, [ds:si]
Or al, bl;
Mov [es:di], al; Inc di; Inc si
@SkipSingle:
Jcxz @Exit
@XLooper:
Mov bx, [es:di]
Mov ax, [ds:si]
Or al, bl; Or ah, bh
Mov [es:di], ax
Add di, 2; Add si, 2
Dec cx
Jnz @XLooper
@Exit:
Add di, XDiff
Pop cx
Dec cx
Jnz @YLooper
Pop ds
End;
{ ----- XOR PUT ----- }
5: Asm
Push ds
Cld
Lds si, SrcPtr; Add si, 4
Mov cx, YSize
@YLooper:
Push cx
Mov cx, XSize;
Shr cx, 1
Jnc @SkipSingle
Mov bl, [es:di]
Mov al, [ds:si]
Xor al, bl;
Mov [es:di], al; Inc di; Inc si
@SkipSingle:
Jcxz @Exit
@XLooper:
Mov bx, [es:di]
Mov ax, [ds:si]
Xor al, bl; Xor ah, bh
Mov [es:di], ax; Add di, 2; Add si, 2
Dec cx
Jnz @XLooper
@Exit:
Add di, XDiff
Pop cx
Dec cx
Jnz @YLooper
Pop ds
End;
{ ----- TRANSPARENT PUT ----- }
6: Asm
Push ds
Cld
Lds si, SrcPtr; Add si, 4
Mov cx, YSize
@YLooper:
Push cx
Mov cx, XSize;
Shr cx, 1
Jnc @TSkipSingle
Mov al, [ds:si]
Or al, al
Jz @TSkipZeroB
Mov [es:di], al
Inc di; Inc si
@TSkipZeroB:
@TSkipSingle:
Jcxz @TExit
@XLooper:
Mov ax, [ds:si];
Or al, al
Je @TSkipZeroWL
Mov [es:di], al
@TSkipZeroWL:
Or ah, ah
Je @TSkipZeroWH
Mov [es:di+1], ah
@TSkipZeroWH:
Add di, 2; Add si, 2
Dec cx
Jnz @XLooper
@TExit:
Add di, XDiff
Pop cx
Dec cx
Jnz @YLooper
Pop ds
End;
End;
_StopDraw:;
End;
{ The next two procedures are used for restoring backgrounds in my
sprite
and vector routines. Ask me and ill give them to you }
{ RestoreBackgoround aint really that fast. It would be more useful
in mode-x
sprite programming }
Procedure RestoreBackground(X1, Y1, XSize, YSize : Integer; SrcPtr,
DestPtr : Pointer);
Label _TotalExit;
Var OutSeg, YOfs, XDiff : Word;
Begin
If DestPtr = Nil then OutSeg := $A000 else OutSeg :=
Seg(DestPtr^);
Asm
{ ----- Determine starting offset ----- }
Mov bx, Y1; Shl bx, 1;
Mov ax, Word Ptr [Vlu+bx]; Mov Yofs, ax
Mov ax, OutSeg
Mov es, ax
Mov bx, 320; Sub bx, XSize; Mov XDiff, bx
Mov dx, 320; Sub dx, XSize
{ ----- Range checking ----- }
Mov ax, Y1; Add ax, Xsize
Cmp ax, 199
Jae @Stop
Mov ax, X1; Add ax, Ysize
Cmp ax, 319
Jae @Stop
{ ----- Clipping Routines ----- }
Mov dx, 200; Sub dx, YSize
Cmp Y1, dx
Jbe @SkipMaxY
Mov ax, Y1
Sub ax, dx
Sub YSize, ax
@SkipMaxY:
Mov dx, 320; Sub dx, XSize
Cmp X1, dx
Jbe @SkipMaxX
Mov ax, X1
Sub ax, dx
Sub XSize, ax
Add XDiff, ax
@SkipMaxX:
Mov di, Yofs
Add di, X1
{ ----- draw the sucker ----- }
Push ds
Lds si, SrcPtr;
Mov si, Yofs; Add si, X1
Cld
Mov cx, YSize
@YLooper:
Push cx
Mov cx, XSize;
Shr cx, 1
Jnc @SkipSingle
Movsb
@SkipSingle:
Jcxz @Exit
Rep Movsw
@Exit:
Add di, XDiff
Add si, XDiff
Pop cx
Dec cx
Jnz @YLooper
Pop ds
@Stop:
End;
End;
{ This one is really fast (386 instr). Y1 is the top line of SrcPtr
and Y2
is the bottom line of ScrPtr to copy to DestPtr }
Procedure RestoreBackgroundVertical(Y1, Y2 : Integer; SrcPtr,
DestPtr : Pointer);
Var Bytes, StartOfs : Word;
Tmp : Integer;
Begin
If Y1 > Y2 then
Begin
Tmp := Y1;
Y1 := Y2;
Y2 := Tmp;
End;
If Y1 < 0 then Y1 := 0;
If Y2 > 199 then Y2 := 199;
Bytes := (Y2-Y1) * 80;
If Bytes = 0 then Exit;
StartOfs := Vlu[Y1];
Asm
Mov cx, StartOfs
Mov dx, Bytes
Push ds
Push es
Cld
Les di, DestPtr
Lds si, SrcPtr
Mov di, cx; Mov si, cx
db 66h; Mov cx, dx;
db 66h; Rep Movsw
Pop es
Pop ds
End;
End;
{ 'down and dirty' pcx loader. ONLY works with 256 color pictures
and is
limited to files <= 64k :(. If you try to load something over 64k
the
machine WILL NOT LOCK but pcx will be all screwed up and so will
the
palette.
If you can, please modify it so it can take >64k pcx files and/or
16 color
pictures
FileName = String that holds the filename
TPal = Palette of the picture. It's AUTOMATICALLY set when you use
this
procedure
Orig = Pointer (remember to use GETMEM) that you want the
extracted image
to go
}
Procedure LoadPcx(FileName : AnyString; Var TPal : PaletteType; Orig
: Pointer);
Var
Size : Word;
TextureOffset : Word;
Count, PcxW, PcxH, TmpCount : Word;
RunLen : Byte;
Value : Byte;
RVal, GVal, BVal : Byte;
PCXOffset, OutOfs : Word;
PCXSeg, OutSeg : Word;
PCXFile : File;
PCXBuffer : Pointer;
TmpLong : LongInt;
Begin
Assign(PcxFile, FileName);
Reset(PcxFile, 1);
TmpLong := FileSize(PcxFile);
If TmpLong > $ffff then TmpLong := $ffff;
GetMem(PcxBuffer, TmpLong);
BlockRead(PcxFile, PcxBuffer^, TmpLong);
OutSeg := Seg(Orig^);
OutOfs := Ofs(Orig^);
PcxSeg := Seg(PcxBuffer^);
PcxOffset := Ofs(PcxBuffer^);
{ Get picture width and height }
PcxW := MemW[PcxSeg:PcxOffset + 10];
PcxH := MemW[PcxSeg:PcxOffset + 12];
PcxOffset := Ofs(PcxBuffer^) + 128;
TextureOffset := 0;
Size := 65535;
While TextureOffset < Size do
Begin
RunLen := Mem[PcxSeg:PcxOffset];
Inc(PcxOffset);
If (RunLen and $C0) = $C0
Then Begin
RunLen := RunLen And $3f;
Value := Mem[PCXSeg:PcxOffset];
Inc(PcxOffset);
End
Else Begin
Value := RunLen;
RunLen := 1;
End;
While (RunLen >= 1) and (TextureOffset < Size) do
Begin
{If Value < MinCol then Value := MinCol;
If Value > MaxCol then Value := MaxCol;}
Mem[OutSeg:OutOfs+TextureOffset] := Value;
TextureOffset := TextureOffset + 1;
RunLen := RunLen - 1;
End;
End;
{ Get palette }
PcxOffset := Ofs(PcxBuffer^);
Count := TmpLong - 768;
For TmpCount := 0 to 255 do
Begin
Port[$3c8] := TmpCount;
RVal := Mem[PcxSeg : PcxOffset + Count];
If TmpCount = 0 then RVal := 0;
Port[$3c9] := RVal div 4;
Tpal[TmpCount].r := Rval div 4;
Inc(Count);
GVal := Mem[PcxSeg : PcxOffset + Count];
If TmpCount = 0 then gVal := 0;
Port[$3c9] := GVal div 4;
Tpal[TmpCount].g := Gval div 4;
Inc(Count);
BVal := Mem[PcxSeg : PcxOffset + Count];
If TmpCount = 0 then bVal := 0;
Port[$3c9] := BVal div 4;
Tpal[TmpCount].b := Bval div 4;
Inc(Count);
End;
FreeMem(PcxBuffer, TmpLong);
Close(PcxFile);
End;
{ Just loads the pcx file's palette into TPal }
Procedure LoadPcxPalette(FileName : AnyString; Var TPal :
PaletteType);
Var
Size : Word;
Count, TmpCount : Word;
RVal, GVal, BVal : Byte;
PCXSeg, PCXOffset : Word;
PCXFile : File;
PCXBuffer : Pointer;
TmpLong : LongInt;
Begin
Assign(PcxFile, FileName);
Reset(PcxFile, 1);
TmpLong := FileSize(PcxFile);
If TmpLong > $ffff then TmpLong := $ffff;
GetMem(PcxBuffer, TmpLong);
BlockRead(PcxFile, PcxBuffer^, TmpLong);
PcxSeg := Seg(PcxBuffer^);
PcxOffset := Ofs(PcxBuffer^);
Count := TmpLong - 768;
For TmpCount := 0 to 255 do
Begin
Port[$3c8] := TmpCount;
RVal := Mem[PcxSeg : PcxOffset + Count];
If TmpCount = 0 then RVal := 0;
Port[$3c9] := RVal div 4;
Tpal[TmpCount].r := Rval div 4;
Inc(Count);
GVal := Mem[PcxSeg : PcxOffset + Count];
If TmpCount = 0 then gVal := 0;
Port[$3c9] := GVal div 4;
Tpal[TmpCount].g := Gval div 4;
Inc(Count);
BVal := Mem[PcxSeg : PcxOffset + Count];
If TmpCount = 0 then bVal := 0;
Port[$3c9] := BVal div 4;
Tpal[TmpCount].b := Bval div 4;
Inc(Count);
End;
FreeMem(PcxBuffer, TmpLong);
Close(PcxFile);
End;
{ Clears a virtual page }
Procedure ClearPage(P : Pointer); Assembler;
Asm
Les di,P
Mov cx, 16000
db 66h; Xor ax, ax
db 66h; Rep Stosw
End;
{Copies a virtual page to video memory}
Procedure CopyPage(P : Pointer); Assembler;
Asm
Push ds
Push es
Cld
Mov ax,$A000
Mov es,ax
Mov di, 0
Lds si, P
db 66h; Mov cx,16000; dw 0;
db 66h; Rep Movsw
Pop es
Pop ds
End;
{Copies a virtual page to video memory with 'offset' :P}
{Note: this routine causes a protection fault so dont use it unless
you can
debug it}
Procedure CopyPageOffset(P : Pointer; POffset : Word); Assembler;
Asm
Push ds
Push es
Cld
Mov ax,$A000
Mov es,ax
Mov di, 0
Lds si, P
db 66h; Mov cx,16000; dw 0;
db 66h; Rep Movsw
Pop es
Pop ds
End;
{ Copies a virtual page to another virtual page }
Procedure Copy2Pages(SrcP, DestP : Pointer); assembler;
Asm
Push ds
Les di, DestP
Lds si, SrcP
db 66h; Mov cx, 16000; dw 0;
db 66h; Rep Movsw
Pop ds
End;
{ One of Bjarke's routines sets the start position of the video
cards video
memory. Use this for hardware scrolling }
Procedure SetStart(p:word); assembler;
Asm
Mov dx,$3d4;Mov bx,p;Mov al,$c; Mov ah,bh;Out dx,ax;Inc al;Mov ah,bl;Out dx,ax;Mov Word Ptr PageOffset, bx;
End;
{ Only works with my Tseng/ET4000 video card apparently. Selects
different
256k sections of my card for SVGA modes. }
Procedure SetBank(bank:byte);
Begin
Port[$03cd] := Bank;
End;
Procedure Vgaline(const x1,y1,x2,y2,where:word;const c:byte);
var
dex,dey,incf:Integer;
offset:word;
begin
{I added the next 2 lines because this routine is not perfect. I
get
garbage whenever I use this im my vector program }
If (y1 <= 0) or (y1 > 319) or (y2 <= 0) or (y2 > 319) then exit;
{If (x2-x1 = 0) or (x1-x2 = 0) then exit;}
asm
mov ax,[x2]
sub ax,[x1]
jnc @@dont1
neg ax
@@dont1:
mov [dex],ax
mov ax,[y2]
sub ax,[y1]
jnc @@dont2
neg ax
@@dont2:
mov [dey],ax
cmp ax,[dex]
jbe @@otherline
mov ax,[y1]
cmp ax,[y2]
jbe @@DontSwap1
mov bx,[y2]
mov [y1],bx
mov [y2],ax
mov ax,[x1]
mov bx,[x2]
mov [x1],bx
mov [x2],ax
@@dontswap1:
mov [incf],1
mov ax,[x1]
cmp ax,[x2]
jbe @@skipnegate1
neg [incf]
@@skipnegate1:
mov di,[y1]
mov bx,di
shl di,8
shl bx,6
add di,bx
add di,[x1]
mov bx,[dey]
mov cx,bx
mov ax,where
mov es,ax
mov dl,[c]
mov si,[dex]
@@drawloop1:
mov es:[di],dl
add di,320
sub bx,si
jnc @@goon1
add bx,[dey]
add di,[incf]
@@goon1:
loop @@drawloop1
jmp @@exitline
@@otherline:
mov ax,[x1]
cmp ax,[x2]
jbe @@dontswap2
mov bx,[x2]
mov [x1],bx
mov [x2],ax
mov ax,[y1]
mov bx,[y2]
mov [y1],bx
mov [y2],ax
@@dontswap2:
mov [incf],320
mov ax,[y1]
cmp ax,[y2]
jbe @@skipnegate2
neg [incf]
@@skipnegate2:
mov di,[y1]
mov bx,di
shl di,8
shl bx,6
add di,bx
add di,[x1]
mov bx,[dex]
mov cx,bx
mov ax,where
mov es,ax
mov dl,[c]
mov si,[dey]
@@drawloop2:
mov es:[di],dl
inc di
sub bx,si
jnc @@goon2
add bx,[dex]
add di,[incf]
@@goon2:
loop @@drawloop2
@@exitline:
end;
end;
Begin
End.