1 /* ; FILE IDENTIFICATION
4 ; Purpose: Draw lines on screen using Bresenham's integer algorithm
5 ; Programmer: Kevin Rosenberg
6 ; Date Started: 1 Jun 84
7 ; Last Modification: 15 Jul 85, Version 1.0
12 ; Newport Beach, CA 92663
13 ; (714) 642-0119 (voice)
14 ; (714) 842-6348 (E-Mail on Consultant's Exchange RBBS)
15 ; Compuserve 73775,1232
18 ; IBM macro v1.000000000
21 ; Public routines callable from Lattice C v2.0+
22 ; Works with S & L memory models. Can easily add support for the
23 ; other models by changing the STK structure below.
26 ; egadrive.inc Definitions, macros, & procedures for driving EGA
27 ; hidden.inc Defines OPTIONAL public procedure, crt_hdn_line().
28 ; dos.mac Lattice's file containing memory model macros
29 ; See inclusion statement for more documentation
31 ; GRAPHIC MODES SUPPORTED
32 ; - Standard CGA modes -- BIOS codes 4, 5, & 6 -- are support through
33 ; the ROM BIOS pixel setting routine. Things could be speeded up
34 ; by a factor of 7-15 by writing to the video buffer directly.
35 ; - You may remove support for the CGA completely by changing the
36 ; EQU of STD_GRF to 0, a slight speed increase in EGA operations
38 ; - All EGA graphic modes are supported with optimized direct pixel
39 ; accessing. Note: mode 13 (320x200) is bugged, see LOG date 6-20-85
46 ; Released in PD as version 1.0
48 ; Put EGA routines in INCLUDE file EGADRIVE.INC
49 ; Put Hidden line routines in OPTIONAL INCLUDE file HIDDEN.INC
51 ; Tested with video modes 13 (320x200) & 14 (640x200). Mode 14 worked
52 ; ok, mode 13 was missing every other vertical line: I'm probably
53 ; not setting one of the myriad of registers correctly. Since I'll
54 ; never use mode 13, I won't investigate it further.
56 ; Added & updated documentation
58 ; Added hidden line routines
59 ; PUBLIC crt_hdn_line plus internal routines
60 ; (see function summary for more info)
62 ; Added global variable STD_GRF
63 ; Will support standard graphic modes if it is set to non-zero value;
64 ; however, the slow ROM BIOS is used as well as a slight overhead
65 ; for the EG code. IT IS MUCH FASTER TO USE THE EGA ENHANCED
66 ; (350 line) GRAPHIC MODES.
68 ; Convert to support IBM's Enhanced graphics adapter.
69 ; Remove all optimized code for color graphics adapter (CGA)
71 ; Changed calls to ROM that set pixels to speedy routines which use
72 ; incremental address calculation and direct writing the to graphics
76 ; Converted C function, bresline.c, to assembly langauge.
77 ; Retained C source of Bresenham's integer rastering algorithm
82 ; crt_line_page (page)
83 ; Set graphics page to plot lines on [default = 0]
85 ; crt_line_style (style)
86 ; Set line style [Default = solid line]
88 ; crt_line (x1, y1, x2, y1, color)
89 ; Plots a line on the screen using Bresenham's integer algorithm
91 ; crt_hdn_line (x1, y1, x2, y1, color, col_min, col_max)
92 ; OPTIONAL routine to plots lines using hidden areas
93 ; INCLUDE file HIDDEN.INC if you wish to use this routine
95 ; crt_init_hdn (col_min, col_max)
96 ; Initializes vectors for use with crt_hdn_line()
99 ; int x1, y1 - starting point
100 ; int x2, y2 - end point
101 ; int color - color to draw line, as defined by IBM bios setting
102 ; int linestyle - 16 bit wide dot setting pattern
103 ; int col_min[640] Minimum values for each X column (initialize to 349)
104 ; int col_max[640] Maximum values for each X column (initialize to 0)
105 ; (Do not display any points between the min & max,
106 ; and update these values for each new min & max)
107 ; If a vector == NULL, then do not clip against that
110 ; REFERENCES FOR BRESENHAM'S ALGORITHM
111 ; Newman & Sproll, "Principals of Interactive Computer Graphics",
113 ; Foley & van Dam, "Fundementals of Interactive Computer Graphics",
117 ;------ Bresenham variables
123 min_inc dw ? ; (-1, 1) indicates direction of minor axis
124 dinc1 dw ? ; d increment if (d >= 0)
125 dinc2 dw ? ; d increment if (d < 0)
130 ;------------------------------------------------------------------------------
132 ; crt_line [PUBLIC] Plot a line on the screen using Bresenham's alg
135 ; crt_line (x1, y1, x2, y2, color)
137 void bresenham (int x1, int y1, int x2, int y2)
140 dx_abs = (delta_x >= 0 ? delta_x : -delta_x);
143 dy_abs = (delta_y >= 0 ? delta_y : -delta_y);
155 ;------------------------------------------------------------------------------
160 ; Do inner most loop to draw pictures
164 ; P1 Major axis & direction
171 ; (DI) Address of local routine to call when setting pixel
172 ; (BX) Decision variable
173 ; (CX) Number of points to plot on major axis (loop counter)
174 ; [bp].min_inc Direction of minor axis increments
175 ; [bp].dinc1 Bresenham decision increments (see references)
177 ; MACROS ADDR_INC_ROW, _DEC_ROW, _INC_COL, _DEC_COL
179 ; REGISTERS USED BY PIXEL SETTING ROUTINES
180 ; (SI) Offset in EGA buffer
183 ; REGISTERS AVAILABLE FOR USE
188 ; LS_PSET, this routine uses the addr in (DI) to set a point if
189 ; the linestyle allows.
190 ;------------------------------------------------------------------------------
194 cmp [bp].min_inc,0 ;if (min_inc >= 0)
196 _BRES P1,INC_&P2 ; inc_minor_axis
198 b0: _BRES P1,DEC_&P2 ; dec_minor_axis
204 LOCAL bres0,bres1,bres2
206 LS_PSET ; ls_pset() /* set pix using linestyle */
208 ADDR_&P1 ; P1 (change major axis)
211 jge bres1 ; if (d < 0)
212 add bx,[bp].dinc2 ; d += dinc2;
215 add bx,[bp].dinc1 ; d += dinc1
216 ADDR_&P2 ; P2 (change minor axis)
219 loop bres0 ; } while (--count > 0)
224 /* draws a line then abs(dx) >= abs(dy) */
226 int npix = dx_abs + 1;
228 /* determine direction of minor axis */
234 /* Put decision variable in d */
236 int d = dy_abs * 2 - dx_abs;
237 int dinc1 = (dy_abs - dx_abs) * 2;
238 int dinc2 = 2 * dy_abs;
243 breas (DEC_COL, ROW)l
250 /*; bresy [LOCAL] For plotting lines with abs(dy) > abs(sx)
253 Logic identical to bresx's, substitution x for y and
254 vice versa. I separate the into two routines rather
255 than having the main loop spending time determining
256 which are the major & minor axis.
260 int count = dy_abs + 1;
262 /* check direction of minor axis */
269 int d = dx_abs * 2 - dy_abs;
270 dinc1 = (dx_abs - dy_abs) * 2;