-/* ; 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()
+/*****************************************************************************
+** This is part of the CTSim program
+** Copyright (c) 1983-2009 Kevin Rosenberg
+**
+** This program is free software; you can redistribute it and/or modify
+** it under the terms of the GNU General Public License (version 2) as
+** published by the Free Software Foundation.
+**
+** This program is distributed in the hope that it will be useful,
+** but WITHOUT ANY WARRANTY; without even the implied warranty of
+** MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+** GNU General Public License for more details.
+**
+** You should have received a copy of the GNU General Public License
+** along with this program; if not, write to the Free Software
+** Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+******************************************************************************/
+
+// REFERENCES FOR BRESENHAM'S ALGORITHM
+// Newman & Sproll, "Principals of Interactive Computer Graphics", page 25.
+// Foley & van Dam, "Fundementals of Interactive Computer Graphics", page 433
+
+
+
+void
+bresenham (int x1, int y1, int x2, int y2)
{
- /* draws a line then abs(dx) >= abs(dy) */
+ int delta_x = x2 - x1;
+ int dx_abs = (delta_x >= 0 ? delta_x : -delta_x);
- int npix = dx_abs + 1;
+ int delta_y = y2 - y1;
+ int dy_abs = (delta_y >= 0 ? delta_y : -delta_y);
- /* determine direction of minor axis */
+ // draws a line when abs(dx) >= abs(dy)
+ if (dx_abs > dy_abs) {
+ int count = dx_abs + 1;
+ int major_inc = (x1 <= x2 ? 1 : -1);
+ int min_inc = (delta_y >= 0 ? 1 : -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 d = dy_abs * 2 - dx_abs; // Put decision variable in d
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.
- */
-
-
+ bresx (x1, y1, major_inc, d, d1, d2);
+ } else { //For plotting lines with abs(dy) > abs(sx)
int count = dy_abs + 1;
- /* check direction of minor axis */
-
- min_inc = 1;
- if (delta_x < 0)
- min_inc = -1;
-
+ int major_inc = (y1 <= y2 ? 1 : -1);
+ int min_inc = (delta_x >= 0 ? 1 : -1); // check direction of minor axis
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);
+ bresy (x1, y1, major_inc, min_inc, count, d, d1, d2);
+ }
+}
+
+
+static void
+bresx (int x, int y, int majorinc, int minorinc, int count, int d, int d1, int d2)
+{
+ do {
+ setpixel();
+ x += majorinc;
+
+ if (d < 0)
+ d += dinc2;
+ else {
+ d += dinc1;
+ y += min_inc;
+ }
+ } while (--count > 0);
+}
+
+
+static void
+bresy (int x, int y, int majorinc, int minorinc, int count, int d, int d1, int d2)
+{
+ do {
+ setpixel();
+ y += majorinc;
+
+ if (d < 0)
+ d += dinc2;
+ else {
+ d += dinc1;
+ x += min_inc;
+ }
+ } while (--count > 0);
}
+