Annotation of ntddk/src/video/displays/s3/i386/fastline.asm, revision 1.1.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.