;*DDK*************************************************************************/
;
; COPYRIGHT    Copyright (C) 1995 IBM Corporation
;
;    The following IBM OS/2 WARP source code is provided to you solely for
;    the purpose of assisting you in your development of OS/2 WARP device
;    drivers. You may use this code in accordance with the IBM License
;    Agreement provided in the IBM Device Driver Source Kit for OS/2. This
;    Copyright statement may not be removed.;
;*****************************************************************************/
;-------------------------------------------------------------------------
;
;   Module          = FFLINES
;
;   Description     = 386 code for the software drawing of lines in MESS
;
;   Functions       = eddf_MESSDoBresenham, eddf_MESSDoShortLines
;
;
;-------------------------------------------------------------------------

INCL_GPIBITMAPS EQU     1
include os2.inc
include eddinclt.inc

; Include the XGA assembler include files and the MESS include files

include eddhcone.inc
include eddhtype.inc
include eddhmacr.inc

include eddfcone.inc
include eddfmacr.inc
include eddftype.inc

?DF     equ     1       ; we dont want _TEXT segment defined
include cmacros.inc



;-------------------------------------------------------------------------




_DATA           segment use32 dword public 'DATA'                       ;**
                assume  cs:FLAT, ds:FLAT, es:FLAT


; Declare the external data elements we use
ifndef _8514
externDP        ShadowXGARegs
else
include         8514.inc
externDP        Shadow8514Regs
endif
externDP        AIxfer          ;declare this because doShortLines needs it so
                                ;implementation is efficient

externDP        dstPixmap
externDP        patPixmap

externDP        messSpad


; structure for parameter block (AIxfer) used by DoShortLines

; This same structure must also appear in the eddhshrt.asm file
SHORTLINESPB    struc
ulPixelOp       dd      ?
usPatPos        dw      ?
usPatType       dw      ?
usXStart        dw      ?
usYStart        dw      ?
usYStop         dw      ?
pSteps          dd      ?
usPatEnd        dw      ?
SHORTLINESPB    ends



_DATA           ends




;-------------------------------------------------------------------------




_TEXT           segment use32 dword public 'CODE'                       ;**
                assume  cs:FLAT, ds:FLAT, es:FLAT

;-------------------------------------------------------------------------
; Function: eddf_MESSDoBresenham
;
; This function performs Bresenham line drawing operation. The lines are
; assumed to be preclipped to the destination bitmap by eddf_PMHlines.
;
; Code Paths:   (16,1), (8,1), (4,1), and (1,1) bitmaps
;               solid and patterned line types
;               directly horizontal/vertical lines and general line cases
;
;-------------------------------------------------------------------------

; macros for this function

IF1

;-------------------------------------------------------------------------
; Macro: plot_pel pels source_path
;
; This macro plots a single pel to (16,1) (8,1) (4,1) or (1,1) bitmaps.
;
; Parameters:
;         pels  should take the value 16, 8, 4, or 1 depending on the
;               destination bitmap format (bits per pel).
;  source_path  is an optional parameter. If it is not present then the macro
;               is created using a standard path for the source overwrite mix.
;               Alternatively it should be a label which points to a fastpath
;               for the source overwrite mix. This will be branched to after
;               the first pel has been read from the destination pixmap.
;
;           dh  is the source pel (dx for 16 bpp)
;          ebx  is the pel address.
;          edi  is the mix to be used (0 to 15 zero padded).
;          esi  points to the start of the destination pixmap
;
; Internally:
;           dh  is the source pel (dx for 16 bpp)
;          ebx  is converted to the address of byte in memory containing pel
;           cx  (1,1) pixmaps: contains the position of the pel within each byte
;                              accessed from memory.
;               (4,1) pixmaps: ch contains the byte accessed from memory with
;                              the old pel masked out, and cl contains the start
;                              position of the pel within that byte.
;               (8,1) pixmaps: unused.
;               (16,1)pixmaps: cx contains the destination pel to be mixed
;                              with the source colour (dx).
;          edi  is the mix to be used.
;          esi  points to the start of the destination pixmap
;
; Preserves:    dh, ebx, edi, esi, (dx in the case of 16 bit per pel).
;
; Destroys:     dl, cx (cx only in the case of (1,1) (4,1) and (16,1) pixmaps)
;               (dl only in the case of (1,1) (4,1) and (8,1) bitmaps).
;
; Registers not listed above are not used within the macro.
;
;-------------------------------------------------------------------------
plot_pel        macro   pels, source_path
        local   switch_mix, zeros, source_and_dest
        local   source_and_notdest, normal_source_path, notsource_and_dest
        local   dest, source_xor_dest, source_or_dest
        local   notsource_and_notdest, source_xor_notdest
        local   notsource, source_or_notdest, notsource_or_dest
        local   notdest, source_or_dest, notsource_or_notdest
        local   ones, done_mix

        ;get hold of destination pel even if not needed

IF      pels eq 1
        ;read from one bit per pel destination
        mov     cl, bl                  ;get low bits of pel address into cl
        push    ebx                                                     ;**
        shr     ebx, 3                  ;set bx = ebx/8. use ror so can rol back ;**
                                        ;to original value at end of macro
        mov     dl, [ebx][esi]          ;esi contains dstPixmap.startAddr ;**
        not     cl                      ;convert to motorola format
        and     cx, 00000111b           ;(cx here so can use BTR later)
        shr     dl, cl                  ;get pel into bit 0 of dl
ENDIF

IF      pels eq 4
        ;read from four bits per pel destination
        mov     cl, bl                  ;get copy of low bits of pel address
        push    ebx                                                     ;**
        shr     ebx, 1                  ;set bx = ebx/2. use ror so can rol back ;**
                                        ;to original value at end of macro
        mov     dl, [ebx][esi]          ;assumes that esi contain dstPixmap.startAddr ;**
        mov     ch, dl                  ;get copy of adjacent pel
        not     cl                      ;convert to motorola format
        and     cl, 01b
        shl     cl, 2                   ;multiply by 4
        shr     dl, cl                  ;get pel into low bits of dl
        shl     ch ,cl
        and     ch, 11110000b
        shr     ch, cl                  ;ch now contains adjacent unaltered pel
ENDIF

IF      pels eq 8
        ;read from eight bit per pel destination
        mov     dl, [ebx][esi]          ;esi contains dstPixmap.startAddr ;**
ENDIF

IF      pels eq 16
        ; read a pel from sixteen bit per pel destination
        mov     cx, [ebx*2][esi]
ENDIF

IF      pels eq 24
        ; read a pel from twenty four bit per pel destination
        mov     ecx, [ebx][esi]
ENDIF

        ;switch(mixToUse)

IFDEF FIREWALLS
        cmp     edi, 15
        jbe     short @F
        int     3       ;switch value out of range
@@:
ENDIF ; FIREWALLS

        jmp     dword ptr cs:switch_mix[edi*4]                          ;**

switch_mix:
                DD      offset FLAT:zeros
                DD      offset FLAT:source_and_dest
                DD      offset FLAT:source_and_notdest
IFNB    <source_path>                           ;if fastpath has been specified
                DD      offset FLAT:source_path ;then use it, otherwise use the
ELSE                                            ;standard path
                DD      offset FLAT:normal_source_path
ENDIF
                DD      offset FLAT:notsource_and_dest
                DD      offset FLAT:dest
                DD      offset FLAT:source_xor_dest
                DD      offset FLAT:source_or_dest
                DD      offset FLAT:notsource_and_notdest
                DD      offset FLAT:source_xor_notdest
                DD      offset FLAT:notdest
                DD      offset FLAT:source_or_notdest
                DD      offset FLAT:notsource
                DD      offset FLAT:notsource_or_dest
                DD      offset FLAT:notsource_or_notdest
                DD      offset FLAT:ones

IF      pels eq 24

; twenty four bit per pel mixing code.

zeros:
        xor     ecx, ecx
        jmp     short done_mix
source_and_notdest:
        not     ecx
source_and_dest:
        and     ecx,edx
        jmp     short done_mix
source_xor_notdest:
        not     ecx
source_xor_dest:
        xor     ecx, edx
        jmp     short done_mix
source_or_dest:
        or      ecx, edx
        jmp     short done_mix
notsource_and_dest:
        not     ecx
notsource_and_notdest:
        or      ecx, edx
        not     ecx
        jmp     short done_mix
notsource:
        mov     ecx, edx
notdest:
        not     ecx
        jmp     short done_mix
source_or_notdest:
        not     ecx
        or      ecx, edx
        jmp     short done_mix
notsource_or_dest:
        not     ecx
notsource_or_notdest:
        and     ecx, edx
        not     ecx
        jmp     short done_mix
ones:
        mov     ecx, 0ffffffffh

IFB     <source_path>                   ;if no fast path has been specified
        jmp     short done_mix          ;then use the standard path here
normal_source_path:
        mov     ecx, edx
ENDIF

; end of 16 bit per pel mixing code.
ELSE    ; other formats

IF      pels eq 16

; sixteen bit per pel mixing code.

zeros:
        xor     cx, cx
        jmp     short done_mix
source_and_notdest:
        not     cx
source_and_dest:
        and     cx, dx
        jmp     short done_mix
source_xor_notdest:
        not     cx
source_xor_dest:
        xor     cx, dx
        jmp     short done_mix
source_or_dest:
        or      cx, dx
        jmp     short done_mix
notsource_and_dest:
        not     cx
notsource_and_notdest:
        or      cx, dx
        not     cx
        jmp     short done_mix
notsource:
        mov     cx, dx
notdest:
        not     cx
        jmp     short done_mix
source_or_notdest:
        not     cx
        or      cx, dx
        jmp     short done_mix
notsource_or_dest:
        not     cx
notsource_or_notdest:
        and     cx, dx
        not     cx
        jmp     short done_mix
ones:
        ;@dms this looks like a     to me !!!
        ;mov     cx, 0ffh
        mov     cx, 0ffffh

IFB     <source_path>                   ;if no fast path has been specified
        jmp     short done_mix          ;then use the standard path here
normal_source_path:
        mov     cx, dx
ENDIF

; end of 16 bit per pel mixing code.

ELSE

; eight, four, and one bit per pel mixing code.

zeros:
        xor     dl, dl
        jmp     short done_mix
source_and_notdest:
        not     dl
source_and_dest:
        and     dl, dh
        jmp     short done_mix
source_xor_notdest:
        not     dl
source_xor_dest:
        xor     dl, dh
        jmp     short done_mix
source_or_dest:
        or      dl, dh
        jmp     short done_mix
notsource_and_dest:
        not     dl
notsource_and_notdest:
        or      dl, dh
        not     dl
        jmp     short done_mix
notsource:
        mov     dl, dh
notdest:
        not     dl
        jmp     short done_mix
source_or_notdest:
        not     dl
        or      dl, dh
        jmp     short done_mix
notsource_or_dest:
        not     dl
notsource_or_notdest:
        and     dl, dh
        not     dl
        jmp     short done_mix
ones:
        mov     dl, 0ffh

IFB     <source_path>                   ;if no fast path has been specified
        jmp     short done_mix          ;then use the standard path here
normal_source_path:
        mov     dl, dh
ENDIF

; end of eight, four, and one bit per pel mixing code.

ENDIF
ENDIF  ; 24bpp else case

done_mix:

        ;now write result to destination

IF      pels eq 1
        ;write to one bit per pel destination
        and     dl, 00000001b           ;mask off any spurious bits in dl
        shl     dl, cl                  ;cx still contains least significant 3
                                        ;bits of pel address
        btr     [ebx][esi],cx          ;clear bit in destination pix map ;**
        or      [ebx][esi],dl          ;esi point to dstPixmap.startAddr ;**
ENDIF

IF      pels eq 4
        ;write to four bits per pel destination
        and     dl, 00001111b           ;mask off any spurious bits in dl
        shl     dl, cl                  ;cl still contains least significant
                                        ;bit of pel address
        or      dl, ch                  ;ch contains adjacent unaltered pel
        mov     [ebx][esi],dl           ;esi point to dstPixmap.startAddr ;**
ENDIF

IF      pels eq 8
        ;write to eight bits per pel destination
        mov     [ebx][esi], dl          ;esi contains dstPixmap.startAddr ;**
ENDIF

IF      pels eq 16
        ;write to eight bits per pel destination
        mov     [ebx*2][esi], cx        ;esi contains dstPixmap.startAddr ;**
ENDIF

IF      pels eq 24
        ;write to 24 bits per pel destination
        ;Put the resulting pel back
        ; @DMS this code is too slow - edi and esi should be reversed and stos used
        mov byte ptr [ebx][esi],cl
        ror ecx,8
        mov byte ptr [ebx][esi+1],cl
        ror ecx,8
        mov byte ptr [ebx][esi+2],cl
ENDIF

dest:                                   ;mix is destination so do not write

IF      pels eq 1
        ;restore registers back to original values
        pop     ebx
ENDIF

IF      pels eq 4
        ;restore registers back to original values
        pop     ebx
ENDIF

endm    ;plot_pel


;-------------------------------------------------------------------------
; Macro: plot_pel_pat pels
;
; This macro plots a single pel to (8,1) (4,1) or (1,1) bitmaps using the
; correct mix according to the current pattern pel. The pattern pixmap is
; passed in bp (pixmap is always 16 bits in PM) rotated so that the current
; pel is in the top bit. The pattern pel is kept up to date by rotating bp
; after each pel has been plotted.
;
; Parameters:
;         pels  should take the value 8, 4, or 1 depending on the destination
;               bitmap format (bits per pel).
;
;          ebx  is the pel address.
;           bp  contains the pattern pixmap (see macro general description).
;          esi  points to the start of the destination pixmap
;
; Internally:
;           dh  is the source pel obtained from the current pattern pel
;          ebx  is converted to the address of byte in memory containing pel
;           cx  (1,1) pixmaps: contains the position of the pel within each byte
;                              accessed from memory.
;               (4,1) pixmaps: ch contains the byte accessed from memory with
;                              the old pel masked out, and cl contains the start
;                              position of the pel within that byte.
;               (8,1) pixmaps: unused
;               (16,1)pixmaps: cx contains the destination pel to be mixed
;                              with the source colour (dx).
;          edi  is the mix to be used obtained from the current pattern pel
;           bp  contains the pattern pixmap ready for next pel to be drawn
;          esi  points to the start of the destination pixmap
;
; Preserves:    dh, ebx, edi, esi, bp (bp is adjusted ready for next plot).
;               (dx in the case of 16 bit per pel).
;
; Destroys:     dl, cx (cx only in the case of (1,1) (4,1) and (16,1) bitmaps)
;               (dl only in the case of (1,1) (4,1) and (8,1) bitmaps).
;
; Registers not listed above are not used within the macro.
;
;-------------------------------------------------------------------------
ifndef  _8514
plot_pel_pat    macro   pels
        local   got_mix

        ;get next pattern bit ready
        rol     bp, 1
        jc      short @F

        movzx   edi, ShadowXGARegs.bg_mix            ;get background mix
IF      pels eq 16
        mov     dx, word ptr ShadowXGARegs.bg_colour ;get background colour
ELSE
        mov     dh, byte ptr ShadowXGARegs.bg_colour ;get background colour
ENDIF
        jmp     short got_mix

@@:     movzx   edi, ShadowXGARegs.fg_mix            ;get foreground mix
IF      pels eq 16
        mov     dx, word ptr ShadowXGARegs.fg_colour ;get foreground colour
ELSE
        mov     dh, byte ptr ShadowXGARegs.fg_colour ;get foreground colour
ENDIF
got_mix:
        plot_pel pels

endm    ;plot_pel_pat

else    ;_8514

plot_pel_pat    macro   pels
        local   got_mix

        ;get next pattern bit ready
        rol     bp, 1
        jc      short @F

        movzx   edi, Shadow8514Regs.Function_0      ;get background mix
        and     di, FUNC_ALU
IF      pels eq 24
        mov     edx, Shadow8514Regs.Color_0         ;get background colour
ELSE
IF      pels eq 16
        mov     dx, word ptr Shadow8514Regs.Color_0 ;get background colour
ELSE
        mov     dh, byte ptr Shadow8514Regs.Color_0 ;get background colour
ENDIF
ENDIF   ; 24bpp
        jmp     short got_mix

@@:     movzx   edi, Shadow8514Regs.Function_1      ;get foreground mix
        and     di, FUNC_ALU
IF      pels eq 24
        mov     edx, Shadow8514Regs.Color_1         ;get foreground colour
ELSE
IF      pels eq 16
        mov     dx, word ptr Shadow8514Regs.Color_1 ;get foreground colour
ELSE
        mov     dh, byte ptr Shadow8514Regs.Color_1 ;get foreground colour
ENDIF
ENDIF   ; 24bpp
got_mix:
        plot_pel pels

endm    ;plot_pel_pat

endif   ;_8514



;-------------------------------------------------------------------------
; Macro: do_bresenham_step_and_loop pels loop_label loop_register k1_register step_register
;
; This macro performs a Bresenham step and then branches to loop_label if there
; are still more pels to be drawn. loop_register and k1_register can be supplied
; to make the macro more effecient. When there are no more pels to be drawn
; the code jumps to exit_Bresenham to exit the line drawing routine.
;
; Parameters:
;         pels  should take the value 16, 8, 4, or 1 depending on the
;               destination bitmap format (bits per pel).
;   loop_label  this label points to the code where the macro will jump to
;               when it loops.
;loop_register  is an optional parameter. If supplied it should be a register
;               which contains the number of pels still to be drawn. If it is
;               not supplied then ShadowXGARegs.dim1 is used to control the loop.
;  k1_register  is an optional parameter. If supplied is should be a register
;               which contains the Bresenham constant k1. If not supplied then
;               the value is taken from ShadowXGARegs.bres_k1 in memory instead.
;               The register should be 16 bits.
;step_register  is an optional parameter. If supplied it should be a register
;               which contains the major step (ie. the value to be added to the
;               pel address each diagonal Bresenham step). It should be a 32bit
;               register.
;
;           ax  is the Bresenham error term. This is copied back to ShadowXGARegs
;               when the loop falls through before branching to exit_Bresenham.
;          ebx  is the pel address.
;
; Internally:
;           ax  is adjusted ready for next Bresenham step to be performed.
;          ebx  is adjusted ready for next pel to be plotted.
;
; Registers not listed above are not used within the macro.
;
;-------------------------------------------------------------------------
ifndef _8514
do_bresenham_step_and_loop macro pels, loop_label, loop_register, k1_register, step_register

        ;look at error term to see whether to do a major or minor step
        cmp     ax, 0                           ;(ax = bres error term)
        jge     short @F

        ;do a major step
IFB     <step_register>
        add     ebx, _messSpad.majorstep
ELSE
        add     ebx, step_register
ENDIF

IFB     <k1_register>                           ;if a bres_k1 register has been
        add     ax, ShadowXGARegs.bres_k1            ;supplied then use it otherwise
ELSE                                            ;use the value in memory
        add     ax, k1_register
ENDIF
IFB     <loop_register>                         ;if a loop count register has
        dec     ShadowXGARegs.dim1                   ;been supplied then use it
ELSE                                            ;otherwise use the memory copy
        dec     loop_register                   ;of the line length
ENDIF
        jne     loop_label
        mov     ShadowXGARegs.bres_error, ax
        jmp     exit_Bresenham

        ;do a minor step
@@:
        add     ebx, _messSpad.bothstep
        add     ax, ShadowXGARegs.bres_k2

IFB     <loop_register>                         ;if a loop count register has
        dec     ShadowXGARegs.dim1                   ;been supplied then use it
ELSE                                            ;otherwise use the memory copy
        dec     loop_register                   ;of the line length
ENDIF
        jne     loop_label
        mov     ShadowXGARegs.bres_error, ax
        jmp     exit_Bresenham

endm    ;do_bresenham_step_and_loop

else    ;_8514

do_bresenham_step_and_loop macro pels, loop_label, loop_register, k1_register, step_register

        ;look at error term to see whether to do a major or minor step
        cmp     ax, 0                           ;(ax = bres error term)
        jge     short @F

        ;do a major step
IFB     <step_register>
        add     ebx, _messSpad.majorstep
ELSE
        add     ebx, step_register
ENDIF

IFB     <k1_register>                           ;if a bres_k1 register has been
        add     ax, Shadow8514Regs.sr_K1             ;supplied then use it otherwise
ELSE                                            ;use the value in memory
        add     ax, k1_register
ENDIF
IFB     <loop_register>                         ;if a loop count register has
        dec     Shadow8514Regs.dim1                  ;been supplied then use it
ELSE                                            ;otherwise use the memory copy
        dec     loop_register                   ;of the line length
ENDIF
        jne     loop_label
        mov     Shadow8514Regs.Err_Term, ax
        jmp     exit_Bresenham

        ;do a minor step
@@:
        add     ebx, _messSpad.bothstep
        add     ax, Shadow8514Regs.sr_K2

IFB     <loop_register>                         ;if a loop count register has
        dec     Shadow8514Regs.dim1                  ;been supplied then use it
ELSE                                            ;otherwise use the memory copy
        dec     loop_register                   ;of the line length
ENDIF
        jne     loop_label
        mov     Shadow8514Regs.Err_Term, ax
        jmp     exit_Bresenham

endm    ;do_bresenham_step_and_loop

endif   ;_8514


;-------------------------------------------------------------------------
; Macro: do_hv_step_and_loop pels loop_label loop_register step_register
;
; This macro performs a horizontal or vertical step and then branches to
; loop_label if there are still more pels to be drawn. loop_register and
; step_register can be supplied to make the macro more effecient. When there
; are no more pels to be drawn the code jumps to exit_Bresenham to exit the
; line drawing routine.
;
; Parameters:
;         pels  should take the value 16, 8, 4, or 1 depending on the
;               destination bitmap format (bits per pel).
;   loop_label  this label points to the code where the macro will jump to
;               when it loops.
;loop_register  is an optional parameter. If supplied it should be a register
;               which contains the number of pels still to be drawn. If it is
;               not supplied then ShadowXGARegs.dim1 is used to control the loop.
;  k1_register  is an optional paramter. It should take the value of the
;               Bresenham constant k1. If not supplied then the value is taken
;               from ShadowXGARegs.bres_k1 in memory instead.
;step_register  is an optional parameter. If supplied it should be a register
;               which contains the horizontal or vertical step (ie. the value
;               to be added to the pel address each step). It should be a 32bit
;               register if the destination is a (1,1) or (4,1) pixmap, or a
;               16bit register if it is an (8,1) pixmap.
;
;          ebx  is the pel address.
;
; Internally:
;          ebx  is adjusted ready for next pel to be plotted.
;
; Registers not listed above are not used within the macro.
;
;-------------------------------------------------------------------------
ifndef _8514
do_hv_step_and_loop macro pels, loop_label, loop_register, step_register

        ;this line is horizontal or vertical so we always want to do
        ;a major step

        ;do a major step
IFB     <step_register>
        add     ebx, _messSpad.majorstep
ELSE
        add     ebx, step_register
ENDIF

IFB     <loop_register>                         ;if a loop count register has
        dec     ShadowXGARegs.dim1                   ;been supplied then use it
ELSE                                            ;otherwise use the memory copy
        dec     loop_register                   ;of the line length
ENDIF
        jne     loop_label
        jmp     exit_Bresenham

endm    ;do_hv_step_and_loop

else    ; _8514
do_hv_step_and_loop macro pels, loop_label, loop_register, step_register

        ;this line is horizontal or vertical so we always want to do
        ;a major step

        ;do a major step
IFB     <step_register>
        add     ebx, _messSpad.majorstep
ELSE
        add     ebx, step_register
ENDIF

IFB     <loop_register>                         ;if a loop count register has
        dec     Shadow8514Regs.dim1             ;been supplied then use it
ELSE                                            ;otherwise use the memory copy
        dec     loop_register                   ;of the line length
ENDIF
        jne     loop_label
        jmp     exit_Bresenham

endm    ;do_hv_step_and_loop
endif   ; _8514

ENDIF   ;if1



; Well thats about it for the macros folks! Now lets write the line drawing
; function with a few fastpaths here and there. Are we having fun yet?

        align   4
cProc   eddf_MESSDoBresenham, <PUBLIC>, <ebp>                           ;**

cBegin
        ;set esi to base address of destination pixmap
        mov     esi, dstPixmap.startAddr                                ;**

        ifdef   BPP24
        ; rid ourselves of the motorola/intel bit once and for all.
        mov     al,byte ptr dstPixmap.format
        and     al,BPP_MASK
        mov     byte ptr dstPixmap.format,al
        endif

        ;find relative address of start pel in terms of pels (not bytes)
        ifndef  _8514
        mov     ax, ShadowXGARegs.dest_map_y
        else
        mov     ax, Shadow8514Regs.dest_map_y
        endif
        mov     dx, dstPixmap.xLen      ;get width of destination pixmap
        inc     dx                      ;(xLen of 0 corresponds to width of 1)
        mul     dx                      ;multiply Y by pixmap width
        shl     edx, 16                 ;move result into edx
        mov     dx, ax
        ifndef  _8514
        movzx   eax, ShadowXGARegs.dest_map_x
        else
        movzx   eax, Shadow8514Regs.dest_map_x
        endif
        add     edx, eax                ;pelAddress=X+(Y*width)
        mov     ebx, edx                ;store relative address of pel

        ;calculate major step and both step as constants which can then
        ;be added directly to pelAddress
        ;(eax=majorStep, edx=bothStep)
        ;(NB. 32 bit quantities used even though not strictly needed so that
        ;can be added to pelAddress which does have to be a 32 bit quantity)
        ifndef  _8514
        mov     cl, byte ptr ShadowXGARegs.pixel_op
        else
        mov     cl, byte ptr Shadow8514Regs.pixel_op
        endif
        movzx   edx, dstPixmap.xLen     ;set bothStep to straight downwards
        inc     edx                     ;(xLen=0 corresponds to width of 1)

        test    cl, 001b                ;see if direction of line is horizontal
        je      short horizontal_major  ;or vertical major (cl=direction octant)

        ;calculate majorStep and bothStep for vertical major lines
        mov     eax, edx        ;set majorStep straight downwards
        test    cl, 010b
        je      short @F        ;jump if line direction is downwards
        neg     eax             ;negate eax,edx so that direction is upwards
        neg     edx
@@:     test    cl, 100b
        je      short @F        ;jump if line directino is towards right
        dec     edx             ;adjust bothstep towards left
ifdef   BPP24
        cmp     byte ptr dstPixmap.format, TWENTYFOUR_BPP
        jnz     short not24_1
        dec     edx             ;adjust bothstep towards left
        dec     edx             ;adjust bothstep towards left
not24_1:
endif
        jmp     short got_steps
@@:     inc     edx             ;adjust bothstep towards right
ifdef   BPP24
        cmp     byte ptr dstPixmap.format, TWENTYFOUR_BPP
        jnz     short not24_2
        inc     edx             ;adjust bothstep towards right
        inc     edx             ;adjust bothstep towards right
not24_2:
endif
        jmp     short got_steps

horizontal_major:
        ;calculate majorStep and bothStep for horizontal major lines
        test    cl, 010b
        je      short @F        ;jump if line direction is downwards
        neg     edx             ;negate dx so that bothStep is upwards
@@:     test    cl, 100b
        je      short @F        ;jump if line direction is towards the right
        mov     eax, -1         ;set majorStep straight left
        dec     edx             ;adjust bothStep towards the left
ifdef   BPP24
        cmp     byte ptr dstPixmap.format, TWENTYFOUR_BPP
        jnz     short not24_3
        dec     edx             ;adjust bothstep towards right
        dec     edx             ;adjust bothstep towards right
        mov     eax, -3         ;set majorStep straight left
not24_3:
endif
        jmp     short got_steps
@@:     mov     eax, 1          ;set majorStep straight right
        inc     edx             ;adjust bothStep towards the right
ifdef   BPP24
        cmp     byte ptr dstPixmap.format, TWENTYFOUR_BPP
        jnz     short not24_4
        inc     edx             ;adjust bothstep towards right
        inc     edx             ;adjust bothstep towards right
        mov     eax, 3          ;set majorStep straight right
not24_4:
endif

got_steps:
        mov     _messSpad.majorstep, eax  ;store to local variables
        mov     _messSpad.bothstep, edx

        ifndef  _8514
        cmp     ShadowXGARegs.bres_k1, 0     ;see if line is exactly horizontal
        else
        cmp     Shadow8514Regs.sr_K1, 0     ;see if line is exactly horizontal
        endif
        je      hor_or_vert_fast_path   ;or exactly vertical -> fastpath it!

        ifndef  _8514
        mov     ax, ShadowXGARegs.bres_error ;get Bresenham error term into ax
        else
        mov     ax, Shadow8514Regs.Err_Term ;get Bresenham error term into ax
        endif

        ;now see if omit first pel mode is set
        ifndef  _8514
        test    byte ptr ShadowXGARegs.pixel_op, 00010000b
        else
        test    byte ptr Shadow8514Regs.pixel_op, 00010000b
        endif
        je      short draw_first_pel

        ;omit first pel so advance pattern position (even if not needed)
        ifndef  _8514
        inc     byte ptr ShadowXGARegs.patt_map_x
        else
        inc     byte ptr Shadow8514Regs.patt_map_x
        endif

        ;omit first pel so do a bresenham step
        cmp     ax, 0
        jl      short @F

        ;do a minor step
        add     ebx, _messSpad.bothstep
        ifndef  _8514
        add     ax, ShadowXGARegs.bres_k2
        dec     ShadowXGARegs.dim1
        else
        add     ax, Shadow8514Regs.sr_K2
        dec     Shadow8514Regs.dim1
        endif
        js      exit_Bresenham          ;if no more pels then exit
        jmp     short draw_first_pel

        ;do a major step
@@:     add     ebx, _messSpad.majorstep
        ifndef  _8514
        add     ax, ShadowXGARegs.bres_k1
        dec     ShadowXGARegs.dim1
        else
        add     ax, Shadow8514Regs.sr_K1
        dec     Shadow8514Regs.dim1
        endif
        js      exit_Bresenham          ;if no more pels then exit

draw_first_pel:

        cmp     patPixmap.isUsed, 1     ;if pattern is enabled then jump to
        je      pattern_is_used         ;pattern specific code

        ;set up loop for solid lines

        ifndef  _8514
        movzx   edi, ShadowXGARegs.fg_mix            ;get foreground mix
        else
        mov     edi, Shadow8514Regs.Function_1       ;get foreground mix
        and     di, FUNC_ALU
        endif

        ;get the foreground color into dh (if 1, 4, or 8 bits per pel) or
        ;into dx (if 16 bits per pel) or into edx (if 24bpp)
ifdef   BPP24
        cmp     byte ptr dstPixmap.format, TWENTYFOUR_BPP
        jnz     short @F
        mov     edx, Shadow8514Regs.fg_colour ;get 24bpp fg col.
        jmp     short got_fg_col
@@:
endif
        test    byte ptr dstPixmap.format, 100b
        jz      short @F

        ifndef  _8514
        mov     dx, word ptr ShadowXGARegs.fg_colour ;get 16bpp fg col.
        jmp     short got_fg_col
@@:
        mov     dh, byte ptr ShadowXGARegs.fg_colour ;get 1/4/8bpp fg col.
        else
        mov     dx, word ptr Shadow8514Regs.Color_1 ;get 16bpp fg col.
        jmp     short got_fg_col
@@:
        mov     dh, byte ptr Shadow8514Regs.Color_1 ;get 1/4/8bpp fg col.
        endif
got_fg_col:

        ;jump to correct bits per pel specific code
        ifdef   BPP24
        cmp     byte ptr dstPixmap.format, EIGHT_BPP
        jnz     not_eight_bits_per_pel
        else
        test    byte ptr dstPixmap.format, 001b
        je      not_eight_bits_per_pel
        endif

IFDEF FIREWALLS
        test    byte ptr dstPixmap.format, 010b
        jne     short @F
        int     3               ;bitmap is not 1, 4, 8, or 16 bits per pel
@@:
        test    byte ptr dstPixmap.format, 100b
        je      short @F
        int     3               ;bitmap is not 1, 4, 8, or 16 bits per pel
@@:
ENDIF ; FIREWALLS

        ;code for 8 bit per pel destination with solid line

        ifndef  _8514
        mov     bp, ShadowXGARegs.bres_k1    ;get constant k1 into unused register
        mov     cx, ShadowXGARegs.dim1       ;number of pels still to be drawn
        else
        mov     bp, Shadow8514Regs.sr_K1    ;get constant k1 into unused register
        mov     cx, Shadow8514Regs.dim1      ;number of pels still to be drawn
        endif
        inc     cx                      ;(dim1=0 corresponds to line of 1 pel)

draw_next_pel_8bp:
        plot_pel 8 hwm_source_8bp
        do_bresenham_step_and_loop 8 draw_next_pel_8bp cx bp

        ;special case source overwrite as it is a very common operation
hwm_source_8bp:
        mov     edi, _messSpad.majorstep ;get constant into unused reg   ;**
hwm_source_8bp_loop:
        ;write to eight bit per pel destination
        mov     [ebx][esi], dh          ;esi contains dstPixmap.startAddr ;**

        do_bresenham_step_and_loop 8 hwm_source_8bp_loop cx bp edi      ;**

        ;end of code for 8 bit per pel destination and solid lines




not_eight_bits_per_pel:
        ifndef  _8514
        mov     bp, ShadowXGARegs.dim1      ;number of pels still to be drawn
        else
        mov     bp, Shadow8514Regs.dim1     ;number of pels still to be drawn
        endif
        inc     bp                     ;(dim1=0 corresponds to line of 1 pel)

        test    byte ptr dstPixmap.format, 111b
        jne     not_one_bit_per_pel

        ;code for 1 bit per pel destination with solid line

        ;see whether to call fast path directly
        cmp     di, 3
        je      hwm_source_1bp

draw_next_pel_1bp:
        plot_pel 1 fast_path_firewall
        do_bresenham_step_and_loop 1 draw_next_pel_1bp bp

fast_path_firewall:
        ;this is a null fast path that should never be called since we have
        ;should have already branched to the fast path by now
        int     3


        ;special case source overwrite since it is a very common operation
hwm_source_1bp:
hwm_source_1bp_loop:

        ;get hold of destination pel address
        mov     cl, bl                  ;get low bits of pel address into cl
        mov     edi, ebx                                                ;**
        shr     edi, 3                  ;set bx = ebx/8. use ror so can rol back ;**
                                        ;to original value at end of macro
        not     cl                      ;convert to motorola format
        and     cx, 00000111b           ;(cx here so can use BTR later)

        mov     dl, dh                  ;copy source to destination

        ;write to one bit per pel destination
        shl     dl, cl                  ;cx still contains least significant 3
                                        ;bits of pel address
        btr     [edi][esi],cx           ;clear bit in destination pix map ;**
        or      [edi][esi],dl           ;esi point to dstPixmap.startAddr ;**

        do_bresenham_step_and_loop 1 hwm_source_1bp_loop bp

        ;end of code for 1 bit per pel solid lines



not_one_bit_per_pel:
        test    byte ptr dstPixmap.format, 100b
        jnz     not_four_bits_per_pel

IFDEF FIREWALLS
        test    byte ptr dstPixmap.format, 101b
        je      short @F
        int     3            ;bit map is not 1, 4, 8, or 16 bits per pel format
@@:
ENDIF ; FIREWALLS

        ;code for 4 bit per pel destination with solid line

draw_next_pel_4bp:
        plot_pel 4
        do_bresenham_step_and_loop 4 draw_next_pel_4bp bp

        ;no fastpath has been used after considering occupancy vs performance
        ;for the four bit per pel source overwrite case here

        ;end of code for four bit per pel solid lines


not_four_bits_per_pel:
IFDEF FIREWALLS
        test    byte ptr dstPixmap.format, 011b
        je      short @F
        ; @DMS this firewall will fail at 24bpp
        int     3            ;bit map is not 1, 4, 8, or 16 bits per pel format
@@:
ENDIF ; FIREWALLS

ifdef   BPP24
        cmp    byte ptr dstPixmap.format, TWENTYFOUR_BPP
        jz     not_sixteen_bits_per_pel
endif

        ;code for 16 bit per pel destination with solid line

draw_next_pel_16bp:
        plot_pel 16 hwm_source_16bp
        do_bresenham_step_and_loop 16 draw_next_pel_16bp bp

        ;special case source overwrite as it is a very common operation
hwm_source_16bp:
        ;get constants into unused registers
        mov     edi, _messSpad.majorstep ;get constant into unused reg
        ifndef  _8514
        mov     cx, ShadowXGARegs.bres_k1
        else
        mov     cx, Shadow8514Regs.sr_K1
        endif

hwm_source_16bp_loop:
        ;write to eight bit per pel destination
        mov     [ebx*2][esi], dx        ;esi contains dstPixmap.startAddr

        do_bresenham_step_and_loop 16 hwm_source_16bp_loop bp cx edi

        ;end of code for 16 bit per pel solid lines

ifdef   BPP24
not_sixteen_bits_per_pel:
        ;code for 24 bit per pel destination with solid line

draw_next_pel_24bp:
        plot_pel 24 hwm_source_24bp
        do_bresenham_step_and_loop 24 draw_next_pel_24bp bp

        ;special case source overwrite as it is a very common operation
hwm_source_24bp:
        ;get constants into unused registers
        mov     edi, _messSpad.majorstep ;get constant into unused reg
        ifndef  _8514
        mov     cx, ShadowXGARegs.bres_k1
        else
        mov     cx, Shadow8514Regs.sr_K1
        endif

hwm_source_24bp_loop:
        ;write to 24 bit per pel destination
        ; @DMS this code is too slow - edi and esi should be reversed and stos used
        ror edx,16
        mov byte ptr [ebx][esi],dl
        rol edx,8
        mov byte ptr [ebx][esi+1],dl
        rol edx,8
        mov byte ptr [ebx][esi+2],dl

        do_bresenham_step_and_loop 24 hwm_source_24bp_loop bp cx edi

        ;end of code for 24 bit per pel solid lines
endif


pattern_is_used:
        ;get pattern pixmap into bp
        mov     edi, patPixmap.startAddr ;get pat pix map (always 16 bit) ;**
        mov     bp, [edi]               ;pat pixmap will always be in the data ;**
                                        ;segment
        rol     bp, 8                   ;convert to intel format

        ;get current pattern bit into bit 15 of bp
        ifndef  _8514
        mov     cl, byte ptr ShadowXGARegs.patt_map_x
        else
        mov     cl, byte ptr Shadow8514Regs.patt_map_x
        endif
        rol     bp, cl

        ;branch to number of bits per pel specific code
        ifdef   BPP24
        cmp     byte ptr dstPixmap.format, EIGHT_BPP
        jnz     not_eight_bits_per_pel_pat
        else
        test    byte ptr dstPixmap.format, 001b
        je      not_eight_bits_per_pel_pat
        endif

IFDEF FIREWALLS
        test    byte ptr dstPixmap.format, 010b
        jne     short @F
        int     3               ;bitmap is not 1, 4, 8, or 16 bits per pel
@@:
        test    byte ptr dstPixmap.format, 100b
        je      short @F
        int     3               ;bitmap is not 1, 4, 8, or 16 bits per pel
@@:
ENDIF ; FIREWALLS

        ;code for 8 bit per pel destination with patterned line

        ifndef  _8514
        mov     cx, ShadowXGARegs.dim1       ;number of pels still to be drawn
        else
        mov     cx, Shadow8514Regs.dim1      ;number of pels still to be drawn
        endif
        inc     cx                      ;(dim1=0 corresponds to line of 1 pel)

draw_next_pel_8bp_pat:
        ; @DMS fix macros to remove operand problem !!!
        plot_pel_pat 8
        do_bresenham_step_and_loop 8 draw_next_pel_8bp_pat cx

        ;end of code for 8 bit per pel destination and patterned lines




not_eight_bits_per_pel_pat:
        ifndef  _8514
        inc     ShadowXGARegs.dim1                   ;line length = dim1 + 1
        else
        inc     Shadow8514Regs.dim1                  ;line length = dim1 + 1
        endif

        test    byte ptr dstPixmap.format, 111b
        jne     not_one_bit_per_pel_pat

        ;code for 1 bit per pel destination with patterned line

draw_next_pel_1bp_pat:
        plot_pel_pat 1
        do_bresenham_step_and_loop 1 draw_next_pel_1bp_pat

        ;end of code for 1 bit per pel destination and patterned lines



not_one_bit_per_pel_pat:
        test    byte ptr dstPixmap.format, 100b
        jnz     not_four_bits_per_pel_pat

IFDEF FIREWALLS
        test    byte ptr dstPixmap.format, 101b
        je      short @F
        int     3            ;bit map is not 1, 4, 8, or 16 bits per pel format
@@:
ENDIF ; FIREWALLS

        ;code for 4 bit per pel destination with patterned line

draw_next_pel_4bp_pat:
        plot_pel_pat 4
        do_bresenham_step_and_loop 4 draw_next_pel_4bp_pat

        ;end of code for 4 bit per pel destination and patterned lines


not_four_bits_per_pel_pat:
IFDEF FIREWALLS
        test    byte ptr dstPixmap.format, 011b
        je      short @F
        int     3            ;bit map is not 1, 4, 8, or 16 bits per pel format
@@:
ENDIF ; FIREWALLS

ifdef   BPP24
        cmp    byte ptr dstPixmap.format, TWENTYFOUR_BPP
        jz     not_sixteen_bits_per_pel_pat
endif

        ;code for 16 bit per pel destination with patterned line

draw_next_pel_16bp_pat:
        plot_pel_pat 16
        do_bresenham_step_and_loop 16 draw_next_pel_16bp_pat

        ;end of code for 16 bit per pel destination and patterned lines

ifdef   BPP24
        ;code for 24 bit per pel destination with patterned line

not_sixteen_bits_per_pel_pat:
draw_next_pel_24bp_pat:
        plot_pel_pat 24
        do_bresenham_step_and_loop 24 draw_next_pel_24bp_pat

        ;end of code for 24 bit per pel destination and patterned lines
endif


hor_or_vert_fast_path:
        ;now see if omit first pel mode is set
ifndef  _8514
        test    byte ptr ShadowXGARegs.pixel_op, 00010000b
        je      short draw_first_pel_hv

        ;omit first pel so advance pattern position (even if not needed)
        inc     byte ptr ShadowXGARegs.patt_map_x

        ;omit first pel so do a horizontal or vertical step
        ;ie do a major step
        add     ebx, _messSpad.majorstep
        dec     ShadowXGARegs.dim1
        js      exit_Bresenham          ;if no more pels then exit

draw_first_pel_hv:

        cmp     patPixmap.isUsed, 1     ;if pattern is enabled then jump to
        je      pattern_is_used_hv      ;pattern specific code

        movzx   edi, ShadowXGARegs.fg_mix            ;get foreground mix

        test    byte ptr dstPixmap.format, 100b
        jz      short @F

        ;get the foreground color into dh (if 1, 4, or 8 bits per pel) or
        ;into dx (if 16 bits per pel)
        test    byte ptr dstPixmap.format, 100b
        jz      short @F
        mov     dx, word ptr ShadowXGARegs.fg_colour ;get 16bpp fg col.
        jmp     short got_fg_col_hv
@@:
        mov     dh, byte ptr ShadowXGARegs.fg_colour ;get 1/4/8bpp fg col.
got_fg_col_hv:

        ifdef   BPP24
        cmp     byte ptr dstPixmap.format, EIGHT_BPP
        jnz     not_eight_bits_per_pel_hv
        else
        test    byte ptr dstPixmap.format, 001b
        je      not_eight_bits_per_pel_hv
        endif

IFDEF FIREWALLS
        test    byte ptr dstPixmap.format, 010b
        jne     short @F
        int     3            ;bit map is not 1, 4, 8, or 16 bits per pel format
@@:
        test    byte ptr dstPixmap.format, 100b
        je      short @F
        int     3            ;bit map is not 1, 4, 8, or 16 bits per pel format
@@:
ENDIF ; FIREWALLS


        ;code for 8 bit per pel destination with solid line
        movzx   ecx, ShadowXGARegs.dim1      ;zero extend for fastpath optimise later

else    ;_8514

        test    byte ptr Shadow8514Regs.pixel_op, 00010000b
        je      short draw_first_pel_hv

        ;omit first pel so advance pattern position (even if not needed)
        inc     byte ptr Shadow8514Regs.patt_map_x

        ;omit first pel so do a horizontal or vertical step
        ;ie do a major step
        add     ebx, _messSpad.majorstep
        dec     Shadow8514Regs.dim1
        js      exit_Bresenham          ;if no more pels then exit

draw_first_pel_hv:

        cmp     patPixmap.isUsed, 1     ;if pattern is enabled then jump to
        je      pattern_is_used_hv      ;pattern specific code

        mov     edi, Shadow8514Regs.Function_1       ;get foreground mix
        and     di, FUNC_ALU

        ;get the foreground color into dh (if 1, 4, or 8 bits per pel) or
        ;into dx (if 16 bits per pel) or into edx (if 24bpp)
ifdef   BPP24
        cmp     byte ptr dstPixmap.format, TWENTYFOUR_BPP
        jnz     short @F
        mov     edx, Shadow8514Regs.fg_colour ;get 24bpp fg col.
        jmp     short got_fg_col_hv
@@:
endif
        test    byte ptr dstPixmap.format, 100b
        jz      short @F

        mov     dx, word ptr Shadow8514Regs.Color_1 ;get 16bpp fg col.
        jmp     short got_fg_col_hv
@@:
        mov     dh, byte ptr Shadow8514Regs.Color_1 ;get 1/4/8bpp fg col.
got_fg_col_hv:

        ifdef   BPP24
        cmp    byte ptr dstPixmap.format, EIGHT_BPP
        jnz    not_eight_bits_per_pel_hv
        else
        test    byte ptr dstPixmap.format, 001b
        je      not_eight_bits_per_pel_hv
        endif

IFDEF FIREWALLS
        test    byte ptr dstPixmap.format, 010b
        jne     short @F
        int     3            ;bit map is not 1, 4, 8, or 16 bits per pel format
@@:
        test    byte ptr dstPixmap.format, 100b
        je      short @F
        int     3            ;bit map is not 1, 4, 8, or 16 bits per pel format
@@:
ENDIF ; FIREWALLS


        ;code for 8 bit per pel destination with solid line

        movzx   ecx, Shadow8514Regs.dim1      ;zero extend for fastpath optimise later

endif   ;_8514

        inc     cx                      ;(dim1=0 corresponds to line of 1 pel)

        mov     eax, _messSpad.majorstep ;step between each pel          ;**


draw_next_pel_8bp_hv:
        plot_pel 8 source_8bp_hv
        do_hv_step_and_loop 8 draw_next_pel_8bp_hv cx eax               ;**

source_8bp_hv:
        ;special case source overwrite as it is a very common operation

        cmp     cx, 8                   ;if loop count > 8 then unroll the loop
        jl      short unroll_finished
        ror     ecx, 3                  ;store low bits of loop count

@@:
        ;do 8 times:
        ;    write to eight bit per pel destination
        ;    then do a horizontal/verical step
        mov     [ebx][esi], dh          ;esi contains dstPixmap.startAddr ;**
        add     ebx, eax                ;pelAddress is 16bits for 8bp   ;**
        mov     [ebx][esi], dh                                          ;**
        add     ebx, eax                                                ;**
        mov     [ebx][esi], dh                                          ;**
        add     ebx, eax                                                ;**
        mov     [ebx][esi], dh                                          ;**
        add     ebx, eax                                                ;**
        mov     [ebx][esi], dh                                          ;**
        add     ebx, eax                                                ;**
        mov     [ebx][esi], dh                                          ;**
        add     ebx, eax                                                ;**
        mov     [ebx][esi], dh                                          ;**
        add     ebx, eax                                                ;**
        mov     [ebx][esi], dh                                          ;**
        add     ebx, eax                                                ;**

        dec     cx                      ;loop back if enough pels still to go
        jne     @B

        rol     ecx, 3                  ;get back low bits of loop count
        cmp     cx, 0
        je      exit_Bresenham          ;if no more pels then exit

unroll_finished:
        mov     [ebx][esi], dh                                          ;**
        add     ebx, eax                                                ;**
        loop    unroll_finished

        jmp     exit_Bresenham

        ;end of code for 8 bit per pel destination and solid lines




not_eight_bits_per_pel_hv:
        ifndef  _8514
        mov     bp, ShadowXGARegs.dim1               ;line length = dim1 + 1
        else
        mov     bp, Shadow8514Regs.dim1              ;line length = dim1 + 1
        endif
        inc     bp

        mov     eax, _messSpad.majorstep ;get majorstep into unused register

        test    byte ptr dstPixmap.format, 111b
        jne     not_one_bit_per_pel_hv

        ;code for 1 bit per pel destination with solid line

        ;branch to fastpath if using source overwrite mix
        cmp     di, 3
        je      hwm_source_1bp_hv

draw_next_pel_1bp_hv:
        plot_pel 1 fast_path_firewall
        do_hv_step_and_loop 1 draw_next_pel_1bp_hv bp eax


        ;special case source overwrite since it is a very common operation

hwm_source_1bp_hv:

hwm_source_1bp_loop_hv:
        ;get hold of destination pel address
        mov     cl, bl                  ;get low bits of pel address into cl
        mov     edi, ebx                                                ;**
        shr     edi, 3                  ;set bx = ebx/8. use ror so can rol back ;**
                                        ;to original value at end of macro
        not     cl                      ;convert to motorola format
        and     cx, 00000111b           ;(cx here so can use BTR later)

        mov     dl, dh                  ;copy source to destination

        ;write to one bit per pel destination
        shl     dl, cl                  ;cx still contains least significant 3
                                        ;bits of pel address
        btr     [edi][esi],cx           ;clear bit in destination pix map ;**
        or      [edi][esi],dl           ;esi point to dstPixmap.startAddr ;**

        do_hv_step_and_loop 1 hwm_source_1bp_loop_hv bp eax


        ;end of code for 1 bit per pel destination and solid lines



not_one_bit_per_pel_hv:
        test    byte ptr dstPixmap.format, 100b
        jnz     not_four_bits_per_pel_hv

IFDEF FIREWALLS
        test    byte ptr dstPixmap.format, 101b
        je      short @F
        int     3            ;bitmap is not 1, 4, 8, or 16 bits per pel format
@@:
ENDIF ; FIREWALLS

        ;code for 4 bit per pel destination with solid line

draw_next_pel_4bp_hv:
        plot_pel 4
        do_hv_step_and_loop 4 draw_next_pel_4bp_hv bp eax

        ;end of code for 4 bit per pel destination and solid lines


not_four_bits_per_pel_hv:
IFDEF FIREWALLS
        test    byte ptr dstPixmap.format, 011b
        je      short @F
        int     3            ;bitmap is not 1, 4, 8, or 16 bits per pel format
@@:
ENDIF ; FIREWALLS

ifdef   BPP24
        cmp    byte ptr dstPixmap.format, TWENTYFOUR_BPP
        jz     not_sixteen_bits_per_pel_hv
endif

        ;code for 16 bit per pel destination with solid line

draw_next_pel_16bp_hv:
        plot_pel 16
        do_hv_step_and_loop 16 draw_next_pel_16bp_hv bp eax

        ;end of code for 16 bit per pel destination and solid lines


ifdef   BPP24
not_sixteen_bits_per_pel_hv:
        ;code for 24 bit per pel destination with solid line

draw_next_pel_24bp_hv:
        plot_pel 24
        do_hv_step_and_loop 24 draw_next_pel_24bp_hv bp eax

        ;end of code for 24 bit per pel destination and solid lines

endif


pattern_is_used_hv:

        ;get pattern pixmap into bp
        mov     edi, patPixmap.startAddr ;get pat pix map (always 16 bit) ;**
        mov     bp, [edi]               ;pat pix map will always be in the data ;**
                                        ;segment
        rol     bp, 8                   ;convert to intel format

        ;get current pattern bit into bit 15 of bp
        ifndef  _8514
        mov     cl, byte ptr ShadowXGARegs.patt_map_x
        else
        mov     cl, byte ptr Shadow8514Regs.patt_map_x
        endif
        rol     bp, cl

        ;branch to correct bits per pel specific code
        ifdef   BPP24
        cmp     byte ptr dstPixmap.format, EIGHT_BPP
        jnz     not_eight_bits_per_pel_hv_pat
        else
        test    byte ptr dstPixmap.format, 001b
        je      not_eight_bits_per_pel_hv_pat
        endif

IFDEF FIREWALLS
        test    byte ptr dstPixmap.format, 010b
        jne     short @F
        int     3            ;bit map is not 1, 4, 8, or 16 bits per pel format
@@:
        test    byte ptr dstPixmap.format, 100b
        je      short @F
        int     3            ;bit map is not 1, 4, 8, or 16 bits per pel format
@@:
ENDIF ; FIREWALLS

        ;code for 8 bit per pel destination with patterned line

        ifndef  _8514
        mov     cx, ShadowXGARegs.dim1       ;number of pels still to be drawn
        else
        mov     cx, Shadow8514Regs.dim1      ;number of pels still to be drawn
        endif
        inc     cx                      ;(dim1=0 corresponds to line of 1 pel)

        mov     eax, _messSpad.majorstep                                 ;**

draw_next_pel_8bp_hv_pat:
        plot_pel_pat 8
        do_hv_step_and_loop 8 draw_next_pel_8bp_hv_pat cx eax            ;**

        ;end of code for 8 bit per pel destination and patterned lines


not_eight_bits_per_pel_hv_pat:
        ifndef  _8514
        mov     ax, ShadowXGARegs.dim1               ;line length = dim1 + 1
        else
        mov     ax, Shadow8514Regs.dim1              ;line length = dim1 + 1
        endif
        inc     ax

        test    byte ptr dstPixmap.format, 111b
        jne     not_one_bit_per_pel_hv_pat

        ;code for 1 bit per pel destination with patterned line

draw_next_pel_1bp_hv_pat:
        plot_pel_pat 1
        do_hv_step_and_loop 1 draw_next_pel_1bp_hv_pat ax

        ;end of code for 1 bit per pel destination and patterned lines



not_one_bit_per_pel_hv_pat:
        test    byte ptr dstPixmap.format, 100b
        jnz     not_four_bits_per_pel_hv_pat

IFDEF FIREWALLS
        test    byte ptr dstPixmap.format, 101b
        je      short @F
        int     3            ;bitmap is not 1, 4, 8, or 16 bits per pel format
@@:
ENDIF ; FIREWALLS

        ;set up loop for 4 bit per pel destination with patterned line

draw_next_pel_4bp_hv_pat:
        plot_pel_pat 4
        do_hv_step_and_loop 4 draw_next_pel_4bp_hv_pat ax

        ;end of code for 4 bit per pel destination and patterned lines


not_four_bits_per_pel_hv_pat:
IFDEF FIREWALLS
        test    byte ptr dstPixmap.format, 011b
        je      short @F
        int     3            ;bit map is not 1, 4, 8, or 16 bits per pel format
@@:
ENDIF ; FIREWALLS

ifdef   BPP24
        cmp    byte ptr dstPixmap.format, TWENTYFOUR_BPP
        jz     not_sixteen_bits_per_pel_hv_pat
endif

        ;set up loop for 16 bit per pel destination with patterned line

draw_next_pel_16bp_hv_pat:
        plot_pel_pat 16
        do_hv_step_and_loop 16 draw_next_pel_16bp_hv_pat ax

        ;end of code for 16 bit per pel destination and patterned lines

ifdef BPP24
not_sixteen_bits_per_pel_hv_pat:

        ;set up loop for 24 bit per pel destination with patterned line

draw_next_pel_24bp_hv_pat:
        plot_pel_pat 24
        do_hv_step_and_loop 24 draw_next_pel_24bp_hv_pat ax

        ;end of code for 24 bit per pel destination and patterned lines
endif



exit_Bresenham:

cEnd




;-------------------------------------------------------------------------
; Function: eddf_MESSDoShortLines
;
; This function draws shortlines passed to it by eddf_PMShortlines. The
; lines are passed using AIxfer and the unaltered shortlines data structure
; for efficiency reasons. The alternative would be to have eddf_PMShortlines
; calling eddf_MESSDoPlotStep in the same way as eddh_PMShortlines drives the
; hardware. This would require calling eddf_MESS every four pels and so would
; have a very high overhead.
; The code assumes that it will be passed shortlines that do not change
; direction (ie. always go  vertical and left, or vertical and right). This
; enables more effecient clipping to be done and is especially useful when
; dealing with patterned line types. However the code is structured so that
; it can easily be modified to deal with any lines. The main changes are to
; change the clipping end point code so that it omits the current pel and not
; the rest of the line when drawing solid lines, and to change the code at the
; beginning of the patterned code section to ensure that it calculates the
; pattern position correctly after clipping.
;
; Fast path(s): (16,1) (8,1), (4,1), and (1,1) bitmaps
;               solid and patterned line types
;
; Parameters:
;
; Internally:
;        ax current x position                          (adjusted to sub pixmap)
;       eax pattern pixmap                              (bits 16 to 31)
;       ebx current pel address                         (bits  0 to 23)
;       ecx per line loop count                         (bits 16 to 31)
;       ecx per pel loop count                          (bits  0 to 15)
;        dh source pel
;        dl destination pel
;       edi current mix                                 (0 to 15 zero extended)
;       ebp current position in shortlines structure
;       esi destination pixmap start address
;
; Preserves:
;       bp, esi
;
; Destroys:
;       eax, ebx, ecx, edx, edi
;
;-------------------------------------------------------------------------

; macros for this function

IF1

;-------------------------------------------------------------------------
; Macro: shrt_plot_pel pels
;
; This macro plots a single pel to (16,1) (8,1) (4,1) or (1,1) bitmaps.
;
; Parameters:
;         pels  should take the value 16, 8, 4, or 1 depending on the
;               destination bitmap format (bits per pel).
;
;           dh  is the source pel (dx in the case of 16 bpp).
;          ebx  is the pel address.
;          edi  is the mix to be used (0 to 15 zero padded).
;          esi  points to the start of the destination pixmap
;
; Internally:
;           dh  is the source pel
;          ebx  is converted to the address of byte in memory containing pel
;           cx  (1,1) pixmaps: contains the position of the pel within each byte
;                              accessed from memory.
;               (4,1) pixmaps: ch contains the byte accessed from memory with
;                              the old pel masked out, and cl contains the start
;                              position of the pel within that byte.
;               (8,1) pixmaps: unused
;               (16,1)pixmaps: cx contains the destination pel to be mixed
;                              with the source colour (dx).
;          edi  is the mix to be used.
;          esi  points to the start of the destination pixmap
;
; Preserves:    ax, dh, ebx, ecx, edi, esi (dx in the case of (16,1) pixmaps).
;
; Destroys:     dl, top half of eax (dl not in the case of (16,1) pixmaps).
;
; Registers not listed above are not used within the macro.
;
;-------------------------------------------------------------------------
shrt_plot_pel   macro   pels

IF      pels ne 8
        ; store ecx on the stack so we can use cx internally in this macro
        push    ecx
ENDIF

        plot_pel pels


IF      pels ne 8
        ;restore ecx register back to original value
        pop     ecx
ENDIF

endm    ;shrt_plot_pel



;-------------------------------------------------------------------------
; Macro: shrt_plot_pel_pat pels
;
; This macro plots a single pel to (8,1) (4,1) or (1,1) bitmaps using the
; correct mix according to the current pattern pel. The pattern pixmap is
; passed in the top half of ebp (pixmap is always 16bits in PM) rotated so
; so that the current pel is in the top bit. The pattern pel is kept up to
; date by rotating bp after each pel has been plotted.
;
; Parameters:
;         pels  should take the value 8, 4, or 1 depending on the destination
;               bitmap format (bits per pel).
;
;          eax  top contains the pattern pixmap (see macro general description).
;          ebx  is the pel address.
;          esi  points to the start of the destination pixmap
;
; Internally:
;           dh  is the source pel obtained from the current pattern pel
;           ax  contains the pattern pixmap ready for next pel to be drawn
;          ebx  is converted to the address of byte in memory containing pel
;           cx  (1,1) pixmaps: contains the position of the pel within each byte
;                              accessed from memory.
;               (4,1) pixmaps: ch contains the byte accessed from memory with
;                              the old pel masked out, and cl contains the start
;                              position of the pel within that byte.
;               (8,1) pixmaps: unused
;               (16,1)pixmaps: cx contains the destination pel to be mixed
;                              with the source colour (dx).
;          edi  is the mix to be used obtained from the current pattern pel
;          esi  points to the start of the destination pixmap
;
; Preserves:    dh, ax, ecx, ebx, edi, esi, ebp.
;               (top half of ebp is adjusted ready for next pel to be plotted).
;               (dx in the case of (16,1) pixmaps).
;
; Destroys:     dl, top half of eax (dl not in the case of (16,1) pixmaps).
;
; Registers not listed above are not used within the macro.
;
;-------------------------------------------------------------------------
ifndef  _8514

shrt_plot_pel_pat    macro   pels
        local   got_mix

        ;get pattern pixmap from top of eax
        swap    eax                                                     ;**

        ;get next pattern bit ready
        rol     ax, 1                                                   ;**
        jc      short @F

        movzx   edi, ShadowXGARegs.bg_mix            ;get background mix
IF      pels eq 16
        mov     dx, word ptr ShadowXGARegs.bg_colour ;get background colour
ELSE
        mov     dh, byte ptr ShadowXGARegs.bg_colour ;get background colour
ENDIF
        jmp     short got_mix

@@:     movzx   edi, ShadowXGARegs.fg_mix            ;get foreground mix
IF      pels eq 16
        mov     dx, word ptr ShadowXGARegs.fg_colour ;get foreground colour
ELSE
        mov     dh, byte ptr ShadowXGARegs.fg_colour ;get foreground colour
ENDIF
got_mix:
        ;store pattern pixmap back in top of eax
        swap    eax                                                     ;**

        shrt_plot_pel pels

endm    ;shrt_plot_pel_pat

else    ;_8514

shrt_plot_pel_pat    macro   pels
        local   got_mix

        ;get pattern pixmap from top of eax
        swap    eax                                                     ;**

        ;get next pattern bit ready
        rol     ax, 1                                                   ;**
        jc      short @F

        movzx   edi, Shadow8514Regs.Function_0       ;get background mix
        and     di, FUNC_ALU
if      pels eq 24
        mov     edx, Shadow8514Regs.Color_0          ;get background colour
else
IF      pels eq 16
        mov     dx, word ptr Shadow8514Regs.Color_0  ;get background colour
ELSE
        mov     dh, byte ptr Shadow8514Regs.Color_0  ;get background colour
ENDIF
endif
        jmp     short got_mix

@@:     movzx   edi, Shadow8514Regs.Function_1       ;get foreground mix
        and     di, FUNC_ALU
if      pels eq 24
        mov     edx, Shadow8514Regs.Color_1          ;get foreground colour
else
IF      pels eq 16
        mov     dx, word ptr Shadow8514Regs.Color_1  ;get foreground colour
ELSE
        mov     dh, byte ptr Shadow8514Regs.Color_1  ;get foreground colour
ENDIF
endif
got_mix:
        ;store pattern pixmap back in top of eax
        swap    eax                                                     ;**

        shrt_plot_pel pels

endm    ;shrt_plot_pel_pat

endif   ;_8514


;This macro contains the main line drawing loop which is common to all cases
;of solid lines.

do_line_loop    macro   pels
        local   line_loop, going_right_loop, goingleft, going_left_loop
        local   vertical

line_loop:

        ;set up per pel loop
        swap    ecx             ;store line loop count
        mov     cx, [ebp+2]     ;get current X (ie end of line)         ;**
        sub     cx, [ebp]       ;sub previous X (ie start of line)      ;**
                                ;(delta .'.  no need to adjusted to subbitmap)
        ;see which direction line is heading
        je      vertical
        jl      goingleft

        ;line is going right
going_right_loop:
        cmp     ax, 0           ;check point is not clipped
        jl      exit_shortlines
        cmp     ax, dstPixmap.xLen
        jg      exit_shortlines
        shrt_plot_pel pels      ;ebx=peladdress, dh=source pel, edi=mix to use
        inc     ax              ;increase current X
        inc     ebx             ;move current pel address right one step
        dec     cx
        jne     going_right_loop

        ;last pel omit mode is always used so no plotting required
        add     ebx, _messSpad.vertstep  ;do a vertical step
        add     ebp, 2          ;move pointer on to next X coordinate   ;**
        swap    ecx             ;get back the line loop count
        dec     cx
        jne     line_loop       ;draw next line
        jmp     exit_shortlines

goingleft:
        ;line is going left
        neg     cx
going_left_loop:
        cmp     ax, 0           ;check point is not clipped
        jl      exit_shortlines
        cmp     ax, dstPixmap.xLen
        jg      exit_shortlines
        shrt_plot_pel pels      ;ebx=peladdress, dh=source pel, edi=mix to use
@@:
        dec     ax              ;decrease current X
        dec     ebx             ;move current pel address left one step
        dec     cx
        jne     going_left_loop

        ;last pel omit mode is always used so no plotting required
        add     ebx, _messSpad.vertstep  ;do a vertical step
        add     ebp, 2          ;move pointer on to next X coordinate   ;**
        swap    ecx             ;get back the line loop count
        dec     cx
        jne     line_loop       ;draw next line
        jmp     exit_shortlines

vertical:
        ;this is a vertical line of length 2 pels
        cmp     ax, 0           ;check point is not clipped
        jl      exit_shortlines
        cmp     ax, dstPixmap.xLen
        jg      exit_shortlines
        shrt_plot_pel pels      ;ebx=peladdress, dh=source pel, edi=mix to use
@@:
        ;last pel omit mode is always used so do not plot this pel
        add     ebx, _messSpad.vertstep  ;do a vertical step
        add     ebp, 2          ;move pointer on to next X coordinate   ;**
        swap    ecx             ;get back the line loop count
        dec     cx
        jne     line_loop       ;draw next line
        jmp     exit_shortlines

endm    ;do_line_loop


;This macro contains the main line drawing loop which is common to all cases
;of patterned lines.

do_line_loop_pat        macro   pels
        local   line_loop_pat, going_right_loop_pat, goingleft_pat
        local   going_left_loop_pat, vertical_pat

line_loop_pat:

        ;set up per pel loop
        swap    ecx             ;store line loop count
        mov     cx, [ebp+2]     ;get current X (ie end of line)         ;**
        sub     cx, [ebp]       ;sub previous X (ie start of line)      ;**
                                ;(delta .'.  no need to adjusted to subbitmap)
        ;see which direction line is heading
        je      vertical_pat
        jl      goingleft_pat

        ;line is going right
going_right_loop_pat:
        inc     byte ptr AIxfer.usPatEnd
        cmp     ax, 0           ;check point is not clipped
        jl      short @F
        cmp     ax, dstPixmap.xLen
        jg      short @F
        shrt_plot_pel_pat pels  ;ebx = peladdress, dh=source pel,
                                ;edi = mix to use, top of ebp = pat pixmap
@@:
        inc     ax              ;increase current X
        inc     ebx             ;move current pel address right one step
        dec     cx
        jne     going_right_loop_pat

        ;last pel omit mode is always used so no plotting required
        add     ebx, _messSpad.vertstep  ;do a vertical step
        add     ebp, 2          ;move pointer on to next X coordinate   ;**
        swap    ecx             ;get back the line loop count
        dec     cx
        jne     line_loop_pat   ;draw next line
        and     AIxfer.usPatEnd, 0fh      ;adjust pattern end to width of bitmap
        jmp     exit_shortlines

goingleft_pat:
        ;line is going left
        neg     cx
going_left_loop_pat:
        inc     byte ptr AIxfer.usPatEnd
        cmp     ax, 0           ;check point is not clipped
        jl      short @F
        cmp     ax, dstPixmap.xLen
        jg      short @F
        shrt_plot_pel_pat pels  ;ebx = peladdress, dh=source pel,
                                ;edi = mix to use, top of ebp = pat pixmap
@@:
        dec     ax              ;decrease current X
        dec     ebx             ;move current pel address left one step
        dec     cx
        jne     going_left_loop_pat

        ;last pel omit mode is always used so no plotting required
        add     ebx, _messSpad.vertstep  ;do a vertical step
        add     ebp, 2          ;move pointer on to next X coordinate   ;**
        swap    ecx             ;get back the line loop count
        dec     cx
        jne     line_loop_pat   ;draw next line
        and     AIxfer.usPatEnd, 0fh      ;adjust pattern end to width of bitmap
        jmp     exit_shortlines

vertical_pat:
        inc     byte ptr AIxfer.usPatEnd
        ;this is a vertical line of length 2 pels
        cmp     ax, 0           ;check point is not clipped
        jl      short @F
        cmp     ax, dstPixmap.xLen
        jg      short @F
        shrt_plot_pel_pat pels  ;ebx = peladdress, dh=source pel,
                                ;edi = mix to use, top of ebp = pat pixmap
@@:
        ;last pel omit mode is always used so do not plot this pel
        add     ebx, _messSpad.vertstep  ;do a vertical step
        add     ebp, 2          ;move pointer on to next X coordinate   ;**
        swap    ecx             ;get back the line loop count
        dec     cx
        jne     line_loop_pat   ;draw next line
        and     AIxfer.usPatEnd, 0fh      ;adjust pattern end to width of bitmap
        jmp     exit_shortlines

endm    ;do_line_loop_pat

ENDIF



        align   4
cProc   eddf_MESSDoShortLines, <PUBLIC>, <esi,ebp>                      ;**

cBegin
        ;set esi to base address of destination pixmap
        mov     esi, dstPixmap.startAddr                                ;**

        ;set ebp to start of point list
        mov     ebp, AIxfer.pSteps                                      ;**

        mov     ax, dstPixmap.yLen        ;get destination bitmap height
        mov     cx, AIxfer.usYStop        ;get stop y point
        movzx   edx, AIxfer.usYStart      ;get start y point            ;**

        ;clip stop y point
        cmp     cx, ax
        jle     short @F
        cmp     dx, ax                  ;check if completely clipped
        jg      exit_shortlines
        mov     cx, ax
        inc     cx
        jmp     short got_ystop
@@:     cmp     cx, 0
        jge     short got_ystop
        cmp     dx, 0
        jl      exit_shortlines         ;check if completely clipped
        mov     cx, -1
got_ystop:

        ;clip start y point
        cmp     dx, ax
        jle     short @F
        sub     dx, ax                  ;adjust bp to point to new start x
        sal     dx, 2
        add     ebp, edx                                                ;**
        mov     dx, ax                  ;adjust y start to bottom of bitmap
        jmp     short got_ystart
@@:     cmp     dx, 0
        jge     short got_ystart
        sal     dx, 2                   ;adjust bp to point to new start x
        neg     dx                                                      ;**
        add     ebp, edx                                                ;**
        xor     dx, dx
got_ystart:

        ;store copy of clipped y start and end in edi to be used later if
        ;a patterned line is to be drawn
        mov     di, cx
        swap    edi
        mov     di, dx

        movzx   eax, dstPixmap.xLen     ;get destination pixel map width
        inc     eax                     ;(xLen = 0 corresponds to width of 1)
        sub     cx, dx                  ;get number of lines to be drawn
        je      exit_shortlines         ;if completely clipped then exit
        jg      short @F                ;jump if line is going down
        neg     eax
        neg     cx
@@:
        ;set the vertical step
        mov     _messSpad.vertstep, eax

        ;find relative address of start pel in terms of pels (not bytes)
        mov     ax, dx                  ;set ax = start y (clipped)
        mov     dx, dstPixmap.xLen      ;get width of destination pixmap
        inc     dx                      ;(xLen of 0 corresponds to width of 1)
        mul     dx                      ;multiply Y by pixmap width
        shl     edx, 16                 ;move result into edx
        mov     dx, ax
        mov     ax, [ebp]               ;set eax = start x (after y clipping) ;**
        cwde                            ;eax = ax
        add     edx, eax                ;pelAddress=X+(Y*width)
        mov     ebx, edx                ;store relative address of pel

        ;now we have done vertical clipping and found the start point

        ;see if we are drawing patterned lines or solid lines
        cmp     patPixmap.isUsed, 1
        je      shrt_pat_code           ;jump to pattern specific code

        ;get foreground mix
        ifndef _8514
        movzx   edi, ShadowXGARegs.fg_mix

        ;get the foreground color into dh (if 1, 4, or 8 bits per pel) or
        ;into dx (if 16 bits per pel)
        test    byte ptr dstPixmap.format, 100b
        jz      short @F
        mov     dx, word ptr ShadowXGARegs.fg_colour ;get 16bpp fg col.
        jmp     short got_fg_col_shortlines
@@:
        mov     dh, byte ptr ShadowXGARegs.fg_colour ;get 1/4/8bpp fg col.

        else    ; _8514
        mov     edi, Shadow8514Regs.Function_1
        and     di, FUNC_ALU

        ;get the foreground color into dh (if 1, 4, or 8 bits per pel) or
        ;into dx (if 16 bits per pel) or into edx (if 24bpp)
ifdef   BPP24
        cmp     byte ptr dstPixmap.format, TWENTYFOUR_BPP
        jnz     short @F
        mov     edx, Shadow8514Regs.fg_colour ;get 24bpp fg col.
        jmp     short got_fg_col_shortlines
@@:
endif
        test    byte ptr dstPixmap.format, 100b
        jz      short @F
        mov     dx, word ptr Shadow8514Regs.Color_1 ;get 16bpp fg col.
        jmp     short got_fg_col_shortlines
@@:
        mov     dh, byte ptr Shadow8514Regs.Color_1 ;get 1/4/8bpp fg col.
        endif   ; _8514

got_fg_col_shortlines:

        ;get current x position into ax so we can do per pel horizontal
        ;clipping within the main loop
        mov     ax, [ebp]                                               ;**

        ;branch to correct bits per pel code
        ifdef   BPP24
        cmp     byte ptr dstPixmap.format, EIGHT_BPP
        jnz     shrt_not_8bp
        else
        test    byte ptr dstPixmap.format, 001b
        je      shrt_not_8bp
        endif

IFDEF FIREWALLS
        test    byte ptr dstPixmap.format, 010b
        jne     short @F
        int     3            ;bit map is not 1, 4, 8, or 16 bits per pel format
@@:
        test    byte ptr dstPixmap.format, 100b
        je      short @F
        int     3            ;bit map is not 1, 4, 8, or 16 bits per pel format
@@:
ENDIF ; FIREWALLS

        ;eight bit per pel solid lines code
        do_line_loop    8

shrt_not_8bp:
        test    byte ptr dstPixmap.format, 111b
        jne     shrt_4bp

        ;one bit per pel solid lines code
        do_line_loop    1

shrt_4bp:
        test    byte ptr dstPixmap.format, 100b
        jnz     shrt_16bp

IFDEF FIREWALLS
        test    byte ptr dstPixmap.format, 101b
        je      short @F
        int     3       ;not 1, 4, 8, or 16 bits per pel destination bitmap
@@:
ENDIF
        ;four bit per pel solid lines code
        do_line_loop    4

shrt_16bp:
ifdef   BPP24
        cmp    byte ptr dstPixmap.format, TWENTYFOUR_BPP
        jz     shrt_24bp
endif

IFDEF FIREWALLS
        test    byte ptr dstPixmap.format, 011b
        je      short @F
        int     3       ;not 1, 4, 8, or 16 bits per pel destination bitmap
@@:
ENDIF
        ;16 bit per pel solid lines code
        do_line_loop    16

shrt_24bp:
        ;24 bit per pel solid lines code
        do_line_loop    24



;initialisation code for patterned shortlines

shrt_pat_code:

        ;store line loop count in top of ecx
        swap    ecx

        ;get pattern position (not yet adjusted for clipped start point)
        ifndef  _8514
        mov     cl, byte ptr ShadowXGARegs.patt_map_x
        else
        mov     cl, byte ptr Shadow8514Regs.patt_map_x
        endif

        ;find how many lines between clipped start and original start point
        ;di contains the clipped usYStart value
        sub     di, AIxfer.usYStart
        je      short got_pat_pos ;no adjustment needed in this case fastpath
        jg      short @F
        neg     di
@@:
        ;di now contains the number of lines clipped up to start point
        mov     cx, [ebp]       ;get current x (not adjusted to sub bitmap)
        movsx   edi, di                                                 ;**
        sub     ebp, edi        ;adjust bp to point to unclipped start point ;**
        sub     ebp, edi                                                ;**
        sub     ebp, edi                                                ;**
        sub     ebp, edi                                                ;**
        sub     cx, [ebp]       ;subtract original start x
        jg      short @F
        neg     cx
@@:
        ;cx now contains the number of x steps which were clipped out.
        ;for each directly vertical step we need to add an extra 1 to cx to
        ;give the overall number of pels which have been clipped out

pat_pos_loop:
        mov     ax, [ebp+4]                                             ;**
        cmp     [ebp], ax       ;see if taking a vertical step          ;**
        jne     short @F        ;if so then increment pattern position
        inc     cl
@@:     add     ebp, 4          ;go on to next point
        dec     di
        jne     pat_pos_loop

        ;now add in original pattern position
        ifndef  _8514
        add     cl, byte ptr ShadowXGARegs.patt_map_x
        else
        add     cl, byte ptr Shadow8514Regs.patt_map_x
        endif
        and     cx, 0fh         ;adjust to the width of the pattern bitmap

got_pat_pos:

        ;now we have the pattern pixmap position for the first pel to be plotted
        ;get the pattern pixmap into a register and keep it there for speed
        ;we can just use a rotate on the register to get the next pattern bit
        ;since the pattern pixmap is always 16 bits for PM.

        ;get pattern pixmap into bp
        mov     edi, patPixmap.startAddr ;get pat pix map (always 16 bit) ;**
        mov     ax, [edi]       ;pat pix map will always be in the data segment ;**

        ;convert pattern from motorola to intel format
        rol     ax, 8                                                   ;**

        ;get current pattern bit into bit 15 of bp
        rol     ax, cl                                                  ;**

        ;set .usPatEnd to current pattern position
        mov     AIxfer.usPatEnd, cx

        ;store pattern pixmap in top of eax
        swap    eax                                                     ;**


        ;we now have the pattern bitmap set up correctly in top of ebp
        ;now we need to work out adjustment to be made to .usPatEnd for
        ;the lines which have been clipped off the end of the shortlines
        ;due to the adjustment of the y stop point to the bitmap boundary

        ;find how many lines between clipped end point and original end point
        ;top of edi contains the clipped y end value
        swap    edi
        sub     di, AIxfer.usYStop
        je      short got_end_pat_pos   ;no adjustment needed fastpath
        jg      short @F
        neg     di
@@:
        ;di now contains the number of lines clipped past adjusted end point
        mov     cx, [ebp]       ;get current x (not adjusted to sub bitmap) ;**
        movsx   edi, di                                                 ;**
        add     ebp, edi        ;adjust bp to point to unclipped end point ;**
        add     ebp, edi                                                ;**
        add     ebp, edi                                                ;**
        add     ebp, edi                                                ;**
        sub     cx, [ebp]       ;subtract original end x                ;**
        jg      short @F
        neg     cx
@@:
        ;cx now contains the number of x steps which were clipped out.
        ;for each directly vertical step we need to add an extra 1 to cx to
        ;give the overall number of pels which have been clipped out

end_pat_pos_loop:
        mov     ax, [ebp-4]                                             ;**
        cmp     [ebp], ax       ;see if taking a vertical step          ;**
        jne     short @F        ;if so then increment pattern position
        inc     cl
@@:     sub     ebp, 4           ;go on to next point                   ;**
        dec     di
        jne     end_pat_pos_loop

        ;now add the adjustment to .usPatEnd
        and     cl, 0fh         ;adjust to the width of the pattern bitmap
        add     byte ptr AIxfer.usPatEnd, cl

got_end_pat_pos:

        ;get back line loop count from top of ecx
        swap    ecx

        ;get current x position into ax so we can do per pel horizontal
        ;clipping within the main loop
        mov     ax, [ebp]                                               ;**

        ;branch to correct bits per pel code
        ifdef   BPP24
        cmp     byte ptr dstPixmap.format, EIGHT_BPP
        jnz      shrt_not_8bp_pat
        else
        test    byte ptr dstPixmap.format, 001b
        je      shrt_not_8bp_pat
        endif

IFDEF FIREWALLS
        test    byte ptr dstPixmap.format, 010b
        jne     short @F
        int     3            ;bit map is not 1, 4, 8, or 16 bits per pel format
@@:
        test    byte ptr dstPixmap.format, 100b
        je      short @F
        int     3            ;bit map is not 1, 4, 8, or 16 bits per pel format
@@:
ENDIF ; FIREWALLS

        ;eight bits per pel patterned lines code
        do_line_loop_pat 8

shrt_not_8bp_pat:
        test    byte ptr dstPixmap.format, 111b
        jne     shrt_4bp_pat

        ;one bit per pel patterned lines code
        do_line_loop_pat 1

shrt_4bp_pat:
        test    byte ptr dstPixmap.format, 100b
        jnz     shrt_16bp_pat

IFDEF FIREWALLS
        test    byte ptr dstPixmap.format, 101b
        je      short @F
        int     3       ;not 1, 4, 8, or 16 bits per pel destination bitmap
@@:
ENDIF
        ;four bit per pel patterned lines code
        do_line_loop_pat 4

shrt_16bp_pat:
ifdef   BPP24
        cmp    byte ptr dstPixmap.format, TWENTYFOUR_BPP
        jz     shrt_24bp_pat
endif

IFDEF FIREWALLS
        test    byte ptr dstPixmap.format, 011b
        je      short @F
        int     3       ;not 1, 4, 8, ro 16 bits per pel destination bitmap
@@:
ENDIF
        ;16 bit per pel patterned lines code
        do_line_loop_pat 16

shrt_24bp_pat:
        ;24 bit per pel patterned lines code
        do_line_loop_pat 24

exit_shortlines:

cEnd


_TEXT   ends



END


