--- /dev/null
+/* ; FILE IDENTIFICATION
+;
+; Name: CRT_LINE.ASM
+; Purpose: Draw lines on screen using Bresenham's integer algorithm
+; Programmer: Kevin Rosenberg
+; Date Started: 1 Jun 84
+; Last Modification: 15 Jul 85, Version 1.0
+;
+; CORRESPONDENCE
+; Kevin Rosenberg
+; 2515 E. 16th St.
+; Newport Beach, CA 92663
+; (714) 642-0119 (voice)
+; (714) 842-6348 (E-Mail on Consultant's Exchange RBBS)
+; Compuserve 73775,1232
+;
+; LANGAUGE
+; IBM macro v1.000000000
+;
+; LANGAUGE INTERFACE
+; Public routines callable from Lattice C v2.0+
+; Works with S & L memory models. Can easily add support for the
+; other models by changing the STK structure below.
+;
+; NEEDED FILES
+; egadrive.inc Definitions, macros, & procedures for driving EGA
+; hidden.inc Defines OPTIONAL public procedure, crt_hdn_line().
+; dos.mac Lattice's file containing memory model macros
+; See inclusion statement for more documentation
+;
+; GRAPHIC MODES SUPPORTED
+; - Standard CGA modes -- BIOS codes 4, 5, & 6 -- are support through
+; the ROM BIOS pixel setting routine. Things could be speeded up
+; by a factor of 7-15 by writing to the video buffer directly.
+; - You may remove support for the CGA completely by changing the
+; EQU of STD_GRF to 0, a slight speed increase in EGA operations
+; is the gain.
+; - All EGA graphic modes are supported with optimized direct pixel
+; accessing. Note: mode 13 (320x200) is bugged, see LOG date 6-20-85
+;
+; LANGUAGE INTERFACE
+; Lattice C v2.0+
+;
+; HISTORY LOG
+; 7-15-85
+; Released in PD as version 1.0
+; 6-27-85
+; Put EGA routines in INCLUDE file EGADRIVE.INC
+; Put Hidden line routines in OPTIONAL INCLUDE file HIDDEN.INC
+; 6-20-85
+; Tested with video modes 13 (320x200) & 14 (640x200). Mode 14 worked
+; ok, mode 13 was missing every other vertical line: I'm probably
+; not setting one of the myriad of registers correctly. Since I'll
+; never use mode 13, I won't investigate it further.
+; 6-05-85
+; Added & updated documentation
+; 2-28-85
+; Added hidden line routines
+; PUBLIC crt_hdn_line plus internal routines
+; (see function summary for more info)
+; 1-20-85
+; Added global variable STD_GRF
+; Will support standard graphic modes if it is set to non-zero value;
+; however, the slow ROM BIOS is used as well as a slight overhead
+; for the EG code. IT IS MUCH FASTER TO USE THE EGA ENHANCED
+; (350 line) GRAPHIC MODES.
+; 1-09-85
+; Convert to support IBM's Enhanced graphics adapter.
+; Remove all optimized code for color graphics adapter (CGA)
+; 7-16-84
+; Changed calls to ROM that set pixels to speedy routines which use
+; incremental address calculation and direct writing the to graphics
+; buffer.
+; 1-12-84
+; File creation:
+; Converted C function, bresline.c, to assembly langauge.
+; Retained C source of Bresenham's integer rastering algorithm
+; as comments.
+;
+; FUNCTION SUMMARY
+;
+; crt_line_page (page)
+; Set graphics page to plot lines on [default = 0]
+;
+; crt_line_style (style)
+; Set line style [Default = solid line]
+;
+; crt_line (x1, y1, x2, y1, color)
+; Plots a line on the screen using Bresenham's integer algorithm
+;
+; crt_hdn_line (x1, y1, x2, y1, color, col_min, col_max)
+; OPTIONAL routine to plots lines using hidden areas
+; INCLUDE file HIDDEN.INC if you wish to use this routine
+;
+; crt_init_hdn (col_min, col_max)
+; Initializes vectors for use with crt_hdn_line()
+;
+;
+; int x1, y1 - starting point
+; int x2, y2 - end point
+; int color - color to draw line, as defined by IBM bios setting
+; int linestyle - 16 bit wide dot setting pattern
+; int col_min[640] Minimum values for each X column (initialize to 349)
+; int col_max[640] Maximum values for each X column (initialize to 0)
+; (Do not display any points between the min & max,
+; and update these values for each new min & max)
+; If a vector == NULL, then do not clip against that
+; boundary.
+;
+; REFERENCES FOR BRESENHAM'S ALGORITHM
+; Newman & Sproll, "Principals of Interactive Computer Graphics",
+; page 25.
+; Foley & van Dam, "Fundementals of Interactive Computer Graphics",
+; page 433
+*/
+
+;------ Bresenham variables
+
+ deltx dw ?
+ delty dw ?
+ absdx dw ?
+ absdy dw ?
+ min_inc dw ? ; (-1, 1) indicates direction of minor axis
+ dinc1 dw ? ; d increment if (d >= 0)
+ dinc2 dw ? ; d increment if (d < 0)
+
+
+
+
+;------------------------------------------------------------------------------
+; PROCEDURE
+; crt_line [PUBLIC] Plot a line on the screen using Bresenham's alg
+;
+; SYNOPSIS
+; crt_line (x1, y1, x2, y2, color)
+
+void bresenham (int x1, int y1, int x2, int y2)
+{
+ delta_x = x2 - x1;
+ dx_abs = (delta_x >= 0 ? delta_x : -delta_x);
+
+ delta_y = y2 - y1;
+ dy_abs = (delta_y >= 0 ? delta_y : -delta_y);
+
+if (dx_abs > dy_abs)
+ bresx();
+else
+ bresy();
+}
+
+lastx= x2;
+lasty = y2;
+
+
+;------------------------------------------------------------------------------
+; MACRO NAME
+; BRES
+;
+; FUNCTION
+; Do inner most loop to draw pictures
+;
+; SYNOPSIS
+; BRES P1,P2
+; P1 Major axis & direction
+; P2 Minor axis
+;
+; EXAMPLES
+; BRES INC_COL,ROW
+;
+; INPUT
+; (DI) Address of local routine to call when setting pixel
+; (BX) Decision variable
+; (CX) Number of points to plot on major axis (loop counter)
+; [bp].min_inc Direction of minor axis increments
+; [bp].dinc1 Bresenham decision increments (see references)
+; [bp].dinc2
+; MACROS ADDR_INC_ROW, _DEC_ROW, _INC_COL, _DEC_COL
+;
+; REGISTERS USED BY PIXEL SETTING ROUTINES
+; (SI) Offset in EGA buffer
+; (AH) Bitmask
+;
+; REGISTERS AVAILABLE FOR USE
+; (AL)
+; (DX)
+;
+; CALLS
+; LS_PSET, this routine uses the addr in (DI) to set a point if
+; the linestyle allows.
+;------------------------------------------------------------------------------
+
+BRES MACRO P1,P2
+ LOCAL b0,b1
+ cmp [bp].min_inc,0 ;if (min_inc >= 0)
+ jl b0
+ _BRES P1,INC_&P2 ; inc_minor_axis
+ jmp b1 ;else
+b0: _BRES P1,DEC_&P2 ; dec_minor_axis
+b1:
+ ENDM
+
+
+_BRES MACRO P1,P2
+ LOCAL bres0,bres1,bres2
+bres0: ; do {
+ LS_PSET ; ls_pset() /* set pix using linestyle */
+
+ ADDR_&P1 ; P1 (change major axis)
+
+ cmp bx,0 ;
+ jge bres1 ; if (d < 0)
+ add bx,[bp].dinc2 ; d += dinc2;
+ jmp bres2 ; else {
+bres1: ;
+ add bx,[bp].dinc1 ; d += dinc1
+ ADDR_&P2 ; P2 (change minor axis)
+ ; }
+bres2:
+ loop bres0 ; } while (--count > 0)
+ ENDM
+
+bresx()
+{
+ /* draws a line then abs(dx) >= abs(dy) */
+
+ int npix = dx_abs + 1;
+
+ /* determine direction of minor axis */
+
+ int min_inc = 1;
+ if (delta_y < 0)
+ min_inc = -1;
+
+ /* Put decision variable in d */
+
+ int d = dy_abs * 2 - dx_abs;
+ int dinc1 = (dy_abs - dx_abs) * 2;
+ int dinc2 = 2 * dy_abs;
+
+ if (x1 <= x2)
+ bres(INC_COL, ROW);
+ else
+ breas (DEC_COL, ROW)l
+
+ }
+
+
+void bresy()
+{
+ /*; bresy [LOCAL] For plotting lines with abs(dy) > abs(sx)
+
+ NOTES
+ Logic identical to bresx's, substitution x for y and
+ vice versa. I separate the into two routines rather
+ than having the main loop spending time determining
+ which are the major & minor axis.
+ */
+
+
+ int count = dy_abs + 1;
+
+ /* check direction of minor axis */
+
+ min_inc = 1;
+ if (delta_x < 0)
+ min_inc = -1;
+
+
+ int d = dx_abs * 2 - dy_abs;
+ dinc1 = (dx_abs - dy_abs) * 2;
+ dinc2 = 2 * dx_abs;
+
+ if (y1 <= y2)
+ bres(INC_ROW,COL);
+ else
+ bres(DEL_ROW,COL);
+}
+