r104: initial cvs import
[ctsim.git] / libctgraphics / bresenham.cpp
diff --git a/libctgraphics/bresenham.cpp b/libctgraphics/bresenham.cpp
new file mode 100644 (file)
index 0000000..e9936fe
--- /dev/null
@@ -0,0 +1,278 @@
+/* ; 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);
+}
+