{**** An include file that contains EGA Graphics primitives. ****} TYPE RegisterPack = RECORD AX, BX, CX, DX, BP, SI, DI, DS, ES, Flags : INTEGER END; VAR Rec : RegisterPack; Xaddr : ARRAY[0..639] OF INTEGER; Yaddr : ARRAY[0..349] OF INTEGER; Point : ARRAY[0..639] OF INTEGER; PROCEDURE Init_graphics; VAR indx : INTEGER; switches : BYTE; info : BYTE; mono : BOOLEAN; BEGIN switches := MEM[$40 : $88] AND $0F; info := MEM[$40 : $87]; { mono is TRUE if monochrome display attached to EGA } mono := ODD((info AND $02) SHR 1); { now we set up registers for the mode set based on } { switch settings and information byte bits } IF mono THEN rec.ax := $000F { 640 X 350 monochrome } ELSE WITH rec DO CASE switches OF 6 : ax := $0D; { Color 40 X 25 -- 320 X 200 } 7 : ax := $0E; { Color 80 X 25 -- 640 X 200 } 8 : ax := $10; { Enhanced color -- normal mode } 9 : ax := $10; { Enhanced color -- enhanced mode ELSE rec.ax := $0E; { Default to "safe" 640 X 200 mode} END; { CASE } INTR($10,rec); {**** Arrays used to avoid repetitive address calculations.} FOR indx := 0 TO 349 DO Yaddr[indx] := 80*indx; FOR indx := 0 TO 639 DO Xaddr[indx] := indx DIV 8; FOR indx := 0 TO 639 DO Point[indx] := $80 SHR (indx MOD 8) END; PROCEDURE plot( x, y : INTEGER); VAR total : INTEGER; BEGIN total := Xaddr[x] + Yaddr[y]; {**** EGA memory is sequential starting at $A000.} MEM[$A000: total] := point[x] OR MEM[$a000: total] END; PROCEDURE switch(VAR first, second : INTEGER); VAR temp : INTEGER; BEGIN temp := first; first := second; second := temp END; PROCEDURE draw( xx1, yy1, xx2, yy2 : INTEGER); VAR Lg_delta, Sh_delta, Cycle, Lg_step, Sh_step, dtotal : INTEGER; BEGIN {**** Set up deltas and steps according to the relationship of (X1, Y1) and (X2, Y2).} Lg_delta := xx2 - xx1; Sh_delta := yy2 - yy1; IF Lg_delta < 0 THEN BEGIN Lg_delta := -Lg_delta; Lg_step := -1 END ELSE Lg_step := 1; IF Sh_delta < 0 THEN BEGIN Sh_delta := -Sh_delta; Sh_step := -1 END ELSE Sh_step := 1; IF Sh_delta < Lg_delta THEN BEGIN {**** Here is the expected case of a longer X-axis so make cycle = large_delta/2 and do the normal increments.} cycle := lg_delta SHR 1; WHILE xx1 <> xx2 DO BEGIN {**** While the endpoints do not meet Plot and make the usual increments.} dtotal := Xaddr[xx1] + Yaddr[yy1]; MEM[$A000: dtotal] := point[xx1] OR MEM[$a000: dtotal]; xx1 := xx1 + Lg_step; cycle := cycle + Sh_delta; IF cycle > Lg_delta THEN BEGIN yy1 := yy1 + Sh_step; cycle := cycle - Lg_delta END END END ELSE BEGIN {**** This is the reverse of what we expect so make the cycle = short_delta/2 and switch deltas and steps.} cycle := sh_delta SHR 1; switch(lg_delta, Sh_delta); switch(lg_step, sh_step); WHILE yy1 <> yy2 DO BEGIN {**** While the endpoints do not meet Plot and make the increments.} dtotal := Xaddr[xx1] + Yaddr[yy1]; MEM[$A000: dtotal] := point[xx1] OR MEM[$A000: dtotal]; yy1 := yy1 + lg_step; cycle := cycle + sh_delta; IF cycle > lg_delta THEN BEGIN cycle := cycle - lg_delta; xx1 := xx1 + sh_step END END END END; FUNCTION isqrt( arg : INTEGER) : INTEGER; {**** Returns the integer sqrt without using reals.} VAR odd_int, old_arg, first_sqrt : INTEGER; BEGIN odd_int := 1; old_arg := arg; WHILE arg >= 0 DO BEGIN arg := arg - odd_int; odd_int := odd_int + 2; END; first_sqrt := odd_int SHR 1; {**** Now a fixup to take care of overshoots.} IF SQR(first_sqrt) - first_sqrt + 1 > old_arg THEN isqrt := first_sqrt - 1 ELSE isqrt := first_sqrt END; PROCEDURE circle( cx, cy, radius : INTEGER); VAR a, af, b, bf, target, r2 : INTEGER; BEGIN target := 0; a := radius; b := 0; r2 := sqr(radius); WHILE a >= b DO BEGIN b := ROUND(sqrt(r2 - sqr(a))); {**** Use Isqrt(r2 - sqr(a)) here if you do not have the 8087 chip.} switch( target, b); WHILE b < target DO {**** Inner loop takes care of straight lines at cardinal points.} BEGIN {**** Put in aspect correction and make use of the symmetry of a circle by plotting 8 points for each calculation.} af := 120*a DIV 100; bf := 120*b DIV 100; plot(cx + af, cy + b); plot(cx + bf, cy + a); plot(cx - af, cy + b); plot(cx - bf, cy + a); plot(cx - af, cy - b); plot(cx - bf, cy - a); plot(cx + af, cy - b); plot(cx + bf, cy - a); b := b + 1; END; a := a - 1; END END; PROCEDURE Screen_dump; VAR xindx, yindx : INTEGER; init_char : STRING[4]; BEGIN {**** The next two lines are for the Epson FX, JX, and MX with GrafTrax+. } WRITELN(LST,CHR(27)+'A'+CHR(7)); WRITELN(lst,chr(27)+'2'); INIT_CHAR := CHR(27)+'K'+CHR(94)+CHR(1); FOR xindx := 0 TO 79 DO BEGIN WRITE(LST, init_char); FOR yindx:=349 DOWNTO 0 DO WRITE(LST,CHR(MEM[$A000: Yaddr[yindx]+xindx])); WRITELN(LST); END; WRITELN(LST,CHR(27) + '@'); {**** Clear printer attributes.} WRITELN(LST); END;