Annotation of ntddk/src/video/displays/s3/i386/fastline.asm, revision 1.1

1.1     ! root        1: ;---------------------------Module-Header------------------------------;
        !             2: ; Module Name: fastline.asm
        !             3: ;
        !             4: ; This module draws solid lines using the line hardware of the S3.
        !             5: ; It handles entirely unclipped lines, or lines clipped to a single
        !             6: ; rectangle by using the S3's hardware clipping.
        !             7: ;
        !             8: ; All lines that have integer end-points are drawn directly using the
        !             9: ; line hardware, and any lines having fractional end-points and are
        !            10: ; less than 256 pels long are also drawn directly by the line hardware.
        !            11: ; (Fractional end-point lines require 4 more bits of precision from the
        !            12: ; DDA hardware than do integer end-point lines, and the S3 has but 13
        !            13: ; bits to use.  Lines longer than 255 pels are punted to the general
        !            14: ; purpose strip routines, which won't overflow the hardware).
        !            15: ;
        !            16: ; There are a number of ways unclipped lines can be sped up on the S3:
        !            17: ;
        !            18: ; 1) Optimize NT's GDI.  This isn't an option for everybody.
        !            19: ;
        !            20: ; 2) Use memory-mapped I/O.
        !            21: ;
        !            22: ; 3) If you can't use memory-mapped I/O, you can at least minimize
        !            23: ;    outs and ins because they are so painfully expensive.  One
        !            24: ;    way to do this is to amortize the cost of the in used for checking
        !            25: ;    the FIFO: do one in to make sure a large number of entries on
        !            26: ;    the FIFO are free (perhaps 6), then do the next 6 outs without
        !            27: ;    having to check the FIFO.
        !            28: ;
        !            29: ;    This will be a win on figures not requiring many outs (such as when
        !            30: ;    radial lines are drawn as with a rectangle), assuming the hardware
        !            31: ;    isn't always being overdriven.
        !            32: ;
        !            33: ; 4) In conjunction with 3) above, since short integer lines occur so
        !            34: ;    frequently with CAD programs, it would be beneficial to use short-
        !            35: ;    stroke vectors to do those lines, as they could reduce the number
        !            36: ;    of outs required.  Perhaps any line 10 pels or shorter could be
        !            37: ;    output by using an array lookup to determine the short stroke vectors
        !            38: ;    needed to represent that line.
        !            39: ;
        !            40: ; 5) Numerous other things I haven't thought of.
        !            41: ;
        !            42: ; Other improvements that should be done to make lines faster in general:
        !            43: ;
        !            44: ; 1) Simple clipping should be improved.  Currently, we simply set the
        !            45: ;    clip rectangle and let the hardware do everything.  We should at least
        !            46: ;    perform a trivial clip test to see if there's no chance the line
        !            47: ;    intersects the clip rectangle.
        !            48: ;
        !            49: ;    Also, for single lines it's expensive to do the 4 outs required to
        !            50: ;    set the S3's clip rectangle, draw the line, then do 4 outs to reset
        !            51: ;    the clip rectangle again.  In those cases, it would be faster to do the
        !            52: ;    clipping entirely in software.
        !            53: ;
        !            54: ; 2) This code can be enhanced to also handle styled lines, and to do
        !            55: ;    complex clipping more efficiently than the strips routines.
        !            56: ;
        !            57: ; 3) It is possible to derive the mathematical algorithm for drawing any
        !            58: ;    GIQ line in NT's 32 bit space using the limited bit precision of the
        !            59: ;    S3's hardware.  What this means is that absolutely any GIQ line can
        !            60: ;    be drawn precisely with at most two drawing commands to the line
        !            61: ;    hardware (and so the strips line drawing routine could be eliminated
        !            62: ;    entirely).  Just be careful of your math...
        !            63: ;
        !            64: ; 4) Numerous other things I haven't thought of.
        !            65: ;
        !            66: ; Copyright (c) 1992-1993 Microsoft Corporation
        !            67: ;-----------------------------------------------------------------------;
        !            68: 
        !            69:         .386
        !            70: 
        !            71:         .model  small,c
        !            72: 
        !            73:         assume cs:FLAT,ds:FLAT,es:FLAT,ss:FLAT
        !            74:         assume fs:nothing,gs:nothing
        !            75: 
        !            76:         .xlist
        !            77:         include stdcall.inc             ;calling convention cmacros
        !            78:         include i386\strucs.inc
        !            79:         include i386\lines.inc
        !            80:         .list
        !            81: 
        !            82: ; Line coordinates are given in 28.4 fixed point format:
        !            83: 
        !            84:         F               equ 16
        !            85:         FLOG2           equ 4
        !            86: 
        !            87: ; The S3's hardware can have 13 bits of significance for the error and
        !            88: ; step terms:
        !            89: 
        !            90:         NUM_DDA_BITS    equ 13
        !            91: 
        !            92: ; GIQ lines have to dedicate 4 bits to the fractional term, so the largest
        !            93: ; delta we can handle for GIQ lines is calculated as follows (scaled by F
        !            94: ; so we can do the test in GIQ coordinates), and remembering that one bit
        !            95: ; has to be used as a sign bit:
        !            96: 
        !            97:         MAX_GIQ_DELTA   equ (((1 shl (NUM_DDA_BITS - 5)) - 1) * F)
        !            98: 
        !            99: ; The following values must match those in winddi.h!
        !           100: 
        !           101:         PD_BEGINSUBPATH equ 00000001h
        !           102:         PD_ENDSUBPATH   equ 00000002h
        !           103:         PD_RESETSTYLE   equ 00000004h
        !           104:         PD_CLOSEFIGURE  equ 00000008h
        !           105:         PD_BEZIERS      equ 00000010h
        !           106: 
        !           107:         PATHDATA struc
        !           108: 
        !           109:         pd_flags        dd  ?
        !           110:         pd_count        dd  ?
        !           111:         pd_pptfx        dd  ?
        !           112: 
        !           113:         PATHDATA ends
        !           114: 
        !           115: ;-------------------------------------------------------------------------;
        !           116: ; I felt a compelling need to use 'ebp' as a 7th general register, and we
        !           117: ; have no nifty macros for dereferencing frame variables off 'esp'.  So
        !           118: ; with this structure I am rolling my own stack frame:
        !           119: 
        !           120: STATE_MEM_SIZE          equ 4           ;4 dwords
        !           121: PROC_MEM_SIZE           equ 7           ;7 dwords
        !           122: 
        !           123: STACK_FRAME struc
        !           124: 
        !           125: ; State variables (don't add/delete fields without modifying STATE_MEM_SIZE!)
        !           126: 
        !           127: sf_ulOurEbp             dd ?            ;useful for debugging
        !           128: sf_ulOriginalEbx        dd ?
        !           129: sf_ulOriginalEdi        dd ?
        !           130: sf_ulOriginalEsi        dd ?
        !           131: 
        !           132: ; Frame variables (feel free to add/delete fields):
        !           133: 
        !           134: sf_y0                   dd ?            ;GIQ variables
        !           135: sf_y1                   dd ?
        !           136: sf_x1                   dd ?
        !           137: sf_ptlOrg               db (size POINTL) dup (?)
        !           138:                                         ;our  origin for normalizing the line
        !           139: sf_ptfxLast             db (size POINTL) dup (?)
        !           140:                                         ;the most recent point
        !           141: sf_ptfxStartFigure      db (size POINTL) dup (?)
        !           142:                                         ;the figure's 1st point
        !           143: sf_bMore                dd ?            ;more path records to get?
        !           144: sf_pptfxEnd             dd ?            ;points to last point in record
        !           145: sf_pptfx                dd ?            ;points to current point
        !           146: sf_pd                   db (size PATHDATA) dup (?)
        !           147:                                         ;pathdata structure
        !           148: sf_ptfxStart            db (size POINTL) dup (?)
        !           149:                                         ;temporary spot for saving start point
        !           150: sf_ptfxEnd              db (size POINTL) dup (?)
        !           151:                                         ;temporary spot for saving end point
        !           152: sf_ulCmd                dd ?            ;S3 draw command
        !           153: sf_cPels                dd ?            ;length of line in pels
        !           154: sf_bSetCP               dd ?            ;1 if first line in figure, 0 otherwise
        !           155: sf_ulLastLength         dd ?            ;last value set as LINE_MAX
        !           156: sf_ulErrorTerm          dd ?            ;error term for line
        !           157: 
        !           158: ; Procedure variables (don't add/delete fields without modifying
        !           159: ; PROC_MEM_SIZE!)
        !           160: 
        !           161: sf_ulOriginalEbp        dd ?
        !           162: sf_ulOriginalReturn     dd ?
        !           163: sf_ppdev                dd ?
        !           164: sf_ppo                  dd ?
        !           165: sf_prclClip             dd ?
        !           166: sf_apfn                 dd ?
        !           167: sf_flags                dd ?
        !           168: 
        !           169: STACK_FRAME ends
        !           170: 
        !           171:         .data
        !           172: 
        !           173:         EXTRNP  PATHOBJ_bEnum,8
        !           174:         EXTRNP  bLines,36
        !           175: 
        !           176:         .code
        !           177: 
        !           178:         ROUND_X_DOWN            equ     01h
        !           179:         ROUND_Y_DOWN            equ     02h
        !           180:         ROUND_SLOPE_ONE         equ     04h
        !           181:         ROUND_X_AND_Y_DOWN      equ     (ROUND_X_DOWN + ROUND_Y_DOWN)
        !           182:         ROUND_X_DOWN_SLOPE_ONE  equ     (ROUND_X_DOWN + ROUND_SLOPE_ONE)
        !           183:         ROUND_Y_DOWN_SLOPE_ONE  equ     (ROUND_Y_DOWN + ROUND_SLOPE_ONE)
        !           184: 
        !           185: ;--------------------------------Macro----------------------------------;
        !           186: ; GIQ flags
        !           187: ;
        !           188: ; This macros computes the start pixel, the number of pixels to
        !           189: ; be lit, and the initial error term given a GIQ line.  The line must
        !           190: ; have already been normalized such that dM >= dN, dN >= 0.
        !           191: ;
        !           192: ; Input:   ebx - M0
        !           193: ;          ecx - N0
        !           194: ;          esi - dM
        !           195: ;          edi - dN
        !           196: ; Trashes:
        !           197: ;          eax, edx
        !           198: ;          [esp].sf_ptlOrg.ptl_x, [esp].sf_ptlOrg.ptl_y
        !           199: ; Output:
        !           200: ;          [esp].sf_x1  - x-coordinate of last pixel (exclusive)
        !           201: ;          ebx - x-coordinate of first pixel
        !           202: ;          ecx - error term
        !           203: ;          esi - dM
        !           204: ;          edi - dN
        !           205: ;          ebp - y-coordinate of first pixel
        !           206: ;-----------------------------------------------------------------------;
        !           207: 
        !           208: GIQ     macro   flags
        !           209:         local   compute_x1, compute_error_term
        !           210: 
        !           211: ; We normalize our coordinate system so that if the start point is
        !           212: ; (M0/F, N0/F), the origin is at (floor(M0/F), (N0/F)):
        !           213: 
        !           214:         mov     eax,ebx
        !           215:         mov     ebp,ecx
        !           216:         sar     eax,FLOG2
        !           217:         sar     ebp,FLOG2
        !           218:         mov     [esp].sf_ptlOrg.ptl_x,eax
        !           219:                                         ;ptlOrg.x = floor(M0 / F)
        !           220:         mov     [esp].sf_ptlOrg.ptl_y,ebp
        !           221:                                         ;ptlOrg.y = floor(N0 / F)
        !           222: 
        !           223: ; Calculate the correct [esp].sf_x1:
        !           224: 
        !           225:         lea     ebp,[ecx + edi]         ;ebp = N1
        !           226:         and     ebp,F - 1
        !           227: 
        !           228:     if (flags AND ROUND_X_DOWN)
        !           229: 
        !           230:     if (flags AND ROUND_SLOPE_ONE)
        !           231:         lea     edx,[ebx + esi]
        !           232:         and     edx,F - 1               ;edx = M1
        !           233:         sub     edx,8
        !           234:         cmp     edx,ebp                 ;cmp M1 - 8, N1
        !           235:         jne     short compute_x1
        !           236: 
        !           237:         lea     edx,[ebx + esi]
        !           238:         sar     edx,FLOG2
        !           239:         jmp     short compute_error_term
        !           240:     endif
        !           241: 
        !           242: compute_x1:
        !           243: 
        !           244:         cmp     ebp,1
        !           245:         sbb     ebp,8                   ;N1 -= 8
        !           246:     else
        !           247:         sub     ebp,8                   ;N1 -= 8
        !           248:     endif
        !           249:         sbb     eax,eax
        !           250:         xor     ebp,eax
        !           251:         sub     ebp,eax                 ;N1 = ABS(N1)
        !           252: 
        !           253:         lea     edx,[ebx + esi]
        !           254:         mov     eax,edx
        !           255:         sar     edx,FLOG2
        !           256:         and     eax,F - 1
        !           257:         jz      short @f                ;special case for M1 == 0
        !           258:         cmp     eax,ebp                 ;cmp M1, N1
        !           259:         sbb     edx,-1                  ;edx is now one pixel past the actual
        !           260: @@:                                     ; end coordinate (note that it hasn't
        !           261:                                         ; been affected by the origin shift)
        !           262: 
        !           263: compute_error_term:
        !           264: 
        !           265: ; ebx = M0
        !           266: ; ecx = N0
        !           267: ; edx = x1
        !           268: ; esi = dM
        !           269: ; edi = dN
        !           270: 
        !           271:         and     ecx,F - 1
        !           272:         mov     [esp].sf_x1,edx         ;save x1
        !           273: 
        !           274: ; Calculate our error term for x = 0.
        !           275: ;
        !           276: ; NOTE: Since this routine is used only for lines that are unclipped, we
        !           277: ;       are guaranteed by our screen size that the values will be far less
        !           278: ;       than 32 bits in significance, and so we don't worry about overflow.
        !           279: ;       If this is used for clipped lines, these multiplies will have to
        !           280: ;       be converted to give 64 bit results, because we can have 36 bits of
        !           281: ;       significance!
        !           282: 
        !           283: 
        !           284:         lea     ebp,[ecx + 8]           ;ebp = N0 + 8
        !           285:         mov     eax,esi
        !           286:         imul    eax,ebp                 ;eax = dM * (N0 + 8)
        !           287:         mov     ebp,edi
        !           288: 
        !           289: ; We have to special case when M0 is 0 -- we know x0 will be zero.
        !           290: ; So we jump ahead a bit to a place where 'ebx' is assumed to contain
        !           291: ; x0 -- and it just so happens 'ebx' is zero in this case:
        !           292: 
        !           293:         and     ebx,F - 1
        !           294:         jz      short @f
        !           295:         imul    ebp,ebx                 ;ebp = dN * M0
        !           296:         sub     eax,ebp
        !           297: 
        !           298: ; Calculate the x-coordinate of the first pixel:
        !           299: 
        !           300:     if (flags AND ROUND_X_DOWN)
        !           301: 
        !           302:     if (flags AND ROUND_SLOPE_ONE)
        !           303:         cmp     ecx,8
        !           304:         sbb     ecx,-1
        !           305:     endif
        !           306: 
        !           307:         cmp     ecx,1
        !           308:         sbb     ecx,8                   ;N0 -= 8
        !           309:     else
        !           310:         sub     ecx,8                   ;N0 -= 8
        !           311:     endif
        !           312:         sbb     ebp,ebp
        !           313:         xor     ecx,ebp
        !           314:         sub     ecx,ebp                 ;N0 = ABS(N0)
        !           315:         cmp     ebx,ecx
        !           316:         sbb     ebx,ebx
        !           317:         not     ebx                     ;ebx = -x0
        !           318: 
        !           319: ; Now adjust the error term accordingly:
        !           320: 
        !           321: @@:
        !           322:     if (flags AND ROUND_Y_DOWN)
        !           323:         dec     eax
        !           324:     endif
        !           325:         sar     eax,FLOG2               ;eax = floor((N0 + 8) dM - M0 dN] / 16)
        !           326: 
        !           327:         mov     ecx,[esp].sf_ptlOrg.ptl_x
        !           328:         mov     ebp,[esp].sf_ptlOrg.ptl_y
        !           329: 
        !           330:         sub     ecx,ebx                 ;ecx = ptlOrg.ptl_x + x0
        !           331: 
        !           332:         and     ebx,edi
        !           333:         add     ebx,eax
        !           334:         sub     ebx,esi                 ;ebx = dN * x0 + initial error - dM
        !           335:         jl      short @f                ;if the error term >= 0, we have to
        !           336:         sub     ebx,esi                 ; add 1 to the y position and subtract
        !           337:         inc     ebp                     ; dM off again
        !           338: @@:
        !           339:         xchg    ebx,ecx
        !           340: 
        !           341: endm
        !           342: 
        !           343: ;--------------------------------Macro----------------------------------;
        !           344: ; GIQR flags
        !           345: ;
        !           346: ; Same as above, except it handles flips about the line x = y.
        !           347: ;
        !           348: ; Input:   ebx - M0
        !           349: ;          ecx - N0
        !           350: ;          esi - dM
        !           351: ;          edi - dN
        !           352: ; Trashes:
        !           353: ;          eax, edx
        !           354: ;          [esp].sf_ptlOrg.ptl_x, [esp].sf_ptlOrg.ptl_y
        !           355: ; Output:
        !           356: ;          [esp].sf_y1  - y-coordinate of last pixel (exclusive)
        !           357: ;          ebx - x-coordinate of first pixel
        !           358: ;          ecx - error term
        !           359: ;          esi - dM
        !           360: ;          edi - dN
        !           361: ;          ebp - y-coordinate of first pixel
        !           362: ;-----------------------------------------------------------------------;
        !           363: 
        !           364: GIQR    macro   flags
        !           365: 
        !           366: ; We normalize our coordinate system so that if the start point is
        !           367: ; (M0/F, N0/F), the origin is at (floor(M0/F), (N0/F)):
        !           368: 
        !           369:         mov     eax,ebx
        !           370:         mov     ebp,ecx
        !           371:         sar     eax,FLOG2
        !           372:         sar     ebp,FLOG2
        !           373:         mov     [esp].sf_ptlOrg.ptl_x,eax
        !           374:                                         ;ptlOrg.x = floor(M0 / F)
        !           375:         mov     [esp].sf_ptlOrg.ptl_y,ebp
        !           376:                                         ;ptlOrg.y = floor(N0 / F)
        !           377: 
        !           378: ; Calculate the correct [esp].sf_y1:
        !           379: 
        !           380:         lea     ebp,[ebx + esi]         ;ebp = M1
        !           381:         and     ebp,F - 1
        !           382: 
        !           383:     if (flags AND ROUND_Y_DOWN)
        !           384:         cmp     ebp,1
        !           385:         sbb     ebp,8                   ;M1 -= 8
        !           386:     else
        !           387:         sub     ebp,8                   ;M1 -= 8
        !           388:     endif
        !           389:         sbb     eax,eax
        !           390:         xor     ebp,eax
        !           391:         sub     ebp,eax                 ;M1 = ABS(M1)
        !           392: 
        !           393:         lea     edx,[ecx + edi]
        !           394:         mov     eax,edx
        !           395:         sar     edx,FLOG2
        !           396:         and     eax,F - 1
        !           397:         jz      short @f                ;special case for N1 == 0
        !           398:         cmp     eax,ebp                 ;cmp N1, M1
        !           399:         sbb     edx,-1                  ;edx is now one pixel past the actual
        !           400: @@:                                     ; end coordinate (note that it hasn't
        !           401:                                         ; been affected by the origin shift)
        !           402:         and     ebx,F - 1
        !           403:         mov     [esp].sf_y1,edx
        !           404: 
        !           405: ; Calculate our error term for y = 0.
        !           406: ;
        !           407: ; NOTE: Since this routine is used only for lines that are unclipped, we
        !           408: ;       are guaranteed by our screen size that the values will be far less
        !           409: ;       than 32 bits in significance, and so we don't worry about overflow.
        !           410: ;       If this is used for clipped lines, these multiplies will have to
        !           411: ;       be converted to give 64 bit results, because we can have 36 bits of
        !           412: ;       significance!
        !           413: 
        !           414:         lea     ebp,[ebx + 8]           ;ebp = M0 + 8
        !           415:         mov     eax,edi
        !           416:         imul    eax,ebp                 ;eax = dN * (M0 + 8)
        !           417:         mov     ebp,esi
        !           418: 
        !           419: ; We have to special case when N0 is 0 -- we know y0 will be zero.
        !           420: ; So we jump ahead a bit to a place where 'ecx' is assumed to contain
        !           421: ; y0 -- and it just so happens 'ecx' is zero in this case:
        !           422: 
        !           423:         and     ecx,F - 1
        !           424:         jz      short @f
        !           425:         imul    ebp,ecx                 ;ebp = dM * N0
        !           426:         sub     eax,ebp
        !           427: 
        !           428: ; Calculate the x-coordinate of the first pixel:
        !           429: 
        !           430:     if (flags AND ROUND_Y_DOWN)
        !           431:         cmp     ebx,1
        !           432:         sbb     ebx,8                   ;M0 -= 8
        !           433:     else
        !           434:         sub     ebx,8                   ;M0 -= 8
        !           435:     endif
        !           436:         sbb     ebp,ebp
        !           437:         xor     ebx,ebp
        !           438:         sub     ebx,ebp                 ;M0 = ABS(M0)
        !           439:         cmp     ecx,ebx
        !           440:         sbb     ecx,ecx
        !           441:         not     ecx                     ;ecx = -y0
        !           442: 
        !           443: ; Now adjust the error term accordingly:
        !           444: 
        !           445: @@:
        !           446:     if (flags AND ROUND_X_DOWN)
        !           447:         dec     eax
        !           448:     endif
        !           449:         sar     eax,FLOG2               ;eax = floor((M0 + 8) dN - N0 dM] / 16)
        !           450: 
        !           451:         mov     ebx,[esp].sf_ptlOrg.ptl_x
        !           452:         mov     ebp,[esp].sf_ptlOrg.ptl_y
        !           453: 
        !           454:         sub     ebp,ecx                 ;ebp = ptlOrg.ptl_y + y0
        !           455: 
        !           456:         and     ecx,esi
        !           457:         add     ecx,eax
        !           458:         sub     ecx,edi                 ;ecx = dM * x0 + initial error - dN
        !           459:         jl      short @f                ;if the error term >= 0, we have to
        !           460:         sub     ecx,edi                 ; add 1 to the x position and subtract
        !           461:         inc     ebx                     ; dN off again
        !           462: @@:
        !           463: 
        !           464: endm
        !           465: 
        !           466: ;---------------------------Public-Routine------------------------------;
        !           467: ; vFastLine(ppdev, ppo, prclClip, apfn, flags)
        !           468: ;
        !           469: ; Draws fast lines.  Or at least attempts to.
        !           470: ;
        !           471: ; Input:
        !           472: ;
        !           473: ;    ppdev     - PDEV pointer
        !           474: ;    ppo       - path
        !           475: ;    prclClip  - pointer to rectangle array for passing to 'bLines'
        !           476: ;    apfn      - pointer to strip routines for passing to 'bLines'
        !           477: ;    flags     - status flag for passing to 'bLines'
        !           478: ;
        !           479: ;-----------------------------------------------------------------------;
        !           480: 
        !           481: ; NOTE: Don't go changing parameters without also changing STACK_FRAME!
        !           482: 
        !           483: cProc vFastLine,20,<     \
        !           484:     uses esi edi ebx,    \
        !           485:     ebp_ppdev:     ptr,  \
        !           486:     ebp_ppo:       ptr,  \
        !           487:     ebp_prclClip:  ptr,  \
        !           488:     ebp_apfn:      ptr,  \
        !           489:     ebp_flags:     dword >
        !           490: 
        !           491: ; Leave room for our stack frame.
        !           492: ;
        !           493: ; NOTE: Don't add local variables here -- you can't reference them with
        !           494: ;       ebp anyway!  Add them to the STACK_FRAME structure.
        !           495: 
        !           496:     local aj[(size STACK_FRAME) - 4 * (STATE_MEM_SIZE + PROC_MEM_SIZE)]: byte
        !           497: 
        !           498: ; We save 'ebp' on the stack (note that STACK_FRAME accounts for this push):
        !           499: 
        !           500:         push    ebp
        !           501: 
        !           502:         mov     [esp].sf_ulLastLength,-1;make sure first line in path resets
        !           503:                                         ; LINE_MAX value
        !           504: 
        !           505: ; Now get some path stuff:
        !           506: 
        !           507: next_record:
        !           508: 
        !           509:         mov     eax,[esp].sf_ppo
        !           510:         lea     ebx,[esp].sf_pd
        !           511:         cCall   PATHOBJ_bEnum,<eax,ebx>
        !           512:         mov     [esp].sf_bMore,eax      ;save away return code for later
        !           513: 
        !           514:         mov     ebx,[esp].sf_pd.pd_count;if 0 points in record, get outta here
        !           515:         or      ebx,ebx
        !           516:         jz      check_for_closefigure
        !           517: 
        !           518:         lea     ebp,[8 * ebx - 8]
        !           519:         add     ebp,[esp].sf_pd.pd_pptfx
        !           520:         mov     [esp].sf_pptfxEnd,ebp   ;points to last point in record
        !           521: 
        !           522:         mov     ecx,[esp].sf_pd.pd_flags
        !           523:         test    ecx,PD_BEGINSUBPATH
        !           524:         jz      short continue_subpath
        !           525: 
        !           526: ; Handle a new sub-path:
        !           527: 
        !           528:         mov     eax,[esp].sf_pd.pd_pptfx
        !           529:         add     eax,8
        !           530:         mov     [esp].sf_pptfx,eax
        !           531: 
        !           532:         mov     esi,[ebp].ptl_x         ;remember last point in case we have
        !           533:         mov     edi,[ebp].ptl_y         ; to continue to another record
        !           534:         mov     [esp].sf_ptfxLast.ptl_x,esi
        !           535:         mov     [esp].sf_ptfxLast.ptl_y,edi
        !           536: 
        !           537:         mov     ebx,[eax - 8].ptl_x     ;load up current start and end point
        !           538:         mov     ecx,[eax - 8].ptl_y
        !           539:         mov     esi,[eax].ptl_x
        !           540:         mov     edi,[eax].ptl_y
        !           541:         mov     [esp].sf_ptfxStartFigure.ptl_x,ebx
        !           542:         mov     [esp].sf_ptfxStartFigure.ptl_y,ecx
        !           543: 
        !           544:         mov     [esp].sf_bSetCP,1       ;this line is first in figure
        !           545: 
        !           546:         cmp     eax,[esp].sf_pptfxEnd   ;we have to be careful when the only
        !           547:                                         ; point in the record is the start-
        !           548:                                         ; figure point (pretty rare)
        !           549:         jbe     new_line
        !           550:         jmp     short next_record
        !           551: 
        !           552: continue_subpath:
        !           553: 
        !           554: ; This record continues the path:
        !           555: 
        !           556:         mov     eax,[esp].sf_pd.pd_pptfx
        !           557:         mov     ebx,[esp].sf_ptfxLast.ptl_x ;load up current start point
        !           558:         mov     ecx,[esp].sf_ptfxLast.ptl_y
        !           559: 
        !           560:         mov     esi,[ebp].ptl_x         ;remember last point in case we have
        !           561:         mov     edi,[ebp].ptl_y         ; to continue to another record
        !           562:         mov     [esp].sf_ptfxLast.ptl_x,esi
        !           563:         mov     [esp].sf_ptfxLast.ptl_y,edi
        !           564: 
        !           565:         mov     esi,[eax].ptl_x         ;load up current end point
        !           566:         mov     edi,[eax].ptl_y
        !           567:         mov     [esp].sf_pptfx,eax
        !           568: 
        !           569:         jmp     new_line
        !           570: 
        !           571: ;/////////////////////////////////////////////////////////////////////
        !           572: ;// Next Line Stuff
        !           573: ;/////////////////////////////////////////////////////////////////////
        !           574: 
        !           575: handle_closefigure:
        !           576:         mov     [esp].sf_pd.pd_flags,0
        !           577:         mov     ebx,[esp].sf_ptfxLast.ptl_x
        !           578:         mov     ecx,[esp].sf_ptfxLast.ptl_y
        !           579:         mov     esi,[esp].sf_ptfxStartFigure.ptl_x
        !           580:         mov     edi,[esp].sf_ptfxStartFigure.ptl_y
        !           581: 
        !           582:         jmp     new_line
        !           583: 
        !           584: ; Before getting the next path record, see if we have to do a closefigure:
        !           585: 
        !           586: check_for_closefigure:
        !           587:         test    [esp].sf_pd.pd_flags,PD_CLOSEFIGURE
        !           588:         jnz     handle_closefigure
        !           589:         mov     esi,[esp].sf_bMore
        !           590:         or      esi,esi
        !           591:         jnz     next_record
        !           592: 
        !           593: all_done:
        !           594: 
        !           595:         pop     ebp
        !           596:         cRet    vFastLine
        !           597: 
        !           598: ;/////////////////////////////////////////////////////////////////////
        !           599: ;// Output Integer Line
        !           600: ;/////////////////////////////////////////////////////////////////////
        !           601: 
        !           602: ; ebx                  = x
        !           603: ; ecx                  = y
        !           604: ; esi                  = dx
        !           605: ; edi                  = dy
        !           606: ; [esp].sf_ulErrorTerm = incomplete error term (actual value is 'dx - bias')
        !           607: ; [esp].sf_ulCmd       = draw command
        !           608: 
        !           609: ; NOTE: The port values retrieved from the PDEV are word values, and word
        !           610: ; moves have a one cycle penalty.  For this reason, the values should
        !           611: ; actually be defined as dwords in the PDEV...
        !           612: 
        !           613:         public  int_output_line
        !           614: int_output_line:
        !           615:         mov     ebp,[esp].sf_ppdev      ;ebp = ppdev
        !           616:         cmp     [esp].sf_bSetCP,0
        !           617:         je      short int_current_position_already_set
        !           618: 
        !           619:         mov     dx,[ebp].pdev_gp_stat
        !           620: @@:     in      ax,dx
        !           621:         and     eax,FIFO_7_EMPTY        ;wait for 7 entries
        !           622:         jnz     short @b
        !           623: 
        !           624:         mov     dx,[ebp].pdev_cur_x
        !           625:         mov     eax,ebx
        !           626:         out     dx,ax
        !           627: 
        !           628:         mov     dx,[ebp].pdev_cur_y
        !           629:         mov     eax,ecx
        !           630:         out     dx,ax
        !           631: 
        !           632:         mov     [esp].sf_bSetCP,0       ;the next integer line in this figure
        !           633:                                         ; will have the CP set correctly
        !           634: 
        !           635:         jmp     short int_output_common
        !           636: 
        !           637: int_current_position_already_set:
        !           638:         mov     dx,[ebp].pdev_gp_stat
        !           639: @@:     in      ax,dx
        !           640:         and     eax,FIFO_5_EMPTY        ;wait for 5 entries
        !           641:         jnz     short @b
        !           642: 
        !           643:         public  int_output_common
        !           644: int_output_common:
        !           645:         cmp     esi,[esp].sf_ulLastLength
        !           646:         je      short @f
        !           647: 
        !           648:         mov     dx,[ebp].pdev_line_max
        !           649:         mov     eax,esi
        !           650:         out     dx,ax
        !           651:         mov     [esp].sf_ulLastLength,eax
        !           652: @@:
        !           653:         mov     dx,[ebp].pdev_axstp
        !           654:         mov     eax,edi
        !           655:         out     dx,ax                   ;axial = dy
        !           656: 
        !           657:         mov     dx,[ebp].pdev_diastp
        !           658:         sub     eax,esi
        !           659:         out     dx,ax                   ;diag = dy - dx
        !           660: 
        !           661:         mov     edx,[esp].sf_ulErrorTerm
        !           662:         sar     edx,1
        !           663:         add     eax,edx
        !           664:         mov     dx,[ebp].pdev_err_term
        !           665:         out     dx,ax                   ;err = dy - dx + floor((dx - bias) / 2)
        !           666: 
        !           667:         mov     dx,[ebp].pdev_cmd
        !           668:         mov     eax,[esp].sf_ulCmd
        !           669:         out     dx,ax                   ;draw that puppy
        !           670: 
        !           671: ;/////////////////////////////////////////////////////////////////////
        !           672: ;// Main Loop
        !           673: ;/////////////////////////////////////////////////////////////////////
        !           674: 
        !           675:         public  next_line
        !           676: next_line:
        !           677:         mov     eax,[esp].sf_pptfx
        !           678:         cmp     eax,[esp].sf_pptfxEnd
        !           679:         jae     check_for_closefigure
        !           680: 
        !           681:         mov     ebx,[eax].ptl_x
        !           682:         mov     ecx,[eax].ptl_y
        !           683:         mov     esi,[eax+8].ptl_x
        !           684:         mov     edi,[eax+8].ptl_y
        !           685:         add     eax,8
        !           686:         mov     [esp].sf_pptfx,eax
        !           687: 
        !           688:         public  new_line
        !           689: new_line:
        !           690: 
        !           691: ; Octants are numbered as follows:
        !           692: ;
        !           693: ;        \ 5 | 6 /
        !           694: ;         \  |  /
        !           695: ;        4 \ | / 7
        !           696: ;           \ /
        !           697: ;       -----+-----
        !           698: ;           /|\
        !           699: ;        3 / | \ 0
        !           700: ;         /  |  \
        !           701: ;        / 2 | 1 \
        !           702: ;
        !           703: 
        !           704: ; ebx = M0
        !           705: ; ecx = N0
        !           706: ; esi = M1 (dM)
        !           707: ; edi = N1 (dN)
        !           708: 
        !           709:         mov     [esp].sf_ptfxStart.ptl_x,ebx
        !           710:         mov     [esp].sf_ptfxStart.ptl_y,ecx
        !           711:         mov     [esp].sf_ptfxEnd.ptl_x,esi
        !           712:         mov     [esp].sf_ptfxEnd.ptl_y,edi
        !           713:                                         ;save points in case we have to punt
        !           714:         mov     eax,ebx
        !           715:         or      eax,ecx
        !           716:         or      eax,esi
        !           717:         or      eax,edi
        !           718:         and     eax,F-1
        !           719:         jnz     non_integer
        !           720: 
        !           721: ;/////////////////////////////////////////////////////////////////////
        !           722: ;// Integer Lines
        !           723: ;/////////////////////////////////////////////////////////////////////
        !           724: 
        !           725:         sar     ebx,FLOG2               ;x0
        !           726:         sar     ecx,FLOG2               ;y0
        !           727:         sar     esi,FLOG2               ;x1 (soon to be dx)
        !           728:         sar     edi,FLOG2               ;y1 (soon to be dy)
        !           729: 
        !           730:         sub     esi,ebx
        !           731:         jl      int_2_3_4_5
        !           732:         jz      int_radial_90_270
        !           733:         sub     edi,ecx
        !           734:         jl      int_6_7
        !           735:         jz      int_radial_0
        !           736:         cmp     esi,edi
        !           737:         jl      int_1
        !           738:         je      int_radial_315
        !           739: 
        !           740: int_0:
        !           741:         lea     ebp,[esi - 1]
        !           742:         mov     [esp].sf_ulCmd,DEFAULT_DRAW_CMD + PLUS_Y + PLUS_X
        !           743:         mov     [esp].sf_ulErrorTerm,ebp
        !           744: 
        !           745:         jmp     int_output_line
        !           746: 
        !           747:         public  int_1
        !           748: int_1:
        !           749:         xchg    esi,edi
        !           750:         lea     ebp,[esi - 1]
        !           751:         mov     [esp].sf_ulCmd,DEFAULT_DRAW_CMD + PLUS_Y + PLUS_X + MAJOR_Y
        !           752:         mov     [esp].sf_ulErrorTerm,ebp
        !           753: 
        !           754:         jmp     int_output_line
        !           755: 
        !           756:         public  int_2_3_4_5
        !           757: int_2_3_4_5:
        !           758:         neg     esi
        !           759:         sub     edi,ecx
        !           760:         jl      int_4_5
        !           761:         jz      int_radial_180
        !           762:         cmp     esi,edi
        !           763:         jl      int_2
        !           764:         je      int_radial_225
        !           765: 
        !           766:         public  int_3
        !           767: int_3:
        !           768:         lea     ebp,[esi - 1]
        !           769:         mov     [esp].sf_ulCmd,DEFAULT_DRAW_CMD + PLUS_Y
        !           770:         mov     [esp].sf_ulErrorTerm,ebp
        !           771: 
        !           772:         jmp     int_output_line
        !           773: 
        !           774:         public  int_2
        !           775: int_2:
        !           776:         xchg    esi,edi
        !           777:         mov     [esp].sf_ulCmd,DEFAULT_DRAW_CMD + PLUS_Y + MAJOR_Y
        !           778:         mov     [esp].sf_ulErrorTerm,esi
        !           779: 
        !           780:         jmp     int_output_line
        !           781: 
        !           782:         public  int_4_5
        !           783: int_4_5:
        !           784:         neg     edi
        !           785:         cmp     esi,edi
        !           786:         jl      int_5
        !           787:         je      int_radial_135
        !           788: 
        !           789: int_4:
        !           790:         mov     [esp].sf_ulCmd,DEFAULT_DRAW_CMD
        !           791:         mov     [esp].sf_ulErrorTerm,esi
        !           792: 
        !           793:         jmp     int_output_line
        !           794: 
        !           795:         public  int_5
        !           796: int_5:
        !           797:         xchg    esi,edi
        !           798:         mov     [esp].sf_ulCmd,DEFAULT_DRAW_CMD + MAJOR_Y
        !           799:         mov     [esp].sf_ulErrorTerm,esi
        !           800: 
        !           801:         jmp     int_output_line
        !           802: 
        !           803:         public  int_6_7
        !           804: int_6_7:
        !           805:         neg     edi
        !           806:         cmp     esi,edi
        !           807:         jg      int_7
        !           808:         je      int_radial_45
        !           809: 
        !           810: int_6:
        !           811:         xchg    esi,edi
        !           812:         lea     ebp,[esi - 1]
        !           813:         mov     [esp].sf_ulCmd,DEFAULT_DRAW_CMD + MAJOR_Y + PLUS_X
        !           814:         mov     [esp].sf_ulErrorTerm,ebp
        !           815: 
        !           816:         jmp     int_output_line
        !           817: 
        !           818:         public  int_7
        !           819: int_7:
        !           820:         mov     [esp].sf_ulCmd,DEFAULT_DRAW_CMD + PLUS_X
        !           821:         mov     [esp].sf_ulErrorTerm,esi
        !           822: 
        !           823:         jmp     int_output_line
        !           824: 
        !           825: ;/////////////////////////////////////////////////////////////////////
        !           826: ;// Lines In The 8 Cardinal Directions
        !           827: ;/////////////////////////////////////////////////////////////////////
        !           828: 
        !           829:         public  int_radial_45
        !           830: int_radial_45:
        !           831:         mov     ebp,DRAW_LINE + DRAW + DIR_TYPE_RADIAL + WRITE + \
        !           832:                     LAST_PIXEL_OFF + MULTIPLE_PIXELS + DRAWING_DIRECTION_45
        !           833:         jmp     short int_output_radial
        !           834: 
        !           835:         public  int_radial_135
        !           836: int_radial_135:
        !           837:         mov     ebp,DRAW_LINE + DRAW + DIR_TYPE_RADIAL + WRITE + \
        !           838:                     LAST_PIXEL_OFF + MULTIPLE_PIXELS + DRAWING_DIRECTION_135
        !           839:         jmp     short int_output_radial
        !           840: 
        !           841:         public  int_radial_225
        !           842: int_radial_225:
        !           843:         mov     ebp,DRAW_LINE + DRAW + DIR_TYPE_RADIAL + WRITE + \
        !           844:                     LAST_PIXEL_OFF + MULTIPLE_PIXELS + DRAWING_DIRECTION_225
        !           845:         jmp     short int_output_radial
        !           846: 
        !           847:         public  int_radial_315
        !           848: int_radial_315:
        !           849:         mov     ebp,DRAW_LINE + DRAW + DIR_TYPE_RADIAL + WRITE + \
        !           850:                     LAST_PIXEL_OFF + MULTIPLE_PIXELS + DRAWING_DIRECTION_315
        !           851:         jmp     short int_output_radial
        !           852: 
        !           853:         public  int_radial_90_270
        !           854: int_radial_90_270:
        !           855:         mov     ebp,DRAW_LINE + DRAW + DIR_TYPE_RADIAL + WRITE + \
        !           856:                     LAST_PIXEL_OFF + MULTIPLE_PIXELS + DRAWING_DIRECTION_270
        !           857:         mov     esi,edi
        !           858:         sub     esi,ecx
        !           859:         jg      short int_output_radial ;if top-to-bottom vertical line
        !           860:         jz      next_line               ;if zero length line
        !           861: 
        !           862:         neg     esi
        !           863:         mov     ebp,DRAW_LINE + DRAW + DIR_TYPE_RADIAL + WRITE + \
        !           864:                     LAST_PIXEL_OFF + MULTIPLE_PIXELS + DRAWING_DIRECTION_90
        !           865:         jmp     short int_output_radial
        !           866: 
        !           867:         public  int_radial_180
        !           868: int_radial_180:
        !           869:         mov     ebp,DRAW_LINE + DRAW + DIR_TYPE_RADIAL + WRITE + \
        !           870:                     LAST_PIXEL_OFF + MULTIPLE_PIXELS + DRAWING_DIRECTION_180
        !           871:         jmp     short int_output_radial
        !           872: 
        !           873: int_radial_0:
        !           874:         mov     ebp,DRAW_LINE + DRAW + DIR_TYPE_RADIAL + WRITE + \
        !           875:                     LAST_PIXEL_OFF + MULTIPLE_PIXELS + DRAWING_DIRECTION_0
        !           876: 
        !           877: ; ebx = x
        !           878: ; ecx = y
        !           879: ; esi = dx (length of radial line since it's normalized)
        !           880: ; ebp = drawing command
        !           881: 
        !           882:         public  int_output_radial
        !           883: int_output_radial:
        !           884:         mov     edi,[esp].sf_ppdev
        !           885:         cmp     [esp].sf_bSetCP,0
        !           886:         je      short int_radial_continue_figure
        !           887: 
        !           888:         mov     dx,[edi].pdev_gp_stat
        !           889: @@:     in      ax,dx
        !           890:         and     eax,FIFO_4_EMPTY
        !           891:         jnz     short @b
        !           892: 
        !           893:         mov     dx,[edi].pdev_cur_x
        !           894:         mov     eax,ebx
        !           895:         out     dx,ax
        !           896: 
        !           897:         mov     dx,[edi].pdev_cur_y
        !           898:         mov     eax,ecx
        !           899:         out     dx,ax
        !           900: 
        !           901:         mov     [esp].sf_bSetCP,0       ;the next integer line in this figure
        !           902:                                         ; will have the CP set correctly
        !           903: 
        !           904:         cmp     esi,[esp].sf_ulLastLength
        !           905:         je      short @f
        !           906: 
        !           907:         mov     dx,[edi].pdev_line_max
        !           908:         mov     eax,esi
        !           909:         out     dx,ax
        !           910:         mov     [esp].sf_ulLastLength,eax
        !           911: @@:
        !           912:         mov     dx,[edi].pdev_cmd
        !           913:         mov     eax,ebp
        !           914:         out     dx,ax
        !           915:         jmp     next_line
        !           916: 
        !           917: ; Jump to here if we don't have to update the current position first:
        !           918: 
        !           919:         public  int_radial_continue_figure
        !           920: int_radial_continue_figure:
        !           921:         cmp     esi,[esp].sf_ulLastLength
        !           922:         je      short int_radial_skip_length
        !           923: 
        !           924:         mov     dx,[edi].pdev_gp_stat
        !           925: @@:     in      ax,dx
        !           926:         and     eax,FIFO_2_EMPTY
        !           927:         jnz     short @b
        !           928: 
        !           929:         mov     dx,[edi].pdev_line_max
        !           930:         mov     eax,esi
        !           931:         out     dx,ax
        !           932:         mov     [esp].sf_ulLastLength,eax
        !           933: 
        !           934:         mov     dx,[edi].pdev_cmd
        !           935:         mov     eax,ebp
        !           936:         out     dx,ax
        !           937:         jmp     next_line
        !           938: 
        !           939: ; Jump to here if we don't have to update the current position or the
        !           940: ; line length variable:
        !           941: 
        !           942:         public  int_radial_skip_length
        !           943: int_radial_skip_length:
        !           944:         mov     dx,[edi].pdev_gp_stat
        !           945: @@:     in      ax,dx
        !           946:         and     eax,FIFO_1_EMPTY
        !           947:         jnz     short @b
        !           948: 
        !           949:         mov     dx,[edi].pdev_cmd
        !           950:         mov     eax,ebp
        !           951:         out     dx,ax
        !           952:         jmp     next_line
        !           953: 
        !           954: ;/////////////////////////////////////////////////////////////////////
        !           955: ;// Non-Integer Lines
        !           956: ;/////////////////////////////////////////////////////////////////////
        !           957: 
        !           958:         public  non_integer
        !           959: non_integer:
        !           960:         sub     esi,ebx
        !           961:         jl      non_int_2_3_4_5
        !           962:         sub     edi,ecx
        !           963:         jl      non_int_6_7
        !           964:         cmp     esi,edi
        !           965:         jl      non_int_1
        !           966:         je      non_int_0_slope_one
        !           967: 
        !           968: non_int_0:
        !           969:         cmp     esi,MAX_GIQ_DELTA
        !           970:         jg      punt_line
        !           971: 
        !           972:         GIQ     ROUND_X_AND_Y_DOWN
        !           973: 
        !           974: non_int_0_common:
        !           975:         add     ecx,edi                 ;err += dN
        !           976:         mov     [esp].sf_ulErrorTerm,ecx
        !           977: 
        !           978:         mov     eax,[esp].sf_x1
        !           979:         sub     eax,ebx
        !           980:         jle     next_line
        !           981:         mov     [esp].sf_cPels,eax
        !           982:         mov     [esp].sf_ulCmd,DEFAULT_DRAW_CMD + PLUS_Y + PLUS_X
        !           983: 
        !           984:         public  non_int_x_major
        !           985: non_int_x_major:
        !           986:         mov     ecx,[esp].sf_ppdev
        !           987:         mov     dx,[ecx].pdev_gp_stat
        !           988: @@:     in      ax,dx
        !           989:         and     eax,FIFO_7_EMPTY        ;wait for 7 entries
        !           990:         jnz     short @b
        !           991: 
        !           992: ; Fractional end-point lines aren't usually going to have the current
        !           993: ; position already set correctly, so we explicitly set the CP each time:
        !           994: 
        !           995:         mov     dx,[ecx].pdev_cur_x
        !           996:         mov     eax,ebx
        !           997:         out     dx,ax                   ;x0
        !           998: 
        !           999:         mov     dx,[ecx].pdev_cur_y
        !          1000:         mov     eax,ebp
        !          1001:         out     dx,ax                   ;y0
        !          1002: 
        !          1003:         mov     [esp].sf_bSetCP,1       ;the next integer line in this figure
        !          1004:                                         ; will not necessarily have the CP set
        !          1005:                                         ; correctly
        !          1006: 
        !          1007:         mov     eax,[esp].sf_cPels
        !          1008:         cmp     eax,[esp].sf_ulLastLength
        !          1009:         je      short @f
        !          1010: 
        !          1011:         mov     dx,[ecx].pdev_line_max
        !          1012:         out     dx,ax                   ;length = cPels
        !          1013:         mov     [esp].sf_ulLastLength,eax
        !          1014: @@:
        !          1015:         mov     dx,[ecx].pdev_axstp
        !          1016:         mov     eax,edi
        !          1017:         out     dx,ax                   ;axial = dN
        !          1018: 
        !          1019:         mov     dx,[ecx].pdev_diastp
        !          1020:         sub     eax,esi
        !          1021:         out     dx,ax                   ;diag = dN - dM
        !          1022: 
        !          1023:         mov     dx,[ecx].pdev_err_term
        !          1024:         mov     eax,[esp].sf_ulErrorTerm
        !          1025:         out     dx,ax                   ;error term
        !          1026: 
        !          1027:         mov     dx,[ecx].pdev_cmd
        !          1028:         mov     eax,[esp].sf_ulCmd
        !          1029:         out     dx,ax                   ;output it
        !          1030: 
        !          1031:         jmp     next_line
        !          1032: 
        !          1033: ; Lines of slope one have a special rounding rule: when the line
        !          1034: ; runs exactly half way between two pixels, the upper or right pel
        !          1035: ; is illuminated.  This translates into x=1/2 rounding up in value,
        !          1036: ; and y=1/2 rounding down:
        !          1037: 
        !          1038:         public  non_int_0_slope_one
        !          1039: non_int_0_slope_one:
        !          1040:         or      esi,esi
        !          1041:         jz      next_line               ;quick check for a zero length GIQ line
        !          1042: 
        !          1043:         cmp     esi,MAX_GIQ_DELTA
        !          1044:         jg      punt_line
        !          1045: 
        !          1046:         GIQ     ROUND_Y_DOWN_SLOPE_ONE
        !          1047:         jmp     non_int_0_common
        !          1048: 
        !          1049:         public  non_int_1
        !          1050: non_int_1:
        !          1051:         cmp     edi,MAX_GIQ_DELTA
        !          1052:         jg      punt_line
        !          1053: 
        !          1054:         GIQR    ROUND_X_AND_Y_DOWN
        !          1055:         add     ecx,esi                 ;err += dM
        !          1056:         mov     [esp].sf_ulErrorTerm,ecx
        !          1057: 
        !          1058:         mov     eax,[esp].sf_y1
        !          1059:         sub     eax,ebp
        !          1060:         jle     next_line
        !          1061:         mov     [esp].sf_cPels,eax
        !          1062:         mov     [esp].sf_ulCmd,DEFAULT_DRAW_CMD + PLUS_Y + PLUS_X + MAJOR_Y
        !          1063: 
        !          1064:         public  non_int_y_major
        !          1065: non_int_y_major:
        !          1066:         mov     ecx,[esp].sf_ppdev
        !          1067:         mov     dx,[ecx].pdev_gp_stat
        !          1068: @@:     in      ax,dx
        !          1069:         and     eax,FIFO_7_EMPTY        ;wait for 7 entries
        !          1070:         jnz     short @b
        !          1071: 
        !          1072: ; Fractional end-point lines aren't usually going to have the current
        !          1073: ; position already set correctly, so we explicitly set the CP each time:
        !          1074: 
        !          1075:         mov     dx,[ecx].pdev_cur_x
        !          1076:         mov     eax,ebx
        !          1077:         out     dx,ax                   ;x0
        !          1078: 
        !          1079:         mov     dx,[ecx].pdev_cur_y
        !          1080:         mov     eax,ebp
        !          1081:         out     dx,ax                   ;y0
        !          1082: 
        !          1083:         mov     [esp].sf_bSetCP,1       ;the next integer line in this figure
        !          1084:                                         ; will not necessarily have the CP set
        !          1085:                                         ; correctly
        !          1086: 
        !          1087:         mov     eax,[esp].sf_cPels
        !          1088:         cmp     eax,[esp].sf_ulLastLength
        !          1089:         je      short @f
        !          1090: 
        !          1091:         mov     dx,[ecx].pdev_line_max
        !          1092:         out     dx,ax                   ;length = cPels
        !          1093:         mov     [esp].sf_ulLastLength,eax
        !          1094: @@:
        !          1095:         mov     dx,[ecx].pdev_axstp
        !          1096:         mov     eax,esi
        !          1097:         out     dx,ax                   ;axial = dM
        !          1098: 
        !          1099:         mov     dx,[ecx].pdev_diastp
        !          1100:         sub     eax,edi
        !          1101:         out     dx,ax                   ;diag = dM - dN
        !          1102: 
        !          1103:         mov     dx,[ecx].pdev_err_term
        !          1104:         mov     eax,[esp].sf_ulErrorTerm
        !          1105:         out     dx,ax                   ;error term
        !          1106: 
        !          1107:         mov     dx,[ecx].pdev_cmd
        !          1108:         mov     eax,[esp].sf_ulCmd
        !          1109:         out     dx,ax                   ;output it
        !          1110: 
        !          1111:         jmp     next_line
        !          1112: 
        !          1113:         public  non_int_2_3_4_5
        !          1114: non_int_2_3_4_5:
        !          1115:         neg     esi                     ;dM = -dM (now positive)
        !          1116:         neg     ebx                     ;M0 = -M0
        !          1117:         sub     edi,ecx
        !          1118:         jl      non_int_4_5
        !          1119:         cmp     esi,edi
        !          1120:         jl      non_int_2
        !          1121: 
        !          1122: non_int_3:
        !          1123:         cmp     esi,MAX_GIQ_DELTA
        !          1124:         jg      punt_line
        !          1125: 
        !          1126:         GIQ     ROUND_Y_DOWN
        !          1127:         add     ecx,edi                 ;err += dN
        !          1128:         mov     [esp].sf_ulErrorTerm,ecx
        !          1129: 
        !          1130:         neg     ebx                     ;untransform x0
        !          1131: 
        !          1132:         mov     eax,[esp].sf_x1
        !          1133:         add     eax,ebx
        !          1134:         jle     next_line
        !          1135:         mov     [esp].sf_cPels,eax
        !          1136:         mov     [esp].sf_ulCmd,DEFAULT_DRAW_CMD + PLUS_Y
        !          1137: 
        !          1138:         jmp     non_int_x_major
        !          1139: 
        !          1140:         public  non_int_2
        !          1141: non_int_2:
        !          1142:         cmp     edi,MAX_GIQ_DELTA
        !          1143:         jg      punt_line
        !          1144: 
        !          1145:         GIQR    ROUND_Y_DOWN
        !          1146:         add     ecx,esi                 ;err += dM
        !          1147:         mov     [esp].sf_ulErrorTerm,ecx
        !          1148: 
        !          1149:         neg     ebx                     ;untransform x0
        !          1150: 
        !          1151:         mov     eax,[esp].sf_y1
        !          1152:         sub     eax,ebp
        !          1153:         jle     next_line
        !          1154:         mov     [esp].sf_cPels,eax
        !          1155:         mov     [esp].sf_ulCmd,DEFAULT_DRAW_CMD + PLUS_Y + MAJOR_Y
        !          1156: 
        !          1157:         jmp     non_int_y_major
        !          1158: 
        !          1159:         public  non_int_4_5
        !          1160: non_int_4_5:
        !          1161:         neg     edi                     ;dN = -dN (now positive)
        !          1162:         neg     ecx                     ;N0 = -N0
        !          1163:         cmp     esi,edi
        !          1164:         jl      non_int_5
        !          1165:         je      non_int_4_slope_one
        !          1166: 
        !          1167:         public  non_int_4
        !          1168: non_int_4:
        !          1169:         cmp     esi,MAX_GIQ_DELTA
        !          1170:         jg      punt_line
        !          1171: 
        !          1172:         GIQ     0
        !          1173: 
        !          1174: non_int_4_common:
        !          1175:         add     ecx,edi                 ;err += dN
        !          1176:         mov     [esp].sf_ulErrorTerm,ecx
        !          1177: 
        !          1178:         neg     ebx                     ;untransform x0
        !          1179:         neg     ebp                     ;untransform y0
        !          1180: 
        !          1181:         mov     eax,[esp].sf_x1
        !          1182:         add     eax,ebx
        !          1183:         jle     next_line
        !          1184:         mov     [esp].sf_cPels,eax
        !          1185:         mov     [esp].sf_ulCmd,DEFAULT_DRAW_CMD
        !          1186: 
        !          1187:         jmp     non_int_x_major
        !          1188: 
        !          1189: ; Lines of slope one have a special rounding rule.
        !          1190: 
        !          1191:         public  non_int_4_slope_one
        !          1192: non_int_4_slope_one:
        !          1193:         cmp     esi,MAX_GIQ_DELTA
        !          1194:         jg      punt_line
        !          1195: 
        !          1196:         GIQ     ROUND_X_DOWN_SLOPE_ONE
        !          1197:         jmp     non_int_4_common
        !          1198: 
        !          1199:         public  non_int_5
        !          1200: non_int_5:
        !          1201:         cmp     edi,MAX_GIQ_DELTA
        !          1202:         jg      punt_line
        !          1203: 
        !          1204:         GIQR    0
        !          1205:         add     ecx,esi                 ;err += dM
        !          1206:         mov     [esp].sf_ulErrorTerm,ecx
        !          1207: 
        !          1208:         neg     ebx                     ;untransform x0
        !          1209:         neg     ebp                     ;untransform y0
        !          1210: 
        !          1211:         mov     eax,[esp].sf_y1
        !          1212:         add     eax,ebp
        !          1213:         jle     next_line
        !          1214:         mov     [esp].sf_cPels,eax
        !          1215:         mov     [esp].sf_ulCmd,DEFAULT_DRAW_CMD + MAJOR_Y
        !          1216: 
        !          1217:         jmp     non_int_y_major
        !          1218: 
        !          1219:         public  non_int_6_7
        !          1220: non_int_6_7:
        !          1221:         neg     edi                     ;dN = -dN (now positive)
        !          1222:         neg     ecx                     ;M0 = -M0
        !          1223:         cmp     esi,edi
        !          1224:         je      non_int_7_slope_one
        !          1225:         jg      non_int_7
        !          1226: 
        !          1227:         public  non_int_6
        !          1228: non_int_6:
        !          1229:         cmp     edi,MAX_GIQ_DELTA
        !          1230:         jg      punt_line
        !          1231: 
        !          1232:         GIQR    ROUND_X_DOWN
        !          1233:         add     ecx,esi                 ;err += dM
        !          1234:         mov     [esp].sf_ulErrorTerm,ecx
        !          1235: 
        !          1236:         neg     ebp                     ;untransform y0
        !          1237: 
        !          1238:         mov     eax,[esp].sf_y1
        !          1239:         add     eax,ebp
        !          1240:         jle     next_line
        !          1241:         mov     [esp].sf_cPels,eax
        !          1242:         mov     [esp].sf_ulCmd,DEFAULT_DRAW_CMD + MAJOR_Y + PLUS_X
        !          1243: 
        !          1244:         jmp     non_int_y_major
        !          1245: 
        !          1246:         public  non_int_7
        !          1247: non_int_7:
        !          1248:         cmp     esi,MAX_GIQ_DELTA
        !          1249:         jg      punt_line
        !          1250: 
        !          1251:         GIQ     ROUND_X_DOWN
        !          1252: 
        !          1253: non_int_7_common:
        !          1254:         add     ecx,edi                 ;err += dN
        !          1255:         mov     [esp].sf_ulErrorTerm,ecx
        !          1256: 
        !          1257:         neg     ebp                     ;untransform y0
        !          1258: 
        !          1259:         mov     eax,[esp].sf_x1
        !          1260:         sub     eax,ebx
        !          1261:         jle     next_line
        !          1262:         mov     [esp].sf_cPels,eax
        !          1263:         mov     [esp].sf_ulCmd,DEFAULT_DRAW_CMD + PLUS_X
        !          1264: 
        !          1265:         jmp     non_int_x_major
        !          1266: 
        !          1267:         public  non_int_7_slope_one
        !          1268: non_int_7_slope_one:
        !          1269:         cmp     esi,MAX_GIQ_DELTA
        !          1270:         jg      punt_line
        !          1271: 
        !          1272:         GIQ     ROUND_X_DOWN_SLOPE_ONE
        !          1273:         jmp     non_int_7_common
        !          1274: 
        !          1275: ;/////////////////////////////////////////////////////////////////////
        !          1276: ;// Punt Line
        !          1277: ;/////////////////////////////////////////////////////////////////////
        !          1278: 
        !          1279: ; If the line is too long, we punt to our strip drawing routine.
        !          1280: 
        !          1281:         public  punt_line
        !          1282: punt_line:
        !          1283:         mov     esi,esp
        !          1284:         lea     eax,[esp].sf_ptfxStart
        !          1285:         lea     ebx,[esp].sf_ptfxEnd
        !          1286: 
        !          1287:         cCall   bLines,<[esi].sf_ppdev, eax, ebx, 0, 1, 0, \
        !          1288:                         [esi].sf_prclClip, [esi].sf_apfn, [esi].sf_flags>
        !          1289: 
        !          1290:         mov     [esp].sf_bSetCP,1       ;Always reset CP after punting
        !          1291:         mov     [esp].sf_ulLastLength,-1;Always reset line length after punting
        !          1292: 
        !          1293:         jmp     next_line
        !          1294: 
        !          1295: endProc vFastLine
        !          1296: 
        !          1297:         end

unix.superglobalmegacorp.com

This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.