]> 4ch.mooo.com Git - 16.git/blobdiff - 16/xw/mxln.asm
refresh wwww
[16.git] / 16 / xw / mxln.asm
diff --git a/16/xw/mxln.asm b/16/xw/mxln.asm
new file mode 100755 (executable)
index 0000000..fbc4ab9
--- /dev/null
@@ -0,0 +1,414 @@
+;-----------------------------------------------------------\r
+;\r
+; MXLN.ASM - Line function\r
+; Copyright (c) 1993,1994 by Alessandro Scotti\r
+;\r
+;-----------------------------------------------------------\r
+WARN    PRO\r
+NOWARN  RES\r
+INCLUDE MODEX.DEF\r
+\r
+PUBLIC  mxLine\r
+\r
+MX_TEXT SEGMENT USE16 PARA PUBLIC 'CODE'\r
+        ASSUME cs:MX_TEXT, ds:NOTHING, es:NOTHING\r
+\r
+EXTRN   mx_BytesPerLine : WORD\r
+EXTRN   mx_VideoSegment : WORD\r
+\r
+EXTRN   mx_ClipX1       : WORD\r
+EXTRN   mx_ClipY1       : WORD\r
+EXTRN   mx_ClipX2       : WORD\r
+EXTRN   mx_ClipY2       : WORD\r
+\r
+tblDrawFunc     LABEL   WORD\r
+        DW      subWidthMove\r
+        DW      subHeightMove\r
+        DW      subWidthOp\r
+        DW      subHeightOp\r
+\r
+;-----------------------------------------------------------\r
+;\r
+; Draws a line from (X1,Y1) to (X2,Y2) using the Bresenham\r
+; algorithm.\r
+;\r
+; Input:\r
+;       X1, Y1  = start point\r
+;       X2, Y2  = end point\r
+;       Color   = line color\r
+;       Op      = raster operator\r
+; Output:\r
+;       none\r
+;\r
+; Note: the end point (X2,Y2) *IS* drawed. I don't like this very much\r
+; but clipping is much simpler.\r
+;\r
+mxLine  PROC FAR\r
+        ARG     Op:WORD,        \\r
+                Color:WORD,     \\r
+                Y2:WORD,        \\r
+                X2:WORD,        \\r
+                Y1:WORD,        \\r
+                X1:WORD         = ARG_SIZE\r
+        LOCAL   Width:WORD,     \\r
+                Height:WORD,    \\r
+                ErrorAdd:WORD,  \\r
+                ErrorSub:WORD,  \\r
+                DeltaX:WORD,    \\r
+                DeltaY:WORD,    \\r
+                P1:BYTE,        \\r
+                P2:BYTE,        \\r
+                WritePlane:BYTE = AUTO_SIZE\r
+        .enter  AUTO_SIZE\r
+        .push   ds, si, di\r
+        ASSUME  ds:NOTHING\r
+\r
+        mov     ax, [X1]\r
+        mov     bx, [Y1]\r
+        mov     cx, [X2]\r
+        mov     dx, [Y2]\r
+        call    subClipLine\r
+        jc      @@Exit                  ; Line is full clipped\r
+\r
+; Get width\r
+        mov     si, cx\r
+        xchg    ax, si                  ; SI = X1, AX = X2\r
+        sub     ax, si\r
+        jge     @@1\r
+; Swap points, we want X1 < X2\r
+        xchg    si, cx                  ; Swap X1 and X2\r
+        xchg    bx, dx                  ; Swap Y1 and Y2\r
+        neg     ax\r
+@@1:\r
+        mov     [Width], ax\r
+\r
+; Get height\r
+        mov     cx, [mx_BytesPerLine]   ; We don't need X2 anymore\r
+        mov     ax, dx\r
+        sub     ax, bx\r
+        jge     @@2\r
+        neg     cx                      ; Move from bottom to top\r
+        neg     ax                      ; Get absolute value of AX\r
+@@2:\r
+        mov     [Height], ax\r
+        mov     [DeltaY], cx\r
+\r
+; Get pixel address and write plane\r
+        mov     ax, bx\r
+        mul     [mx_BytesPerLine]\r
+        mov     cx, si                  ; CX = X1\r
+        shr     si, 1\r
+        shr     si, 1\r
+        add     si, ax                  ; SI = pixel offset\r
+        and     cl, 03h\r
+        mov     ax, 1102h\r
+        shl     ah, cl\r
+        mov     [WritePlane], ah\r
+        mov     dx, TS\r
+        out     dx, ax                  ; Set write plane\r
+        mov     ax, [mx_VideoSegment]\r
+        mov     ds, ax                  ; DS:SI points to (X1,Y1)\r
+\r
+; Select the function to handle the drawing loop\r
+        xor     bx, bx\r
+        mov     al, BYTE PTR [Op]\r
+        cmp     al, OP_MOVE\r
+        je      @@3\r
+        and     al, 03h\r
+        shl     al, 1\r
+        shl     al, 1\r
+        shl     al, 1\r
+        mov     ah, al\r
+        mov     al, 03h\r
+        mov     dx, GDC\r
+        out     dx, ax                  ; Set logical function\r
+        inc     bx\r
+        inc     bx\r
+@@3:\r
+        mov     ax, [Width]\r
+        mov     cx, [Height]\r
+; Horizontal, vertical and diagonal lines are not optimized yet\r
+        cmp     ax, cx\r
+        jae     @@4\r
+        inc     bx\r
+@@4:\r
+        shl     bx, 1\r
+        call    tblDrawFunc[bx]\r
+\r
+; Reset logical function if needed\r
+        cmp     BYTE PTR [Op], OP_MOVE\r
+        je      @@Exit\r
+        mov     ax, 0003h\r
+        mov     dx, GDC\r
+        out     dx, ax\r
+\r
+@@Exit:\r
+        xor     ax, ax\r
+        .pop    ds, si, di\r
+        .leave  ARG_SIZE\r
+\r
+;-----------------------------------------------------------\r
+;\r
+; Checks the coordinates of a line against the active\r
+; clip region.\r
+; Uses a variation of the Cohen-Sutherland algorithm developed\r
+; by Victor Duvanenko.\r
+;\r
+; Input:\r
+;       AX, BX  = X1, Y1\r
+;       CX, DX  = X2, Y2\r
+; Output:\r
+;       CF      = set if line is full clipped\r
+;       AX, BX  = clipped X1, Y1\r
+;       CX, DX  = clipped X2, Y2\r
+; Note:\r
+;       destroys SI, DI\r
+;\r
+subClipLine     PROC    NEAR\r
+        mov     di, ax                  ; Copy X1 to DI and free AX\r
+        mov     si, dx                  ; Copy Y2 to SI and free DX\r
+; Compute clip codes for point (X2,Y2)=(CX,SI)\r
+        xor     al, al\r
+@@P2X1: cmp     cx, [mx_ClipX1]\r
+        jge     @@P2X2\r
+        or      al, 1\r
+@@P2X2: cmp     cx, [mx_ClipX2]\r
+        jle     @@P2Y1\r
+        or      al, 2\r
+@@P2Y1: cmp     si, [mx_ClipY1]\r
+        jge     @@P2Y2\r
+        or      al, 4\r
+@@P2Y2: cmp     si, [mx_ClipY2]\r
+        jle     @@P2XY\r
+        or      al, 8\r
+@@P2XY: mov     [P2], al\r
+; Compute clip codes for point (X1,Y1)=(DI,BX)\r
+        xor     al, al\r
+@@P1X1: cmp     di, [mx_ClipX1]\r
+        jge     @@P1X2\r
+        or      al, 1\r
+@@P1X2: cmp     di, [mx_ClipX2]\r
+        jle     @@P1Y1\r
+        or      al, 2\r
+@@P1Y1: cmp     bx, [mx_ClipY1]\r
+        jge     @@P1Y2\r
+        or      al, 4\r
+@@P1Y2: cmp     bx, [mx_ClipY2]\r
+        jle     @@P1XY\r
+        or      al, 8\r
+@@P1XY: mov     [P1], al\r
+; Check codes for trivial cases\r
+        mov     ah, [P2]\r
+        test    al, ah                  ; Is line invisible?\r
+        jnz     @@FullClip              ; Yes, exit\r
+        or      ah, al                  ; Both points clipped?\r
+        jz      @@Done                  ; Yes, exit\r
+; Calculate deltas\r
+        mov     ax, cx\r
+        sub     ax, di\r
+        mov     [DeltaX], ax\r
+        mov     ax, si\r
+        sub     ax, bx\r
+        mov     [DeltaY], ax\r
+        mov     al, [P1]                ; Init clipping code\r
+; Clipping loop\r
+@@ClipLoop:\r
+        test    al, al                  ; Is first point clipped?\r
+        jnz     @@ClipX1                ; No, continue\r
+        xchg    cx, di                  ; Swap points...\r
+        xchg    bx, si\r
+        xchg    al, [P2]                ; ...and codes\r
+; Clip left: Y1 = Y1 + DeltaY*(mx_ClipX1-X1)/DeltaX\r
+@@ClipX1:\r
+        test    al, 1\r
+        jz      @@ClipX2\r
+        mov     ax, [mx_ClipX1]\r
+        sub     ax, di\r
+        mov     di, [mx_ClipX1]\r
+        jmp     @@ClipX1X2\r
+; Clip right: Y1 = Y1 + DeltaY*(mx_ClipX2-X1)/DeltaX\r
+@@ClipX2:\r
+        test    al, 2\r
+        jz      @@ClipY1\r
+        mov     ax, [mx_ClipX2]\r
+        sub     ax, di\r
+        mov     di, [mx_ClipX2]\r
+@@ClipX1X2:\r
+        imul    [DeltaY]\r
+        idiv    [DeltaX]\r
+        add     bx, ax\r
+        mov     al, 8\r
+        cmp     bx, [mx_ClipY2]\r
+        jg      @@CheckLoop\r
+        mov     al, 4\r
+        cmp     bx, [mx_ClipY1]\r
+        jl      @@CheckLoop\r
+        xor     al, al\r
+        jmp     @@CheckLoop\r
+; Clip top: X1 = X1 + DeltaX*(mx_ClipY1-Y1)/DeltaY\r
+@@ClipY1:\r
+        test    al, 4\r
+        jz      @@ClipY2\r
+        mov     ax, [mx_ClipY1]\r
+        sub     ax, bx\r
+        mov     bx, [mx_ClipY1]\r
+        jmp     @@ClipY1Y2\r
+; Clip bottom: X1 = X1 + DeltaX*(mx_ClipY2-Y1)/DeltaY\r
+@@ClipY2:\r
+        mov     ax, [mx_ClipY2]\r
+        sub     ax, bx\r
+        mov     bx, [mx_ClipY2]\r
+@@ClipY1Y2:\r
+        imul    [DeltaX]\r
+        idiv    [DeltaY]\r
+        add     di, ax\r
+        mov     al, 1\r
+        cmp     di, [mx_ClipX1]\r
+        jl      @@CheckLoop\r
+        mov     al, 2\r
+        cmp     di, [mx_ClipX2]\r
+        jg      @@CheckLoop\r
+        xor     al, al\r
+@@CheckLoop:\r
+        mov     ah, [P2]\r
+        test    al, ah\r
+        jnz     @@FullClip\r
+        or      ah, al\r
+        jnz     @@ClipLoop\r
+\r
+@@Done:\r
+        mov     ax, di\r
+        mov     dx, si\r
+        clc\r
+        ret\r
+@@FullClip:\r
+        stc\r
+        ret\r
+subClipLine     ENDP\r
+\r
+; Called when Width >= Height and Op = OP_MOVE\r
+subWidthMove    PROC NEAR\r
+        mov     di, ax\r
+        neg     di                      ; Initialize error term\r
+        shl     cx, 1\r
+        mov     [ErrorAdd], cx\r
+        mov     cx, ax\r
+        shl     ax, 1\r
+        mov     [ErrorSub], ax\r
+        mov     al, 02h\r
+        mov     ah, [WritePlane]\r
+        mov     bl, BYTE PTR [Color]\r
+        mov     dx, TS\r
+        inc     cx\r
+@@Loop:\r
+        mov     ds:[si], bl\r
+        dec     cx\r
+        jz      @@Exit\r
+        rol     ah, 1\r
+        adc     si, 0\r
+        out     dx, ax\r
+        add     di, [ErrorAdd]\r
+        jl      @@Loop\r
+        add     si, [DeltaY]\r
+        sub     di, [ErrorSub]\r
+        jmp     @@Loop\r
+@@Exit:\r
+        ret\r
+subWidthMove    ENDP\r
+\r
+; Called when Width < Height and Op = OP_MOVE\r
+subHeightMove   PROC NEAR\r
+        mov     di, cx\r
+        neg     di                      ; Initialize error term\r
+        shl     ax, 1\r
+        mov     [ErrorAdd], ax\r
+        mov     ax, cx\r
+        shl     ax, 1\r
+        mov     [ErrorSub], ax\r
+        mov     bl, BYTE PTR [Color]\r
+        mov     ah, [WritePlane]\r
+        mov     al, 02h\r
+        mov     dx, TS\r
+        inc     cx\r
+@@Loop:\r
+        mov     ds:[si], bl\r
+        dec     cx\r
+        jz      @@Exit\r
+        add     si, [DeltaY]\r
+        add     di, [ErrorAdd]\r
+        jl      @@Loop\r
+        rol     ah, 1                   ; Next write plane\r
+        adc     si, 0                   ; Bump video offset if plane overflows\r
+        out     dx, ax\r
+        sub     di, [ErrorSub]          ; Adjust error down\r
+        jmp     @@Loop\r
+@@Exit:\r
+        ret\r
+subHeightMove   ENDP\r
+\r
+; Called when Width >= Height and Op <> OP_MOVE\r
+subWidthOp      PROC NEAR\r
+        mov     di, ax\r
+        neg     di                      ; Initialize error term\r
+        shl     cx, 1\r
+        mov     [ErrorAdd], cx\r
+        mov     cx, ax\r
+        shl     ax, 1\r
+        mov     [ErrorSub], ax\r
+        mov     al, 02h\r
+        mov     ah, [WritePlane]\r
+        mov     bl, BYTE PTR [Color]\r
+        mov     dx, TS\r
+        inc     cx\r
+@@Loop:\r
+        mov     bh, ds:[si]             ; Latch data\r
+        mov     ds:[si], bl\r
+        dec     cx\r
+        jz      @@Exit\r
+        rol     ah, 1\r
+        adc     si, 0\r
+        out     dx, ax\r
+        add     di, [ErrorAdd]\r
+        jl      @@Loop\r
+        add     si, [DeltaY]\r
+        sub     di, [ErrorSub]\r
+        jmp     @@Loop\r
+@@Exit:\r
+        ret\r
+subWidthOp      ENDP\r
+\r
+; Called when Width < Height and Op <> OP_MOVE\r
+subHeightOp     PROC NEAR\r
+        mov     di, cx\r
+        neg     di                      ; Initialize error term\r
+        shl     ax, 1\r
+        mov     [ErrorAdd], ax\r
+        mov     ax, cx\r
+        shl     ax, 1\r
+        mov     [ErrorSub], ax\r
+        mov     bl, BYTE PTR [Color]\r
+        mov     ah, [WritePlane]\r
+        mov     al, 02h\r
+        mov     dx, TS\r
+        inc     cx\r
+@@Loop:\r
+        mov     bh, ds:[si]\r
+        mov     ds:[si], bl\r
+        dec     cx\r
+        jz      @@Exit\r
+        add     si, [DeltaY]\r
+        add     di, [ErrorAdd]\r
+        jl      @@Loop\r
+        rol     ah, 1                   ; Next write plane\r
+        adc     si, 0                   ; Bump video offset if plane overflows\r
+        out     dx, ax\r
+        sub     di, [ErrorSub]          ; Adjust error down\r
+        jmp     @@Loop\r
+@@Exit:\r
+        ret\r
+subHeightOp     ENDP\r
+\r
+mxLine  ENDP\r
+\r
+MX_TEXT         ENDS\r
+END\r