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

1.1     ! root        1: ;---------------------------Module-Header------------------------------;
        !             2: ; Module Name: fastline.asm
        !             3: ;
        !             4: ; This module goes completely overboard in trying to do fast lines.
        !             5: ; It handles only solid R2_COPYPEN unclipped lines.
        !             6: ;
        !             7: ; Unfortunately, I know of only 4 performance tricks:
        !             8: ;
        !             9: ;    1) Most VGAs can co-process the last write to video memory,
        !            10: ;       so we employ a traditional Bresenham-style algorithm (as
        !            11: ;       opposed to a run-length version) as this minimizes our
        !            12: ;       set-up time, and we can do some work between video writes
        !            13: ;       without any throughput penalty.
        !            14: ;
        !            15: ;    2) Most VGAs can do one aligned word write faster than two
        !            16: ;       byte writes; consequently we derive a double-stepping DDA
        !            17: ;       that does aligned word writes whenever possible (note that
        !            18: ;       this only makes sense on x-major lines).
        !            19: ;
        !            20: ;    3) Planar mode can be used to speed up long horizontal lines,
        !            21: ;       where the cost to switch from linear to planar mode is offset
        !            22: ;       by the ability to light 8 pixels on every word write instead
        !            23: ;       of 2.
        !            24: ;
        !            25: ;    4) Most lines have integer end-points, so we accelerate those.
        !            26: ;
        !            27: ; If you're not familiar with GIQ lines, this is not the code to start
        !            28: ; with.
        !            29: ;
        !            30: ; Copyright (c) 1992-1993 Microsoft Corporation
        !            31: ;-----------------------------------------------------------------------;
        !            32: 
        !            33:         .386
        !            34: 
        !            35:         .model  small,c
        !            36: 
        !            37:         assume cs:FLAT,ds:FLAT,es:FLAT,ss:FLAT
        !            38:         assume fs:nothing,gs:nothing
        !            39: 
        !            40:         .xlist
        !            41:         include stdcall.inc             ;calling convention cmacros
        !            42:         include i386\egavga.inc
        !            43:         include i386\strucs.inc
        !            44:         include i386\driver.inc
        !            45:         include i386\lines.inc
        !            46:         .list
        !            47: 
        !            48: ; Length of horizontal line needed before we'll do it in planar mode:
        !            49: 
        !            50:         NUM_PELS_NEEDED_FOR_PLANAR_HORIZONTAL   equ 64
        !            51: 
        !            52: ; Line coordinates are given in 28.4 fixed point format:
        !            53: 
        !            54:         F               equ 16
        !            55:         FLOG2           equ 4
        !            56: 
        !            57: ; The following values must match those in winddi.h!
        !            58: 
        !            59:         PD_BEGINSUBPATH equ 00000001h
        !            60:         PD_ENDSUBPATH   equ 00000002h
        !            61:         PD_RESETSTYLE   equ 00000004h
        !            62:         PD_CLOSEFIGURE  equ 00000008h
        !            63:         PD_BEZIERS      equ 00000010h
        !            64: 
        !            65:         PATHDATA struc
        !            66: 
        !            67:         pd_flags        dd  ?
        !            68:         pd_count        dd  ?
        !            69:         pd_pptfx        dd  ?
        !            70: 
        !            71:         PATHDATA ends
        !            72: 
        !            73: ;-------------------------------------------------------------------------;
        !            74: ; I felt a compelling need to use 'ebp' as a 7th general register, and we
        !            75: ; have no nifty macros for dereferencing frame variables off 'esp'.  So
        !            76: ; with this structure I am rolling my own stack frame:
        !            77: 
        !            78: STATE_MEM_SIZE          equ 4           ;4 dwords
        !            79: PROC_MEM_SIZE           equ 6           ;6 dwords
        !            80: 
        !            81: STACK_FRAME struc
        !            82: 
        !            83: ; State variables (don't add/delete fields without modifying STATE_MEM_SIZE!)
        !            84: 
        !            85: sf_ulOurEbp             dd ?            ;useful for debugging
        !            86: sf_ulOriginalEbx        dd ?
        !            87: sf_ulOriginalEdi        dd ?
        !            88: sf_ulOriginalEsi        dd ?
        !            89: 
        !            90: ; Frame variables (feel free to add/delete fields):
        !            91: 
        !            92: sf_lDelta               dd ?            ;sign depends on going up or down
        !            93: sf_pfnReturn            dd ?            ;where to jump after getting next bank
        !            94: sf_pfnNextBank          dd ?            ;routine for getting the next bank
        !            95: sf_y0                   dd ?            ;GIQ variables
        !            96: sf_y1                   dd ?
        !            97: sf_x1                   dd ?
        !            98: sf_pjStart              dd ?            ;for remembering edi
        !            99: sf_cAfterThisBank       dd ?            ;# of pixels to light after this bank
        !           100: sf_ptlOrg               db (size POINTL) dup (?)
        !           101:                                         ;our  origin for normalizing the line
        !           102: sf_ptfxLast             db (size POINTL) dup (?)
        !           103:                                         ;the most recent point
        !           104: sf_ptfxStartFigure      db (size POINTL) dup (?)
        !           105:                                         ;the figure's 1st point
        !           106: sf_bMore                dd ?            ;more path records to get?
        !           107: sf_pptfxEnd             dd ?            ;points to last point in record
        !           108: sf_pptfx                dd ?            ;points to current point
        !           109: sf_pd                   db (size PATHDATA) dup (?)
        !           110:                                         ;pathdata structure
        !           111: 
        !           112: ; Procedure variables (don't add/delete fields without modifying
        !           113: ; PROC_MEM_SIZE!)
        !           114: 
        !           115: sf_ulOriginalEbp        dd ?
        !           116: sf_ulOriginalReturn     dd ?
        !           117: sf_ppdev                dd ?
        !           118: sf_ppo                  dd ?
        !           119: sf_lNextScan            dd ?
        !           120: sf_iColor               dd ?
        !           121: 
        !           122: STACK_FRAME ends
        !           123: 
        !           124:         .data
        !           125: 
        !           126:         EXTRNP  PATHOBJ_bEnum,8
        !           127: 
        !           128:         .code
        !           129: 
        !           130:         ROUND_X_DOWN            equ     01h
        !           131:         ROUND_Y_DOWN            equ     02h
        !           132:         ROUND_SLOPE_ONE         equ     04h
        !           133:         ROUND_X_AND_Y_DOWN      equ     (ROUND_X_DOWN + ROUND_Y_DOWN)
        !           134:         ROUND_X_DOWN_SLOPE_ONE  equ     (ROUND_X_DOWN + ROUND_SLOPE_ONE)
        !           135:         ROUND_Y_DOWN_SLOPE_ONE  equ     (ROUND_Y_DOWN + ROUND_SLOPE_ONE)
        !           136: 
        !           137: ;--------------------------------Macro----------------------------------;
        !           138: ; GIQ flags
        !           139: ;
        !           140: ; This macros computes the start pixel, the number of pixels to
        !           141: ; be lit, and the initial error term given a GIQ line.  The line must
        !           142: ; have already been normalized such that dM >= dN, dN >= 0.
        !           143: ;
        !           144: ; Input:   eax - M0
        !           145: ;          ebx - N0
        !           146: ;          ecx - dM
        !           147: ;          edx - dN
        !           148: ; Trashes:
        !           149: ;          esi, ebp
        !           150: ;          [esp].sf_ptlOrg.ptl_x, [esp].sf_ptlOrg.ptl_y
        !           151: ; Output:
        !           152: ;          [esp].sf_x1  - x-coordinate of last pixel (exclusive)
        !           153: ;          eax - x-coordinate of first pixel
        !           154: ;          ebx - error term
        !           155: ;          ecx - dM
        !           156: ;          edx - dN
        !           157: ;          edi - y-coordinate of first pixel
        !           158: ;-----------------------------------------------------------------------;
        !           159: 
        !           160: GIQ     macro   flags
        !           161:         local   compute_x1, compute_error_term
        !           162: 
        !           163: ; We normalize our coordinate system so that if the start point is
        !           164: ; (M0/F, N0/F), the origin is at (floor(M0/F), (N0/F)):
        !           165: 
        !           166:         mov     esi,eax
        !           167:         mov     edi,ebx
        !           168:         sar     esi,FLOG2
        !           169:         sar     edi,FLOG2
        !           170:         mov     [esp].sf_ptlOrg.ptl_x,esi
        !           171:                                         ;ptlOrg.x = floor(M0 / F)
        !           172:         mov     [esp].sf_ptlOrg.ptl_y,edi
        !           173:                                         ;ptlOrg.y = floor(N0 / F)
        !           174: 
        !           175: ; Calculate the correct [esp].sf_x1:
        !           176: 
        !           177:         lea     edi,[ebx + edx]         ;edi = N1
        !           178:         and     edi,F - 1
        !           179: 
        !           180:     if (flags AND ROUND_X_DOWN)
        !           181: 
        !           182:     if (flags AND ROUND_SLOPE_ONE)
        !           183:         lea     ebp,[eax + ecx]
        !           184:         and     ebp,F - 1               ;ebp = M1
        !           185:         sub     ebp,8
        !           186:         cmp     ebp,edi                 ;cmp M1 - 8, N1
        !           187:         jne     short compute_x1
        !           188: 
        !           189:         lea     ebp,[eax + ecx]
        !           190:         sar     ebp,FLOG2
        !           191:         jmp     short compute_error_term
        !           192:     endif
        !           193: 
        !           194: compute_x1:
        !           195: 
        !           196:         cmp     edi,1
        !           197:         sbb     edi,8                   ;N1 -= 8
        !           198:     else
        !           199:         sub     edi,8                   ;N1 -= 8
        !           200:     endif
        !           201:         sbb     esi,esi
        !           202:         xor     edi,esi
        !           203:         sub     edi,esi                 ;N1 = ABS(N1)
        !           204: 
        !           205:         lea     ebp,[eax + ecx]
        !           206:         mov     esi,ebp
        !           207:         sar     ebp,FLOG2
        !           208:         and     esi,F - 1
        !           209:         jz      short @f                ;special case for M1 == 0
        !           210:         cmp     esi,edi                 ;cmp M1, N1
        !           211:         sbb     ebp,-1                  ;ebp is now one pixel past the actual
        !           212: @@:                                     ; end coordinate (note that it hasn't
        !           213:                                         ; been affected by the origin shift)
        !           214: 
        !           215: compute_error_term:
        !           216: 
        !           217: ; eax = M0
        !           218: ; ebx = N0
        !           219: ; ebp = x1
        !           220: ; ecx = dM
        !           221: ; edx = dN
        !           222: 
        !           223:         and     ebx,F - 1
        !           224:         mov     [esp].sf_x1,ebp         ;save x1
        !           225: 
        !           226: ; Calculate our error term for x = 0.
        !           227: ;
        !           228: ; NOTE: Since this routine is used only for lines that are unclipped, we
        !           229: ;       are guaranteed by our screen size that the values will be far less
        !           230: ;       than 32 bits in significance, and so we don't worry about overflow.
        !           231: ;       If this is used for clipped lines, these multiplies will have to
        !           232: ;       be converted to give 64 bit results, because we can have 36 bits of
        !           233: ;       significance!
        !           234: 
        !           235: 
        !           236:         lea     edi,[ebx + 8]           ;edi = N0 + 8
        !           237:         mov     esi,ecx
        !           238:         imul    esi,edi                 ;esi = dM * (N0 + 8)
        !           239:         mov     edi,edx
        !           240: 
        !           241: ; We have to special case when M0 is 0 -- we know x0 will be zero.
        !           242: ; So we jump ahead a bit to a place where 'eax' is assumed to contain
        !           243: ; x0 -- and it just so happens 'eax' is zero in this case:
        !           244: 
        !           245:         and     eax,F - 1
        !           246:         jz      short @f
        !           247:         imul    edi,eax                 ;edi = dN * M0
        !           248:         sub     esi,edi
        !           249: 
        !           250: ; Calculate the x-coordinate of the first pixel:
        !           251: 
        !           252:     if (flags AND ROUND_X_DOWN)
        !           253: 
        !           254:     if (flags AND ROUND_SLOPE_ONE)
        !           255:         cmp     ebx,8
        !           256:         sbb     ebx,-1
        !           257:     endif
        !           258: 
        !           259:         cmp     ebx,1
        !           260:         sbb     ebx,8                   ;N0 -= 8
        !           261:     else
        !           262:         sub     ebx,8                   ;N0 -= 8
        !           263:     endif
        !           264:         sbb     edi,edi
        !           265:         xor     ebx,edi
        !           266:         sub     ebx,edi                 ;N0 = ABS(N0)
        !           267:         cmp     eax,ebx
        !           268:         sbb     eax,eax
        !           269:         not     eax                     ;eax = -x0
        !           270: 
        !           271: ; Now adjust the error term accordingly:
        !           272: 
        !           273: @@:
        !           274:     if (flags AND ROUND_Y_DOWN)
        !           275:         dec     esi
        !           276:     endif
        !           277:         sar     esi,FLOG2               ;esi = floor((N0 + 8) dM - M0 dN] / 16)
        !           278: 
        !           279:         mov     ebx,[esp].sf_ptlOrg.ptl_x
        !           280:         mov     edi,[esp].sf_ptlOrg.ptl_y
        !           281: 
        !           282:         sub     ebx,eax                 ;ebx = ptlOrg.ptl_x + x0
        !           283: 
        !           284:         and     eax,edx
        !           285:         add     eax,esi
        !           286:         sub     eax,ecx                 ;eax = dN * x0 + initial error - dM
        !           287:         jl      short @f                ;if the error term >= 0, we have to
        !           288:         sub     eax,ecx                 ; add 1 to the y position and subtract
        !           289:         inc     edi                     ; dM off again
        !           290: @@:
        !           291:         xchg    eax,ebx
        !           292: 
        !           293: endm
        !           294: 
        !           295: ;--------------------------------Macro----------------------------------;
        !           296: ; GIQR flags
        !           297: ;
        !           298: ; Same as above, except it handles flips about the line x = y.
        !           299: ;
        !           300: ; Input:   eax - M0
        !           301: ;          ebx - N0
        !           302: ;          ecx - dM
        !           303: ;          edx - dN
        !           304: ; Trashes:
        !           305: ;          esi, ebp
        !           306: ;          [esp].sf_ptlOrg.ptl_x, [esp].sf_ptlOrg.ptl_y
        !           307: ; Output:
        !           308: ;          [esp].sf_y1  - y-coordinate of last pixel (exclusive)
        !           309: ;          eax - x-coordinate of first pixel
        !           310: ;          ebx - error term
        !           311: ;          ecx - dM
        !           312: ;          edx - dN
        !           313: ;          edi - y-coordinate of first pixel
        !           314: ;-----------------------------------------------------------------------;
        !           315: 
        !           316: GIQR    macro   flags
        !           317: 
        !           318: ; We normalize our coordinate system so that if the start point is
        !           319: ; (M0/F, N0/F), the origin is at (floor(M0/F), (N0/F)):
        !           320: 
        !           321:         mov     esi,eax
        !           322:         mov     edi,ebx
        !           323:         sar     esi,FLOG2
        !           324:         sar     edi,FLOG2
        !           325:         mov     [esp].sf_ptlOrg.ptl_x,esi
        !           326:                                         ;ptlOrg.x = floor(M0 / F)
        !           327:         mov     [esp].sf_ptlOrg.ptl_y,edi
        !           328:                                         ;ptlOrg.y = floor(N0 / F)
        !           329: 
        !           330: ; Calculate the correct [esp].sf_y1:
        !           331: 
        !           332:         lea     edi,[eax + ecx]         ;edi = M1
        !           333:         and     edi,F - 1
        !           334: 
        !           335:     if (flags AND ROUND_Y_DOWN)
        !           336:         cmp     edi,1
        !           337:         sbb     edi,8                   ;M1 -= 8
        !           338:     else
        !           339:         sub     edi,8                   ;M1 -= 8
        !           340:     endif
        !           341:         sbb     esi,esi
        !           342:         xor     edi,esi
        !           343:         sub     edi,esi                 ;M1 = ABS(M1)
        !           344: 
        !           345:         lea     ebp,[ebx + edx]
        !           346:         mov     esi,ebp
        !           347:         sar     ebp,FLOG2
        !           348:         and     esi,F - 1
        !           349:         jz      short @f                ;special case for N1 == 0
        !           350:         cmp     esi,edi                 ;cmp N1, M1
        !           351:         sbb     ebp,-1                  ;ebp is now one pixel past the actual
        !           352: @@:                                     ; end coordinate (note that it hasn't
        !           353:                                         ; been affected by the origin shift)
        !           354:         and     eax,F - 1
        !           355:         mov     [esp].sf_y1,ebp
        !           356: 
        !           357: ; Calculate our error term for y = 0.
        !           358: ;
        !           359: ; NOTE: Since this routine is used only for lines that are unclipped, we
        !           360: ;       are guaranteed by our screen size that the values will be far less
        !           361: ;       than 32 bits in significance, and so we don't worry about overflow.
        !           362: ;       If this is used for clipped lines, these multiplies will have to
        !           363: ;       be converted to give 64 bit results, because we can have 36 bits of
        !           364: ;       significance!
        !           365: 
        !           366:         lea     edi,[eax + 8]           ;edi = M0 + 8
        !           367:         mov     esi,edx
        !           368:         imul    esi,edi                 ;esi = dN * (M0 + 8)
        !           369:         mov     edi,ecx
        !           370: 
        !           371: ; We have to special case when N0 is 0 -- we know y0 will be zero.
        !           372: ; So we jump ahead a bit to a place where 'ebx' is assumed to contain
        !           373: ; y0 -- and it just so happens 'ebx' is zero in this case:
        !           374: 
        !           375:         and     ebx,F - 1
        !           376:         jz      short @f
        !           377:         imul    edi,ebx                 ;edi = dM * N0
        !           378:         sub     esi,edi
        !           379: 
        !           380: ; Calculate the x-coordinate of the first pixel:
        !           381: 
        !           382:     if (flags AND ROUND_Y_DOWN)
        !           383:         cmp     eax,1
        !           384:         sbb     eax,8                   ;M0 -= 8
        !           385:     else
        !           386:         sub     eax,8                   ;M0 -= 8
        !           387:     endif
        !           388:         sbb     edi,edi
        !           389:         xor     eax,edi
        !           390:         sub     eax,edi                 ;M0 = ABS(M0)
        !           391:         cmp     ebx,eax
        !           392:         sbb     ebx,ebx
        !           393:         not     ebx                     ;ebx = -y0
        !           394: 
        !           395: ; Now adjust the error term accordingly:
        !           396: 
        !           397: @@:
        !           398:     if (flags AND ROUND_X_DOWN)
        !           399:         dec     esi
        !           400:     endif
        !           401:         sar     esi,FLOG2               ;esi = floor((M0 + 8) dN - N0 dM] / 16)
        !           402: 
        !           403:         mov     eax,[esp].sf_ptlOrg.ptl_x
        !           404:         mov     edi,[esp].sf_ptlOrg.ptl_y
        !           405: 
        !           406:         sub     edi,ebx                 ;edi = ptlOrg.ptl_y + y0
        !           407: 
        !           408:         and     ebx,ecx
        !           409:         add     ebx,esi
        !           410:         sub     ebx,edx                 ;ebx = dM * x0 + initial error - dN
        !           411:         jl      short @f                ;if the error term >= 0, we have to
        !           412:         sub     ebx,edx                 ; add 1 to the x position and subtract
        !           413:         inc     eax                     ; dN off again
        !           414: @@:
        !           415: 
        !           416: endm
        !           417: 
        !           418: ;---------------------------Public-Routine------------------------------;
        !           419: ; vFastLine(ppdev, ppo, lNextScan, iColor)
        !           420: ;
        !           421: ; Draws fast lines.  Or at least attempts to.
        !           422: ;
        !           423: ; Input:
        !           424: ;
        !           425: ;    ppdev     - PDEV pointer
        !           426: ;    ppo       - path
        !           427: ;    lNextScan - delta to start of next scan (same as ppdev->lNextScan)
        !           428: ;    iColor    - color (least significant byte must be the same as the next
        !           429: ;                least signficant byte, so that we can do words writes)
        !           430: ;
        !           431: ;-----------------------------------------------------------------------;
        !           432: 
        !           433: ; NOTE: Don't go changing parameters without also changing STACK_FRAME!
        !           434: 
        !           435: cProc vFastLine,16,<     \
        !           436:     uses esi edi ebx,    \
        !           437:     ebp_ppdev:     ptr,  \
        !           438:     ebp_ppo:       ptr,  \
        !           439:     ebp_lNextScan: ptr,  \
        !           440:     ebp_iColor:    dword >
        !           441: 
        !           442: ; Leave room for our stack frame.
        !           443: ;
        !           444: ; NOTE: Don't add local variables here -- you can't reference them with
        !           445: ;       ebp anyway!  Add them to the STACK_FRAME structure.
        !           446: 
        !           447:     local aj[(size STACK_FRAME) - 4 * (STATE_MEM_SIZE + PROC_MEM_SIZE)]: byte
        !           448: 
        !           449: ; We save 'ebp' on the stack (note that STACK_FRAME accounts for this push):
        !           450: 
        !           451:         push    ebp
        !           452: 
        !           453: ; Now get some path stuff:
        !           454: 
        !           455: next_record:
        !           456: 
        !           457:         mov     esi,[esp].sf_ppo
        !           458:         lea     eax,[esp].sf_pd
        !           459:         cCall   PATHOBJ_bEnum,<esi,eax>
        !           460:         mov     [esp].sf_bMore,eax      ;save away return code for later
        !           461: 
        !           462:         mov     eax,[esp].sf_pd.pd_count;if 0 points in record, get outta here
        !           463:         or      eax,eax
        !           464:         jz      check_for_closefigure
        !           465: 
        !           466:         lea     edi,[8 * eax - 8]
        !           467:         add     edi,[esp].sf_pd.pd_pptfx
        !           468:         mov     [esp].sf_pptfxEnd,edi   ;points to last point in record
        !           469: 
        !           470:         mov     ebx,[esp].sf_pd.pd_flags
        !           471:         test    ebx,PD_BEGINSUBPATH
        !           472:         jz      short continue_subpath
        !           473: 
        !           474: ; Handle a new sub-path:
        !           475: 
        !           476:         mov     esi,[esp].sf_pd.pd_pptfx
        !           477:         add     esi,8
        !           478:         mov     [esp].sf_pptfx,esi
        !           479: 
        !           480:         mov     ecx,[edi].ptl_x         ;remember last point in case we have
        !           481:         mov     edx,[edi].ptl_y         ; to continue to another record
        !           482:         mov     [esp].sf_ptfxLast.ptl_x,ecx
        !           483:         mov     [esp].sf_ptfxLast.ptl_y,edx
        !           484: 
        !           485:         mov     eax,[esi - 8].ptl_x     ;load up current start and end point
        !           486:         mov     ebx,[esi - 8].ptl_y
        !           487:         mov     ecx,[esi].ptl_x
        !           488:         mov     edx,[esi].ptl_y
        !           489:         mov     [esp].sf_ptfxStartFigure.ptl_x,eax
        !           490:         mov     [esp].sf_ptfxStartFigure.ptl_y,ebx
        !           491: 
        !           492:         cmp     esi,[esp].sf_pptfxEnd   ;we have to be careful when the only
        !           493:                                         ; point in the record is the start-
        !           494:                                         ; figure point (pretty rare)
        !           495:         jbe     new_line
        !           496:         jmp     short next_record
        !           497: 
        !           498: continue_subpath:
        !           499: 
        !           500: ; This record continues the path:
        !           501: 
        !           502:         mov     esi,[esp].sf_pd.pd_pptfx
        !           503:         mov     eax,[esp].sf_ptfxLast.ptl_x ;load up current start point
        !           504:         mov     ebx,[esp].sf_ptfxLast.ptl_y
        !           505: 
        !           506:         mov     ecx,[edi].ptl_x         ;remember last point in case we have
        !           507:         mov     edx,[edi].ptl_y         ; to continue to another record
        !           508:         mov     [esp].sf_ptfxLast.ptl_x,ecx
        !           509:         mov     [esp].sf_ptfxLast.ptl_y,edx
        !           510: 
        !           511:         mov     ecx,[esi].ptl_x         ;load up current end point
        !           512:         mov     edx,[esi].ptl_y
        !           513:         mov     [esp].sf_pptfx,esi
        !           514:         jmp     short new_line
        !           515: 
        !           516: ;/////////////////////////////////////////////////////////////////////
        !           517: ;// Next Line Stuff
        !           518: ;/////////////////////////////////////////////////////////////////////
        !           519: 
        !           520: handle_closefigure:
        !           521:         mov     [esp].sf_pd.pd_flags,0
        !           522:         mov     eax,[esp].sf_ptfxLast.ptl_x
        !           523:         mov     ebx,[esp].sf_ptfxLast.ptl_y
        !           524:         mov     ecx,[esp].sf_ptfxStartFigure.ptl_x
        !           525:         mov     edx,[esp].sf_ptfxStartFigure.ptl_y
        !           526:         jmp     new_line
        !           527: 
        !           528: ; Before getting the next path record, see if we have to do a closefigure:
        !           529: 
        !           530: check_for_closefigure:
        !           531:         test    [esp].sf_pd.pd_flags,PD_CLOSEFIGURE
        !           532:         jnz     handle_closefigure
        !           533:         mov     ecx,[esp].sf_bMore
        !           534:         or      ecx,ecx
        !           535:         jnz     next_record
        !           536: 
        !           537: all_done:
        !           538: 
        !           539:         pop     ebp
        !           540:         cRet    vFastLine
        !           541: 
        !           542:         public  next_line
        !           543: next_line:
        !           544:         mov     esi,[esp].sf_pptfx
        !           545:         cmp     esi,[esp].sf_pptfxEnd
        !           546:         jae     short check_for_closefigure
        !           547: 
        !           548:         mov     eax,[esi].ptl_x
        !           549:         mov     ebx,[esi].ptl_y
        !           550:         mov     ecx,[esi+8].ptl_x
        !           551:         mov     edx,[esi+8].ptl_y
        !           552:         add     esi,8
        !           553:         mov     [esp].sf_pptfx,esi
        !           554: 
        !           555: ;/////////////////////////////////////////////////////////////////////
        !           556: ;// Main Loop
        !           557: ;/////////////////////////////////////////////////////////////////////
        !           558: 
        !           559:         public  new_line
        !           560: new_line:
        !           561: 
        !           562: ; Octants are numbered as follows:
        !           563: ;
        !           564: ;        \ 5 | 6 /
        !           565: ;         \  |  /
        !           566: ;        4 \ | / 7
        !           567: ;           \ /
        !           568: ;       -----+-----
        !           569: ;           /|\
        !           570: ;        3 / | \ 0
        !           571: ;         /  |  \
        !           572: ;        / 2 | 1 \
        !           573: ;
        !           574: 
        !           575: ; eax = M0
        !           576: ; ebx = N0
        !           577: ; ecx = M1 (dM)
        !           578: ; edx = N1 (dN)
        !           579: 
        !           580:         sub     ecx,eax
        !           581:         jl      octants_2_3_4_5
        !           582:         sub     edx,ebx
        !           583:         jl      octants_6_7
        !           584:         cmp     ecx,edx
        !           585:         jl      octant_1
        !           586: 
        !           587: ;/////////////////////////////////////////////////////////////////////
        !           588: ;// Octant 0
        !           589: ;/////////////////////////////////////////////////////////////////////
        !           590: 
        !           591:         public  octant_0
        !           592: octant_0:
        !           593:         mov     esi,[esp].sf_lNextScan
        !           594:         mov     [esp].sf_lDelta,esi     ;we're going down
        !           595:         mov     [esp].sf_pfnNextBank,offset bank_x_major_next_lower
        !           596: 
        !           597:         mov     esi,ecx
        !           598:         or      esi,edx
        !           599:         jz      next_line               ;we do an early check here for
        !           600:                                         ; lines that start and end on the
        !           601:                                         ; same GIQ point, because those
        !           602:                                         ; occur surprisingly often.
        !           603:         or      esi,eax
        !           604:         or      esi,ebx
        !           605:         and     esi,F - 1
        !           606:         jnz     oct_0_non_integer
        !           607: 
        !           608:         or      edx,edx
        !           609:         jz      do_horizontal_line
        !           610: 
        !           611:         mov     esi,[esp].sf_ppdev
        !           612:         sar     eax,FLOG2               ;x0
        !           613:         sar     ebx,FLOG2               ;y0
        !           614: 
        !           615:         cmp     ebx,[esi].pdev_rcl1WindowClip.yTop
        !           616:         jl      short oct_0_map_in_bank
        !           617: 
        !           618:         cmp     ebx,[esi].pdev_rcl1WindowClip.yBottom
        !           619:         jl      short oct_0_done_bank_map
        !           620: 
        !           621: oct_0_map_in_bank:
        !           622:         push    eax
        !           623:         push    ecx
        !           624:         push    edx
        !           625: 
        !           626: ; ebx, esi, edi and ebp are preserved according to C calling conventions:
        !           627: 
        !           628:         ptrCall <dword ptr [esi].pdev_pfnBankControl>, \
        !           629:                 <esi, ebx, JustifyTop>  ;###
        !           630: 
        !           631:         pop     edx
        !           632:         pop     ecx
        !           633:         pop     eax
        !           634: 
        !           635:         public  oct_0_done_bank_map
        !           636: oct_0_done_bank_map:
        !           637:         mov     edi,[esp].sf_lNextScan
        !           638:         imul    edi,ebx
        !           639:         add     edi,[esi].pdev_pvBitmapStart
        !           640:         add     edi,eax                 ;edi now points to start byte
        !           641: 
        !           642:         mov     ebp,[esi].pdev_rcl1WindowClip.yBottom
        !           643:         sub     ebp,ebx                 ;### ebp = # of scans before end of bank
        !           644: 
        !           645:         mov     esi,ecx
        !           646:         sar     esi,FLOG2               ;esi = # of pixels to lay down
        !           647: 
        !           648:         mov     ebx,-1                  ;### round y = 1/2 *DOWN* in value
        !           649:         sub     ebx,ecx
        !           650:         sar     ebx,1                   ;now have error term
        !           651: 
        !           652:         mov     eax,[esp].sf_iColor
        !           653:         sub     ecx,edx                 ;ecx = dM - dN
        !           654:         cmp     edx,ecx
        !           655:         jg      oct_07b
        !           656: 
        !           657: ;-------------------------------------------------------------------------;
        !           658: ; Left-to-right Lines With ABS(Slope) <= 1/2
        !           659: ; ------------------------------------------
        !           660: ;
        !           661: ; Since the line's slope is less than 1/2, we have only 3 possibilities
        !           662: ; at each pair of pixels:
        !           663: ;
        !           664: ;    Case 1:  o            Case 2:  o o            Case 3:  o o o
        !           665: ;               o o                     o
        !           666: ;
        !           667: ; Case:    err + dN >= 0         err + 2dN >= 0          err + 2dN < 0
        !           668: ; New:     err += 2dN - dM       err += 2dN - dM         err += 2dN
        !           669: ;
        !           670: ; eax = color
        !           671: ; ebx = error term
        !           672: ; ecx = dM - dN
        !           673: ; edx = dN
        !           674: ; esi = # of pixels to lay down
        !           675: ; edi = memory pointer
        !           676: ; ebp = # of scans before end of bank
        !           677: ;-------------------------------------------------------------------------;
        !           678: 
        !           679:         public  oct_07a
        !           680: oct_07a:
        !           681:         test    edi,1
        !           682:         jz      short oct_07a_main      ;start is word aligned
        !           683: 
        !           684: ; Handle unaligned start:
        !           685: 
        !           686:         dec     esi
        !           687:         jl      next_line
        !           688: 
        !           689:         mov     [edi],al
        !           690:         inc     edi
        !           691:         add     ebx,edx                 ;err += dN
        !           692:         jl      short oct_07a_main
        !           693: 
        !           694:         add     edi,[esp].sf_lDelta
        !           695:         dec     ebp                     ;hit a new bank?
        !           696:         jz      short oct_07a_next_bank_3
        !           697: oct_07a_done_bank_3:
        !           698:         sub     ebx,ecx                 ;err += dN - dM
        !           699:         jl      short oct_07a_continue
        !           700: 
        !           701: ;;; Case 1:
        !           702: 
        !           703:         public  oct_07a_case_1
        !           704: oct_07a_case_1:
        !           705:         sub     esi,2
        !           706:         jl      short oct_07a_done
        !           707:         mov     [edi],al
        !           708:         add     edi,[esp].sf_lDelta
        !           709:         add     edi,2
        !           710:         dec     ebp
        !           711:         jz      short oct_07a_next_bank_1
        !           712: oct_07a_done_bank_1:
        !           713:         mov     [edi-1],al
        !           714:         sub     ebx,ecx                 ;err += dN - dM
        !           715:                                         ;;;case 1 is done
        !           716: ;;; Main loop:
        !           717: 
        !           718: oct_07a_main:
        !           719:         add     ebx,edx                 ;err += dN
        !           720:         jge     short oct_07a_case_1
        !           721: oct_07a_continue:
        !           722:         sub     esi,2
        !           723:         jl      short oct_07a_done
        !           724:         mov     [edi],ax
        !           725:         add     edi,2
        !           726:         add     ebx,edx                 ;err += dN
        !           727:         jl      short oct_07a_main      ;;;case 3 is done
        !           728: 
        !           729: ;;; Handle end of case 2:
        !           730: 
        !           731:         add     edi,[esp].sf_lDelta
        !           732:         dec     ebp
        !           733:         jz      short oct_07a_next_bank_2
        !           734: oct_07a_done_bank_2:
        !           735:         sub     ebx,ecx                 ;err += dN - dM
        !           736:         jge     short oct_07a_case_1
        !           737:         jmp     short oct_07a_continue  ;;;case 2 is done
        !           738: 
        !           739: oct_07a_done:
        !           740:         inc     esi                     ;esi = -1 means do another pixel
        !           741:         jnz     next_line
        !           742:         mov     [edi],al
        !           743:         jmp     next_line
        !           744: 
        !           745: oct_07a_next_bank_1:
        !           746:         mov     [esp].sf_pfnReturn,offset oct_07a_done_bank_1
        !           747:         jmp     [esp].sf_pfnNextBank
        !           748: oct_07a_next_bank_2:
        !           749:         mov     [esp].sf_pfnReturn,offset oct_07a_done_bank_2
        !           750:         jmp     [esp].sf_pfnNextBank
        !           751: oct_07a_next_bank_3:
        !           752:         mov     [esp].sf_pfnReturn,offset oct_07a_done_bank_3
        !           753:         jmp     [esp].sf_pfnNextBank
        !           754: 
        !           755: ;-------------------------------------------------------------------------;
        !           756: ; Left-to-right Lines With 1/2 < ABS(Slope) <= 1
        !           757: ; ----------------------------------------------
        !           758: ;
        !           759: ; Since the line's slope is between 1/2 and 1, we have only 3 possibilities
        !           760: ; at each pair of pixels:
        !           761: ;
        !           762: ;   Case 1:  o o          Case 2:  o              Case 3:  o
        !           763: ;                o                   o o                     o
        !           764: ;                                                              o
        !           765: ;
        !           766: ; Case:   err + dN < 0          err + 2dN - dM < 0      err + 2dN - dM >= 0
        !           767: ; New:    err += 2dN - dM       err += 2dN - dM         err += 2dN - 2dM
        !           768: ;
        !           769: ; eax = color
        !           770: ; ebx = error term
        !           771: ; ecx = dM - dN
        !           772: ; edx = dN
        !           773: ; esi = # of pixels to lay down
        !           774: ; edi = memory pointer
        !           775: ; ebp = # of scans before end of bank
        !           776: ;-------------------------------------------------------------------------;
        !           777: 
        !           778:         public  oct_07b
        !           779: oct_07b:
        !           780:         test    edi,1
        !           781:         jz      short oct_07b_main
        !           782: 
        !           783:         dec     esi
        !           784:         jl      next_line
        !           785: 
        !           786:         mov     [edi],al
        !           787:         inc     edi
        !           788:         add     ebx,edx                 ;err += dN
        !           789:         jl      short oct_07b_main
        !           790: 
        !           791:         add     edi,[esp].sf_lDelta
        !           792:         dec     ebp
        !           793:         jz      short oct_07b_next_bank_4
        !           794: oct_07b_done_bank_4:
        !           795:         sub     ebx,ecx                 ;err += dN - dM
        !           796:         jge     short oct_07b_continue
        !           797: 
        !           798:         public  oct_07b_case_1
        !           799: oct_07b_case_1:
        !           800:         sub     esi,2
        !           801:         jl      short oct_07b_done
        !           802:         mov     [edi],ax
        !           803:         add     edi,[esp].sf_lDelta
        !           804:         add     edi,2
        !           805:         dec     ebp
        !           806:         jz      short oct_07b_next_bank_1
        !           807: oct_07b_done_bank_1:
        !           808:         sub     ebx,ecx                 ;err += dN - dM
        !           809:                                         ;;;case 1 is done
        !           810: ;;; Main loop:
        !           811: 
        !           812: oct_07b_main:
        !           813:         add     ebx,edx                 ;err += dN
        !           814:         jl      short oct_07b_case_1
        !           815: oct_07b_continue:
        !           816:         sub     esi,2
        !           817:         jl      short oct_07b_done
        !           818:         mov     [edi],al
        !           819:         add     edi,[esp].sf_lDelta
        !           820:         add     edi,2
        !           821:         dec     ebp
        !           822:         jz      short oct_07b_next_bank_2
        !           823: oct_07b_done_bank_2:
        !           824:         mov     [edi-1],al
        !           825:         sub     ebx,ecx                 ;err += dN - dM
        !           826:         jl      short oct_07b_main      ;;;case 2 is done
        !           827: 
        !           828:         add     edi,[esp].sf_lDelta
        !           829:         dec     ebp
        !           830:         jz      oct_07b_next_bank_3
        !           831: oct_07b_done_bank_3:
        !           832:         sub     ebx,ecx                 ;err += dN - dM
        !           833:         jl      short oct_07b_case_1    ;;;case 3 is done
        !           834:         jmp     short oct_07b_continue
        !           835: 
        !           836: oct_07b_next_bank_4:
        !           837:         mov     [esp].sf_pfnReturn,offset oct_07b_done_bank_4
        !           838:         jmp     [esp].sf_pfnNextBank
        !           839: oct_07b_next_bank_3:
        !           840:         mov     [esp].sf_pfnReturn,offset oct_07b_done_bank_3
        !           841:         jmp     [esp].sf_pfnNextBank
        !           842: oct_07b_next_bank_2:
        !           843:         mov     [esp].sf_pfnReturn,offset oct_07b_done_bank_2
        !           844:         jmp     [esp].sf_pfnNextBank
        !           845: oct_07b_next_bank_1:
        !           846:         mov     [esp].sf_pfnReturn,offset oct_07b_done_bank_1
        !           847:         jmp     [esp].sf_pfnNextBank
        !           848: 
        !           849: oct_07b_done:
        !           850:         inc     esi
        !           851:         jnz     next_line               ;esi = -1 means do another pixel
        !           852:         mov     [edi],al
        !           853:         jmp     next_line
        !           854: 
        !           855: ;-------------------------------------------------------------------------;
        !           856: 
        !           857:         public  oct_0_non_integer
        !           858: oct_0_non_integer:
        !           859:         cmp     ecx,edx
        !           860:         je      oct_0_slope_one         ;have a special case rounding rule for
        !           861:                                         ; 45 degree lines (which only affects
        !           862:                                         ; non-integer lines)
        !           863: 
        !           864:         GIQ     ROUND_X_AND_Y_DOWN      ;### round x=1/2, y=1/2 down in value
        !           865: 
        !           866:         or      edx,edx
        !           867:         jz      do_non_integer_horizontal_line
        !           868: 
        !           869: oct_0_common:
        !           870:         mov     esi,[esp].sf_ppdev
        !           871:         cmp     edi,[esi].pdev_rcl1WindowClip.yTop
        !           872:         jl      short oct_0_nonint_map_in_bank
        !           873: 
        !           874:         cmp     edi,[esi].pdev_rcl1WindowClip.yBottom
        !           875:         jl      short oct_0_nonint_done_bank_map
        !           876: 
        !           877: oct_0_nonint_map_in_bank:
        !           878:         push    eax
        !           879:         push    ecx
        !           880:         push    edx
        !           881: 
        !           882:         ptrCall <dword ptr [esi].pdev_pfnBankControl>, \
        !           883:                 <esi, edi, JustifyTop>  ;###
        !           884: 
        !           885:         pop     edx
        !           886:         pop     ecx
        !           887:         pop     eax
        !           888: 
        !           889: oct_0_nonint_done_bank_map:
        !           890:         mov     ebp,[esi].pdev_rcl1WindowClip.yBottom
        !           891:         sub     ebp,edi                 ;### ebp = # scans before end of bank
        !           892: 
        !           893:         imul    edi,[esp].sf_lNextScan  ;
        !           894:         add     edi,[esi].pdev_pvBitmapStart
        !           895:         add     edi,eax                 ;edi now points to start byte
        !           896: 
        !           897:         mov     esi,[esp].sf_x1
        !           898:         sub     esi,eax                 ;esi = # pixels to lay down
        !           899: 
        !           900:         mov     eax,[esp].sf_iColor
        !           901: 
        !           902:         sub     ecx,edx                 ;ecx = dM - dN
        !           903:         cmp     edx,ecx
        !           904:         jg      oct_07b
        !           905:         jmp     oct_07a
        !           906: 
        !           907: ;-------------------------------------------------------------------;
        !           908: ; 45 degree lines have a special rounding rule: when the line
        !           909: ; runs exactly half way between to pixels, the upper or right pel
        !           910: ; is illuminated.  This translates into x=1/2 rounding up, and
        !           911: ; y=1/2 rounding down in value:
        !           912: 
        !           913:         public  oct_0_slope_one
        !           914: oct_0_slope_one:
        !           915:         GIQ     ROUND_Y_DOWN_SLOPE_ONE  ;round y=1/2 down in value
        !           916:         jmp     oct_0_common
        !           917: 
        !           918: ;/////////////////////////////////////////////////////////////////////
        !           919: ;// Octant 1
        !           920: ;/////////////////////////////////////////////////////////////////////
        !           921: 
        !           922:         public  octant_1
        !           923: octant_1:
        !           924:         mov     [esp].sf_pfnNextBank,offset bank_y_major_next_lower
        !           925: 
        !           926:         mov     esi,eax
        !           927:         or      esi,ebx
        !           928:         or      esi,ecx
        !           929:         or      esi,edx
        !           930:         and     esi,F - 1
        !           931:         jnz     oct_1_non_integer
        !           932: 
        !           933:         mov     esi,[esp].sf_ppdev
        !           934:         sar     eax,FLOG2               ;x0
        !           935:         sar     ebx,FLOG2               ;y0
        !           936: 
        !           937:         cmp     ebx,[esi].pdev_rcl1WindowClip.yTop
        !           938:         jl      short oct_1_map_in_bank
        !           939: 
        !           940:         cmp     ebx,[esi].pdev_rcl1WindowClip.yBottom
        !           941:         jl      short oct_1_done_bank_map
        !           942: 
        !           943: oct_1_map_in_bank:
        !           944:         push    eax
        !           945:         push    ecx
        !           946:         push    edx
        !           947: 
        !           948: ; ebx, esi, edi and ebp are preserved according to C calling conventions:
        !           949: 
        !           950:         ptrCall <dword ptr [esi].pdev_pfnBankControl>, \
        !           951:                 <esi, ebx, JustifyTop>  ;###
        !           952: 
        !           953:         pop     edx
        !           954:         pop     ecx
        !           955:         pop     eax
        !           956: 
        !           957:         public  oct_1_done_bank_map
        !           958: oct_1_done_bank_map:
        !           959:         mov     edi,[esp].sf_lNextScan
        !           960:         imul    edi,ebx
        !           961:         add     edi,[esi].pdev_pvBitmapStart
        !           962:         add     edi,eax                 ;edi now points to start byte
        !           963: 
        !           964:         mov     ebp,[esi].pdev_rcl1WindowClip.yBottom
        !           965:         sub     ebp,ebx                 ;### ebp = # of scans before end of bank
        !           966: 
        !           967:         mov     esi,edx
        !           968:         sar     esi,FLOG2               ;esi = # of pixels to lay down
        !           969: 
        !           970:         sub     esi,ebp
        !           971:         sbb     ebx,ebx
        !           972:         and     ebx,esi
        !           973:         add     ebp,ebx                 ;ebp = # of pels in this bank
        !           974: 
        !           975:         mov     [esp].sf_cAfterThisBank,esi
        !           976:         mov     esi,[esp].sf_lNextScan
        !           977: 
        !           978:         mov     ebx,-1                  ;### round x = 1/2 *DOWN* in value
        !           979:         sub     ebx,edx
        !           980:         sar     ebx,1                   ;now have error term
        !           981: 
        !           982:         mov     eax,[esp].sf_iColor
        !           983: 
        !           984: ;-------------------------------------------------------------------------;
        !           985: ; Left-to-right Lines With Abs(Slope) > 1/2
        !           986: ; -----------------------------------------
        !           987: ;
        !           988: ; eax = color
        !           989: ; ebx = error term
        !           990: ; ecx = dM
        !           991: ; edx = dN
        !           992: ; esi = delta
        !           993: ; edi = memory pointer
        !           994: ; ebp = # of scans before end of bank
        !           995: ;-------------------------------------------------------------------------;
        !           996: 
        !           997: oct_1_main_loop:
        !           998:         dec     ebp
        !           999:         jl      short oct_1_see_if_more
        !          1000:         mov     [edi],al
        !          1001:         add     edi,esi
        !          1002:         add     ebx,ecx                 ;err += dM
        !          1003:         jl      short oct_1_main_loop
        !          1004: 
        !          1005:         inc     edi                     ;one to right
        !          1006:         sub     ebx,edx                 ;err -= dN
        !          1007: 
        !          1008: ; Unroll a bit:
        !          1009: 
        !          1010:         dec     ebp
        !          1011:         jl      short oct_1_see_if_more
        !          1012:         mov     [edi],al
        !          1013:         add     edi,esi
        !          1014:         add     ebx,ecx                 ;err += dM
        !          1015:         jl      short oct_1_main_loop
        !          1016: 
        !          1017:         inc     edi                     ;one to right
        !          1018:         sub     ebx,edx                 ;err -= dN
        !          1019:         jmp     short oct_1_main_loop
        !          1020: 
        !          1021:         public  oct_1_see_if_more
        !          1022: oct_1_see_if_more:
        !          1023:         mov     eax,[esp].sf_cAfterThisBank
        !          1024:         cmp     eax,0
        !          1025:         jle     next_line
        !          1026: 
        !          1027:         mov     [esp].sf_pfnReturn,offset oct_1_main_loop
        !          1028:         jmp     [esp].sf_pfnNextBank
        !          1029: 
        !          1030:         public  oct_1_non_integer
        !          1031: oct_1_non_integer:
        !          1032:         GIQR    ROUND_X_AND_Y_DOWN      ;### round x=1/2, y=1/2 down in value
        !          1033: 
        !          1034:         mov     esi,[esp].sf_ppdev
        !          1035:         cmp     edi,[esi].pdev_rcl1WindowClip.yTop
        !          1036:         jl      short oct_1_nonint_map_in_bank
        !          1037: 
        !          1038:         cmp     edi,[esi].pdev_rcl1WindowClip.yBottom
        !          1039:         jl      short oct_1_nonint_done_bank_map
        !          1040: 
        !          1041: oct_1_nonint_map_in_bank:
        !          1042:         push    eax
        !          1043:         push    ecx
        !          1044:         push    edx
        !          1045: 
        !          1046:         ptrCall <dword ptr [esi].pdev_pfnBankControl>, \
        !          1047:                 <esi, edi, JustifyTop>  ;###
        !          1048: 
        !          1049:         pop     edx
        !          1050:         pop     ecx
        !          1051:         pop     eax
        !          1052: 
        !          1053: oct_1_nonint_done_bank_map:
        !          1054:         mov     [esp].sf_y0,edi
        !          1055:         imul    edi,[esp].sf_lNextScan
        !          1056:         add     edi,[esi].pdev_pvBitmapStart
        !          1057:         add     edi,eax                 ;edi points to start byte
        !          1058: 
        !          1059:         mov     ebp,[esi].pdev_rcl1WindowClip.yBottom
        !          1060:         mov     esi,[esp].sf_y1
        !          1061:         sub     esi,ebp
        !          1062: 
        !          1063:         sbb     eax,eax
        !          1064:         and     eax,esi
        !          1065:         add     ebp,eax
        !          1066:         sub     ebp,[esp].sf_y0         ;ebp = min(y1,
        !          1067:                                         ; ppdev->rcl1WindowClip.yBottom) - y0
        !          1068:                                         ; (# of pixels to lay down)
        !          1069: 
        !          1070:         mov     [esp].sf_cAfterThisBank,esi
        !          1071: 
        !          1072:         mov     esi,[esp].sf_lNextScan
        !          1073:         mov     eax,[esp].sf_iColor
        !          1074: 
        !          1075:         jmp     oct_1_main_loop
        !          1076: 
        !          1077: ;/////////////////////////////////////////////////////////////////////
        !          1078: ;// Octant 3
        !          1079: ;/////////////////////////////////////////////////////////////////////
        !          1080: 
        !          1081: octants_2_3_4_5:
        !          1082:         neg     ecx                     ;dM = -dM (now positive)
        !          1083:         neg     eax                     ;M0 = -M0
        !          1084:         sub     edx,ebx
        !          1085:         jl      octants_4_5
        !          1086:         cmp     ecx,edx
        !          1087:         jl      octant_2
        !          1088: 
        !          1089:         public  octant_3
        !          1090: octant_3:
        !          1091:         mov     esi,[esp].sf_lNextScan
        !          1092:         mov     [esp].sf_lDelta,esi     ;we're going down
        !          1093:         mov     [esp].sf_pfnNextBank,offset bank_x_major_next_lower
        !          1094: 
        !          1095:         mov     esi,eax
        !          1096:         or      esi,ebx
        !          1097:         or      esi,ecx
        !          1098:         or      esi,edx
        !          1099:         and     esi,F - 1
        !          1100:         jnz     oct_3_non_integer
        !          1101: 
        !          1102:         or      edx,edx
        !          1103:         jz      flip_and_do_horizontal_line
        !          1104: 
        !          1105:         mov     esi,[esp].sf_ppdev
        !          1106: 
        !          1107:         neg     eax                     ;### untransform M0
        !          1108: 
        !          1109:         sar     eax,FLOG2               ;x0
        !          1110:         sar     ebx,FLOG2               ;y0
        !          1111: 
        !          1112:         cmp     ebx,[esi].pdev_rcl1WindowClip.yTop
        !          1113:         jl      short oct_3_map_in_bank
        !          1114: 
        !          1115:         cmp     ebx,[esi].pdev_rcl1WindowClip.yBottom
        !          1116:         jl      short oct_3_done_bank_map
        !          1117: 
        !          1118: oct_3_map_in_bank:
        !          1119:         push    eax
        !          1120:         push    ecx
        !          1121:         push    edx
        !          1122: 
        !          1123: ; ebx, esi, edi and esi are preserved according to C calling conventions:
        !          1124: 
        !          1125:         ptrCall <dword ptr [esi].pdev_pfnBankControl>, \
        !          1126:                 <esi, ebx, JustifyTop>  ;###
        !          1127: 
        !          1128:         pop     edx
        !          1129:         pop     ecx
        !          1130:         pop     eax
        !          1131: 
        !          1132:         public  oct_3_done_bank_map
        !          1133: oct_3_done_bank_map:
        !          1134:         mov     edi,[esp].sf_lNextScan
        !          1135:         imul    edi,ebx
        !          1136:         add     edi,[esi].pdev_pvBitmapStart
        !          1137:         add     edi,eax                 ;edi now points to start byte
        !          1138: 
        !          1139:         mov     ebp,[esi].pdev_rcl1WindowClip.yBottom
        !          1140:         sub     ebp,ebx                 ;### ebp = # of scans before end of bank
        !          1141: 
        !          1142:         mov     esi,ecx
        !          1143:         sar     esi,FLOG2               ;esi = # of pixels to lay down
        !          1144: 
        !          1145:         mov     ebx,-1                  ;### round y = 1/2 *DOWN* in value
        !          1146:         sub     ebx,ecx
        !          1147:         sar     ebx,1                   ;now have error term
        !          1148: 
        !          1149:         mov     eax,[esp].sf_iColor
        !          1150:         sub     ecx,edx                 ;ecx = dM - dN
        !          1151:         cmp     edx,ecx
        !          1152:         jg      oct_34b
        !          1153: 
        !          1154: ;-------------------------------------------------------------------------;
        !          1155: ; Right-to-left Lines With ABS(Slope) <= 1/2
        !          1156: ; ------------------------------------------
        !          1157: ;
        !          1158: ; Since the line's slope is less than 1/2, we have only 3 possibilities
        !          1159: ; at each pair of pixels:
        !          1160: ;
        !          1161: ;    Case 1:  o            Case 2:  o o            Case 3:  o o o
        !          1162: ;               o o                     o
        !          1163: ;
        !          1164: ; Case:    err + dN >= 0         err + 2dN >= 0          err + 2dN < 0
        !          1165: ; New:     err += 2dN - dM       err += 2dN - dM         err += 2dN
        !          1166: ;
        !          1167: ; eax = color
        !          1168: ; ebx = error term
        !          1169: ; ecx = dM - dN
        !          1170: ; edx = dN
        !          1171: ; esi = # of pixels to lay down
        !          1172: ; edi = memory pointer
        !          1173: ; ebp = # of scans before end of bank
        !          1174: ;-------------------------------------------------------------------------;
        !          1175: 
        !          1176: oct_34a:
        !          1177:         test    edi,1
        !          1178:         jnz     short oct_34a_main      ;### start is word aligned
        !          1179: 
        !          1180: ; Handle unaligned start:
        !          1181: 
        !          1182:         dec     esi
        !          1183:         jl      next_line
        !          1184: 
        !          1185:         mov     [edi],al
        !          1186:         dec     edi                     ;###
        !          1187:         add     ebx,edx                 ;err += dN
        !          1188:         jl      short oct_34a_main
        !          1189: 
        !          1190:         add     edi,[esp].sf_lDelta
        !          1191:         dec     ebp                     ;hit a new bank?
        !          1192:         jz      short oct_34a_next_bank_3
        !          1193: oct_34a_done_bank_3:
        !          1194:         sub     ebx,ecx                 ;err += dN - dM
        !          1195:         jl      short oct_34a_continue
        !          1196: 
        !          1197: ;;; Case 1:
        !          1198: 
        !          1199:         public  oct_34a_case_1
        !          1200: oct_34a_case_1:
        !          1201:         sub     esi,2
        !          1202:         jl      short oct_34a_done
        !          1203:         mov     [edi],al
        !          1204:         add     edi,[esp].sf_lDelta
        !          1205:         sub     edi,2                   ;###
        !          1206:         dec     ebp
        !          1207:         jz      short oct_34a_next_bank_1
        !          1208: oct_34a_done_bank_1:
        !          1209:         mov     [edi+1],al
        !          1210:         sub     ebx,ecx                 ;err += dN - dM
        !          1211:                                         ;;;case 1 is done
        !          1212: ;;; Main loop:
        !          1213: 
        !          1214: oct_34a_main:
        !          1215:         add     ebx,edx                 ;err += dN
        !          1216:         jge     short oct_34a_case_1
        !          1217: oct_34a_continue:
        !          1218:         sub     esi,2
        !          1219:         jl      short oct_34a_done
        !          1220:         mov     [edi-1],ax              ;###
        !          1221:         sub     edi,2                   ;###
        !          1222:         add     ebx,edx                 ;err += dN
        !          1223:         jl      short oct_34a_main      ;;;case 3 is done
        !          1224: 
        !          1225: ;;; Handle end of case 2:
        !          1226: 
        !          1227:         add     edi,[esp].sf_lDelta
        !          1228:         dec     ebp
        !          1229:         jz      short oct_34a_next_bank_2
        !          1230: oct_34a_done_bank_2:
        !          1231:         sub     ebx,ecx                 ;err += dN - dM
        !          1232:         jge     short oct_34a_case_1
        !          1233:         jmp     short oct_34a_continue  ;;;case 2 is done
        !          1234: 
        !          1235: oct_34a_done:
        !          1236:         inc     esi                     ;esi = -1 means do another pixel
        !          1237:         jnz     next_line
        !          1238:         mov     [edi],al
        !          1239:         jmp     next_line
        !          1240: 
        !          1241: oct_34a_next_bank_1:
        !          1242:         mov     [esp].sf_pfnReturn,offset oct_34a_done_bank_1
        !          1243:         jmp     [esp].sf_pfnNextBank
        !          1244: oct_34a_next_bank_2:
        !          1245:         mov     [esp].sf_pfnReturn,offset oct_34a_done_bank_2
        !          1246:         jmp     [esp].sf_pfnNextBank
        !          1247: oct_34a_next_bank_3:
        !          1248:         mov     [esp].sf_pfnReturn,offset oct_34a_done_bank_3
        !          1249:         jmp     [esp].sf_pfnNextBank
        !          1250: 
        !          1251: ;-------------------------------------------------------------------------;
        !          1252: ; Right-to-left Lines With 1/2 < ABS(Slope) <= 1
        !          1253: ; ----------------------------------------------
        !          1254: ;
        !          1255: ; Since the line's slope is between 1/2 and 1, we have only 3 possibilities
        !          1256: ; at each pair of pixels:
        !          1257: ;
        !          1258: ;   Case 1:  o o          Case 2:  o              Case 3:  o
        !          1259: ;                o                   o o                     o
        !          1260: ;                                                              o
        !          1261: ;
        !          1262: ; Case:   err + dN < 0          err + 2dN - dM < 0      err + 2dN - dM >= 0
        !          1263: ; New:    err += 2dN - dM       err += 2dN - dM         err += 2dN - 2dM
        !          1264: ;
        !          1265: ; eax = color
        !          1266: ; ebx = error term
        !          1267: ; ecx = dM - dN
        !          1268: ; edx = dN
        !          1269: ; esi = # of pixels to lay down
        !          1270: ; edi = memory pointer
        !          1271: ; ebp = # of scans before end of bank
        !          1272: ;-------------------------------------------------------------------------;
        !          1273: 
        !          1274:         public  oct_34b
        !          1275: oct_34b:
        !          1276:         test    edi,1
        !          1277:         jnz     short oct_34b_main      ;###
        !          1278: 
        !          1279:         dec     esi
        !          1280:         jl      next_line
        !          1281: 
        !          1282:         mov     [edi],al
        !          1283:         dec     edi                     ;###
        !          1284:         add     ebx,edx                 ;err += dN
        !          1285:         jl      short oct_34b_main
        !          1286: 
        !          1287:         add     edi,[esp].sf_lDelta
        !          1288:         dec     ebp
        !          1289:         jz      short oct_34b_next_bank_4
        !          1290: oct_34b_done_bank_4:
        !          1291:         sub     ebx,ecx                 ;err += dN - dM
        !          1292:         jge     short oct_34b_continue
        !          1293: 
        !          1294:         public  oct_34b_case_1
        !          1295: oct_34b_case_1:
        !          1296:         sub     esi,2
        !          1297:         jl      short oct_34b_done
        !          1298:         mov     [edi-1],ax              ;###
        !          1299:         add     edi,[esp].sf_lDelta
        !          1300:         sub     edi,2                   ;###
        !          1301:         dec     ebp
        !          1302:         jz      short oct_34b_next_bank_1
        !          1303: oct_34b_done_bank_1:
        !          1304:         sub     ebx,ecx                 ;err += dN - dM
        !          1305:                                         ;;;case 1 is done
        !          1306: ;;; Main loop:
        !          1307: 
        !          1308: oct_34b_main:
        !          1309:         add     ebx,edx                 ;err += dN
        !          1310:         jl      short oct_34b_case_1
        !          1311: oct_34b_continue:
        !          1312:         sub     esi,2
        !          1313:         jl      short oct_34b_done
        !          1314:         mov     [edi],al
        !          1315:         add     edi,[esp].sf_lDelta
        !          1316:         sub     edi,2                   ;###
        !          1317:         dec     ebp
        !          1318:         jz      short oct_34b_next_bank_2
        !          1319: oct_34b_done_bank_2:
        !          1320:         mov     [edi+1],al
        !          1321:         sub     ebx,ecx                 ;err += dN - dM
        !          1322:         jl      short oct_34b_main      ;;;case 2 is done
        !          1323: 
        !          1324:         add     edi,[esp].sf_lDelta
        !          1325:         dec     ebp
        !          1326:         jz      oct_34b_next_bank_3
        !          1327: oct_34b_done_bank_3:
        !          1328:         sub     ebx,ecx                 ;err += dN - dM
        !          1329:         jl      short oct_34b_case_1    ;;;case 3 is done
        !          1330:         jmp     short oct_34b_continue
        !          1331: 
        !          1332: oct_34b_next_bank_4:
        !          1333:         mov     [esp].sf_pfnReturn,offset oct_34b_done_bank_4
        !          1334:         jmp     [esp].sf_pfnNextBank
        !          1335: oct_34b_next_bank_3:
        !          1336:         mov     [esp].sf_pfnReturn,offset oct_34b_done_bank_3
        !          1337:         jmp     [esp].sf_pfnNextBank
        !          1338: oct_34b_next_bank_2:
        !          1339:         mov     [esp].sf_pfnReturn,offset oct_34b_done_bank_2
        !          1340:         jmp     [esp].sf_pfnNextBank
        !          1341: oct_34b_next_bank_1:
        !          1342:         mov     [esp].sf_pfnReturn,offset oct_34b_done_bank_1
        !          1343:         jmp     [esp].sf_pfnNextBank
        !          1344: 
        !          1345: oct_34b_done:
        !          1346:         inc     esi
        !          1347:         jnz     next_line               ;esi = -1 means do another pixel
        !          1348:         mov     [edi],al
        !          1349:         jmp     next_line
        !          1350: 
        !          1351: ;-------------------------------------------------------------------------;
        !          1352: 
        !          1353:         public  oct_3_non_integer
        !          1354: oct_3_non_integer:
        !          1355:         GIQ     ROUND_Y_DOWN            ;### round y=1/2 down in value
        !          1356:                                         ;###  (remember that we're flipped
        !          1357:                                         ;###  in 'x')
        !          1358: 
        !          1359:         or      edx,edx
        !          1360:         jz      flip_and_do_non_integer_horizontal_line
        !          1361: 
        !          1362:         mov     esi,[esp].sf_ppdev
        !          1363:         neg     eax                     ;### Untransform x0
        !          1364:         cmp     edi,[esi].pdev_rcl1WindowClip.yTop
        !          1365:         jl      short oct_3_nonint_map_in_bank
        !          1366: 
        !          1367:         cmp     edi,[esi].pdev_rcl1WindowClip.yBottom
        !          1368:         jl      short oct_3_nonint_done_bank_map
        !          1369: 
        !          1370: oct_3_nonint_map_in_bank:
        !          1371:         push    eax
        !          1372:         push    ecx
        !          1373:         push    edx
        !          1374: 
        !          1375:         ptrCall <dword ptr [esi].pdev_pfnBankControl>, \
        !          1376:                 <esi, edi, JustifyTop>  ;###
        !          1377: 
        !          1378:         pop     edx
        !          1379:         pop     ecx
        !          1380:         pop     eax
        !          1381: 
        !          1382: oct_3_nonint_done_bank_map:
        !          1383:         mov     ebp,[esi].pdev_rcl1WindowClip.yBottom
        !          1384:         sub     ebp,edi                 ;### ebp = # scans before end of bank
        !          1385: 
        !          1386:         imul    edi,[esp].sf_lNextScan  ;
        !          1387:         add     edi,[esi].pdev_pvBitmapStart
        !          1388:         add     edi,eax                 ;edi now points to start byte
        !          1389: 
        !          1390:         mov     esi,[esp].sf_x1
        !          1391:         add     esi,eax                 ;### esi = # pixels to lay down
        !          1392: 
        !          1393:         mov     eax,[esp].sf_iColor
        !          1394: 
        !          1395:         sub     ecx,edx                 ;ecx = dM - dN
        !          1396:         cmp     edx,ecx
        !          1397:         jg      oct_34b
        !          1398:         jmp     oct_34a
        !          1399: 
        !          1400: ;/////////////////////////////////////////////////////////////////////
        !          1401: ;// Octant 2
        !          1402: ;/////////////////////////////////////////////////////////////////////
        !          1403: 
        !          1404:         public  octant_2
        !          1405: octant_2:
        !          1406:         mov     [esp].sf_pfnNextBank,offset bank_y_major_next_lower
        !          1407: 
        !          1408:         mov     esi,eax
        !          1409:         or      esi,ebx
        !          1410:         or      esi,ecx
        !          1411:         or      esi,edx
        !          1412:         and     esi,F - 1
        !          1413:         jnz     oct_2_non_integer
        !          1414: 
        !          1415:         neg     eax                     ;### untransform M0
        !          1416: 
        !          1417:         mov     esi,[esp].sf_ppdev
        !          1418:         sar     eax,FLOG2               ;x0
        !          1419:         sar     ebx,FLOG2               ;y0
        !          1420: 
        !          1421:         cmp     ebx,[esi].pdev_rcl1WindowClip.yTop
        !          1422:         jl      short oct_2_map_in_bank
        !          1423: 
        !          1424:         cmp     ebx,[esi].pdev_rcl1WindowClip.yBottom
        !          1425:         jl      short oct_2_done_bank_map
        !          1426: 
        !          1427: oct_2_map_in_bank:
        !          1428:         push    eax
        !          1429:         push    ecx
        !          1430:         push    edx
        !          1431: 
        !          1432: ; ebx, esi, edi and ebp are preserved according to C calling conventions:
        !          1433: 
        !          1434:         ptrCall <dword ptr [esi].pdev_pfnBankControl>, \
        !          1435:                 <esi, ebx, JustifyTop>  ;###
        !          1436: 
        !          1437:         pop     edx
        !          1438:         pop     ecx
        !          1439:         pop     eax
        !          1440: 
        !          1441:         public  oct_2_done_bank_map
        !          1442: oct_2_done_bank_map:
        !          1443:         mov     edi,[esp].sf_lNextScan
        !          1444:         imul    edi,ebx
        !          1445:         add     edi,[esi].pdev_pvBitmapStart
        !          1446:         add     edi,eax                 ;edi now points to start byte
        !          1447: 
        !          1448:         mov     ebp,[esi].pdev_rcl1WindowClip.yBottom
        !          1449:         sub     ebp,ebx                 ;### ebp = # of scans before end of bank
        !          1450: 
        !          1451:         mov     esi,edx
        !          1452:         sar     esi,FLOG2               ;esi = # of pixels to lay down
        !          1453: 
        !          1454:         sub     esi,ebp
        !          1455:         sbb     ebx,ebx
        !          1456:         and     ebx,esi
        !          1457:         add     ebp,ebx                 ;ebp = # of pels in this bank
        !          1458: 
        !          1459:         mov     [esp].sf_cAfterThisBank,esi
        !          1460:         mov     esi,[esp].sf_lNextScan
        !          1461: 
        !          1462:         xor     ebx,ebx                 ;### round x = 1/2 *UP* in value
        !          1463:         sub     ebx,edx
        !          1464:         sar     ebx,1                   ;now have error term
        !          1465: 
        !          1466:         mov     eax,[esp].sf_iColor
        !          1467: 
        !          1468: ;-------------------------------------------------------------------------;
        !          1469: ; Right-to-left Lines With Abs(Slope) > 1/2
        !          1470: ; -----------------------------------------
        !          1471: ;
        !          1472: ; eax = color
        !          1473: ; ebx = error term
        !          1474: ; ecx = dM
        !          1475: ; edx = dN
        !          1476: ; esi = delta
        !          1477: ; edi = memory pointer
        !          1478: ; ebp = # of scans before end of bank
        !          1479: ;-------------------------------------------------------------------------;
        !          1480: 
        !          1481: oct_2_main_loop:
        !          1482:         dec     ebp
        !          1483:         jl      short oct_2_see_if_more
        !          1484:         mov     [edi],al
        !          1485:         add     edi,esi
        !          1486:         add     ebx,ecx                 ;err += dM
        !          1487:         jl      short oct_2_main_loop
        !          1488: 
        !          1489:         dec     edi                     ;one to left
        !          1490:         sub     ebx,edx                 ;err -= dN
        !          1491: 
        !          1492: ; Unroll a bit:
        !          1493: 
        !          1494:         dec     ebp
        !          1495:         jl      short oct_2_see_if_more
        !          1496:         mov     [edi],al
        !          1497:         add     edi,esi
        !          1498:         add     ebx,ecx                 ;err += dM
        !          1499:         jl      short oct_2_main_loop
        !          1500: 
        !          1501:         dec     edi                     ;one to left
        !          1502:         sub     ebx,edx                 ;err -= dN
        !          1503:         jmp     short oct_2_main_loop
        !          1504: 
        !          1505:         public  oct_2_see_if_more
        !          1506: oct_2_see_if_more:
        !          1507:         mov     eax,[esp].sf_cAfterThisBank
        !          1508:         cmp     eax,0
        !          1509:         jle     next_line
        !          1510: 
        !          1511:         mov     [esp].sf_pfnReturn,offset oct_2_main_loop
        !          1512:         jmp     [esp].sf_pfnNextBank
        !          1513: 
        !          1514:         public  oct_2_non_integer
        !          1515: oct_2_non_integer:
        !          1516:         GIQR    ROUND_Y_DOWN            ;### round y=1/2 down in value
        !          1517:                                         ;###  (remember that we're flipped
        !          1518:                                         ;###  in 'x')
        !          1519: 
        !          1520:         mov     esi,[esp].sf_ppdev
        !          1521: 
        !          1522:         neg     eax                     ;### untransform x0
        !          1523: 
        !          1524:         cmp     edi,[esi].pdev_rcl1WindowClip.yTop
        !          1525:         jl      short oct_2_nonint_map_in_bank
        !          1526: 
        !          1527:         cmp     edi,[esi].pdev_rcl1WindowClip.yBottom
        !          1528:         jl      short oct_2_nonint_done_bank_map
        !          1529: 
        !          1530: oct_2_nonint_map_in_bank:
        !          1531:         push    eax
        !          1532:         push    ecx
        !          1533:         push    edx
        !          1534: 
        !          1535:         ptrCall <dword ptr [esi].pdev_pfnBankControl>, \
        !          1536:                 <esi, edi, JustifyTop>  ;###
        !          1537: 
        !          1538:         pop     edx
        !          1539:         pop     ecx
        !          1540:         pop     eax
        !          1541: 
        !          1542: oct_2_nonint_done_bank_map:
        !          1543:         mov     [esp].sf_y0,edi
        !          1544:         imul    edi,[esp].sf_lNextScan
        !          1545:         add     edi,[esi].pdev_pvBitmapStart
        !          1546:         add     edi,eax                 ;edi points to start byte
        !          1547: 
        !          1548:         mov     ebp,[esi].pdev_rcl1WindowClip.yBottom
        !          1549:         mov     esi,[esp].sf_y1
        !          1550:         sub     esi,ebp
        !          1551: 
        !          1552:         sbb     eax,eax
        !          1553:         and     eax,esi
        !          1554:         add     ebp,eax
        !          1555:         sub     ebp,[esp].sf_y0         ;ebp = min(y1,
        !          1556:                                         ; ppdev->rcl1WindowClip.yBottom) - y0
        !          1557:                                         ; (# of pixels to lay down)
        !          1558: 
        !          1559:         mov     [esp].sf_cAfterThisBank,esi
        !          1560: 
        !          1561:         mov     esi,[esp].sf_lNextScan
        !          1562:         mov     eax,[esp].sf_iColor
        !          1563: 
        !          1564:         jmp     oct_2_main_loop
        !          1565: 
        !          1566: ;/////////////////////////////////////////////////////////////////////
        !          1567: ;// Octant 4
        !          1568: ;/////////////////////////////////////////////////////////////////////
        !          1569: 
        !          1570: octants_4_5:
        !          1571:         neg     edx
        !          1572:         neg     ebx
        !          1573:         cmp     ecx,edx
        !          1574:         jl      octant_5
        !          1575: 
        !          1576:         public  octant_4
        !          1577: octant_4:
        !          1578:         mov     esi,[esp].sf_lNextScan
        !          1579:         neg     esi
        !          1580:         mov     [esp].sf_lDelta,esi     ;we're going up
        !          1581:         mov     [esp].sf_pfnNextBank,offset bank_x_major_next_upper
        !          1582: 
        !          1583:         mov     esi,eax
        !          1584:         or      esi,ebx
        !          1585:         or      esi,ecx
        !          1586:         or      esi,edx
        !          1587:         and     esi,F - 1
        !          1588:         jnz     oct_4_non_integer
        !          1589: 
        !          1590:         neg     eax                     ;### untransform x
        !          1591:         neg     ebx                     ;### untransform y
        !          1592: 
        !          1593:         mov     esi,[esp].sf_ppdev
        !          1594:         sar     eax,FLOG2               ;x0
        !          1595:         sar     ebx,FLOG2               ;y0
        !          1596: 
        !          1597:         cmp     ebx,[esi].pdev_rcl1WindowClip.yTop
        !          1598:         jl      short oct_4_map_in_bank
        !          1599: 
        !          1600:         cmp     ebx,[esi].pdev_rcl1WindowClip.yBottom
        !          1601:         jl      short oct_4_done_bank_map
        !          1602: 
        !          1603: oct_4_map_in_bank:
        !          1604:         push    eax
        !          1605:         push    ecx
        !          1606:         push    edx
        !          1607: 
        !          1608: ; ebx, esi, edi and esi are preserved according to C calling conventions:
        !          1609: 
        !          1610:         ptrCall <dword ptr [esi].pdev_pfnBankControl>, \
        !          1611:                 <esi, ebx, JustifyBottom> ;###
        !          1612: 
        !          1613:         pop     edx
        !          1614:         pop     ecx
        !          1615:         pop     eax
        !          1616: 
        !          1617:         public  oct_4_done_bank_map
        !          1618: oct_4_done_bank_map:
        !          1619:         mov     edi,[esp].sf_lNextScan
        !          1620:         imul    edi,ebx
        !          1621:         add     edi,[esi].pdev_pvBitmapStart
        !          1622:         add     edi,eax                 ;edi now points to start byte
        !          1623: 
        !          1624:         mov     ebp,ebx                 ;###
        !          1625:         sub     ebp,[esi].pdev_rcl1WindowClip.yTop
        !          1626:         inc     ebp                     ;### ebp = # scans before end of bank
        !          1627: 
        !          1628:         mov     esi,ecx
        !          1629:         sar     esi,FLOG2               ;esi = # of pixels to lay down
        !          1630: 
        !          1631:         xor     ebx,ebx                 ;### round y = 1/2 *UP* in value
        !          1632:         sub     ebx,ecx
        !          1633:         sar     ebx,1                   ;now have error term
        !          1634: 
        !          1635:         mov     eax,[esp].sf_iColor
        !          1636:         sub     ecx,edx                 ;ecx = dM - dN
        !          1637:         cmp     edx,ecx
        !          1638:         jg      oct_34b
        !          1639:         jmp     oct_34a
        !          1640: 
        !          1641:         public  oct_4_non_integer
        !          1642: oct_4_non_integer:
        !          1643:         cmp     ecx,edx
        !          1644:         je      oct_4_slope_one
        !          1645:         GIQ     0                       ;###
        !          1646:                                         ;###  (remember that we're flipped
        !          1647:                                         ;###  in 'x' and 'y')
        !          1648: 
        !          1649: oct_4_common:
        !          1650:         mov     esi,[esp].sf_ppdev
        !          1651:         neg     edi                     ;### untransform y
        !          1652:         neg     eax                     ;### untransform x
        !          1653: 
        !          1654:         cmp     edi,[esi].pdev_rcl1WindowClip.yTop
        !          1655:         jl      short oct_4_nonint_map_in_bank
        !          1656: 
        !          1657:         cmp     edi,[esi].pdev_rcl1WindowClip.yBottom
        !          1658:         jl      short oct_4_nonint_done_bank_map
        !          1659: 
        !          1660: oct_4_nonint_map_in_bank:
        !          1661:         push    eax
        !          1662:         push    ecx
        !          1663:         push    edx
        !          1664: 
        !          1665:         ptrCall <dword ptr [esi].pdev_pfnBankControl>, \
        !          1666:                 <esi, edi, JustifyBottom>;###
        !          1667: 
        !          1668:         pop     edx
        !          1669:         pop     ecx
        !          1670:         pop     eax
        !          1671: 
        !          1672: oct_4_nonint_done_bank_map:
        !          1673:         mov     ebp,edi                 ;###
        !          1674:         sub     ebp,[esi].pdev_rcl1WindowClip.yTop
        !          1675:         inc     ebp                     ;### esp = # scans before end of bank
        !          1676: 
        !          1677:         imul    edi,[esp].sf_lNextScan
        !          1678:         add     edi,[esi].pdev_pvBitmapStart
        !          1679:         add     edi,eax                 ;edi now points to start byte
        !          1680: 
        !          1681:         mov     esi,[esp].sf_x1
        !          1682:         add     esi,eax                 ;### esi = # pixels to lay down
        !          1683: 
        !          1684:         mov     eax,[esp].sf_iColor
        !          1685: 
        !          1686:         sub     ecx,edx                 ;ecx = dM - dN
        !          1687:         cmp     edx,ecx
        !          1688:         jg      oct_34b
        !          1689:         jmp     oct_34a
        !          1690: 
        !          1691: ;-------------------------------------------------------------------;
        !          1692: ; 45 degree lines have a special rounding rule: when the line
        !          1693: ; runs exactly half way between to pixels, the upper or right pel
        !          1694: ; is illuminated.  This translates into x=1/2 rounding up, and
        !          1695: ; y=1/2 rounding down in value:
        !          1696: 
        !          1697:         public  oct_4_slope_one
        !          1698: oct_4_slope_one:
        !          1699:         GIQ     ROUND_X_DOWN_SLOPE_ONE  ;round x=1/2 down in value
        !          1700:         jmp     oct_4_common
        !          1701: 
        !          1702: ;/////////////////////////////////////////////////////////////////////
        !          1703: ;// Octant 5
        !          1704: ;/////////////////////////////////////////////////////////////////////
        !          1705: 
        !          1706:         public  octant_5
        !          1707: octant_5:
        !          1708:         mov     [esp].sf_pfnNextBank,offset bank_y_major_next_upper
        !          1709: 
        !          1710:         mov     esi,eax
        !          1711:         or      esi,ebx
        !          1712:         or      esi,ecx
        !          1713:         or      esi,edx
        !          1714:         and     esi,F - 1
        !          1715:         jnz     oct_5_non_integer
        !          1716: 
        !          1717:         mov     esi,[esp].sf_ppdev
        !          1718:         neg     eax                     ;### untransform
        !          1719:         neg     ebx                     ;### untransform
        !          1720:         sar     eax,FLOG2               ;x0
        !          1721:         sar     ebx,FLOG2               ;y0
        !          1722: 
        !          1723:         cmp     ebx,[esi].pdev_rcl1WindowClip.yTop
        !          1724:         jl      short oct_5_map_in_bank
        !          1725: 
        !          1726:         cmp     ebx,[esi].pdev_rcl1WindowClip.yBottom
        !          1727:         jl      short oct_5_done_bank_map
        !          1728: 
        !          1729: oct_5_map_in_bank:
        !          1730:         push    eax
        !          1731:         push    ecx
        !          1732:         push    edx
        !          1733: 
        !          1734: ; ebx, esi, edi and ebp are preserved according to C calling conventions:
        !          1735: 
        !          1736:         ptrCall <dword ptr [esi].pdev_pfnBankControl>, \
        !          1737:                 <esi,ebx,JustifyBottom> ;###
        !          1738: 
        !          1739:         pop     edx
        !          1740:         pop     ecx
        !          1741:         pop     eax
        !          1742: 
        !          1743:         public  oct_5_done_bank_map
        !          1744: oct_5_done_bank_map:
        !          1745:         mov     edi,[esp].sf_lNextScan
        !          1746:         imul    edi,ebx
        !          1747:         add     edi,[esi].pdev_pvBitmapStart
        !          1748:         add     edi,eax                 ;edi now points to start byte
        !          1749: 
        !          1750:         mov     ebp,ebx                 ;###
        !          1751:         sub     ebp,[esi].pdev_rcl1WindowClip.yTop
        !          1752:         inc     ebp                     ;### ebp = # scans before end of bank
        !          1753: 
        !          1754:         mov     esi,edx
        !          1755:         sar     esi,FLOG2               ;esi = # of pixels to lay down
        !          1756: 
        !          1757:         sub     esi,ebp
        !          1758:         sbb     ebx,ebx
        !          1759:         and     ebx,esi
        !          1760:         add     ebp,ebx                 ;ebp = # of pels in this bank
        !          1761: 
        !          1762:         mov     [esp].sf_cAfterThisBank,esi
        !          1763:         mov     esi,[esp].sf_lNextScan
        !          1764:         neg     esi                     ;### going down!
        !          1765: 
        !          1766:         xor     ebx,ebx                 ;### round x = 1/2 *UP* in value
        !          1767:         sub     ebx,edx
        !          1768:         sar     ebx,1                   ;now have error term
        !          1769: 
        !          1770:         mov     eax,[esp].sf_iColor
        !          1771:         jmp     oct_2_main_loop
        !          1772: 
        !          1773:         public  oct_5_non_integer
        !          1774: oct_5_non_integer:
        !          1775:         GIQR    0                       ;###
        !          1776:                                         ;###  (remember that we're flipped
        !          1777:                                         ;###  in 'x' and 'y')
        !          1778: 
        !          1779:         mov     esi,[esp].sf_ppdev
        !          1780: 
        !          1781:         neg     edi                     ;### untransform y0
        !          1782:         neg     eax                     ;### untransform x0
        !          1783: 
        !          1784:         cmp     edi,[esi].pdev_rcl1WindowClip.yTop
        !          1785:         jl      short oct_5_nonint_map_in_bank
        !          1786: 
        !          1787:         cmp     edi,[esi].pdev_rcl1WindowClip.yBottom
        !          1788:         jl      short oct_5_nonint_done_bank_map
        !          1789: 
        !          1790: oct_5_nonint_map_in_bank:
        !          1791:         push    eax
        !          1792:         push    ecx
        !          1793:         push    edx
        !          1794: 
        !          1795:         ptrCall <dword ptr [esi].pdev_pfnBankControl>, \
        !          1796:                 <esi,edi,JustifyBottom> ;###
        !          1797: 
        !          1798:         pop     edx
        !          1799:         pop     ecx
        !          1800:         pop     eax
        !          1801: 
        !          1802: oct_5_nonint_done_bank_map:
        !          1803:         mov     [esp].sf_y0,edi
        !          1804:         imul    edi,[esp].sf_lNextScan
        !          1805:         add     edi,[esi].pdev_pvBitmapStart
        !          1806:         add     edi,eax                 ;edi points to start byte
        !          1807: 
        !          1808:         mov     ebp,[esp].sf_y0         ;###
        !          1809:         mov     esi,[esi].pdev_rcl1WindowClip.yTop
        !          1810:         dec     esi                     ;### make top exclusive
        !          1811:         sub     ebp,esi                 ;###
        !          1812:         add     esi,[esp].sf_y1         ;### don't forget that y1 wasn't un-
        !          1813:                                         ;###  transformed (so this is an 'add')
        !          1814: 
        !          1815:         jg      short @F                ;###
        !          1816:         add     ebp,esi                 ;###
        !          1817: @@:
        !          1818:         mov     [esp].sf_cAfterThisBank,esi
        !          1819: 
        !          1820:         mov     esi,[esp].sf_lNextScan
        !          1821:         neg     esi                     ;### going down!
        !          1822:         mov     eax,[esp].sf_iColor
        !          1823: 
        !          1824:         jmp     oct_2_main_loop
        !          1825: 
        !          1826: ;/////////////////////////////////////////////////////////////////////
        !          1827: ;// Octant 6
        !          1828: ;/////////////////////////////////////////////////////////////////////
        !          1829: 
        !          1830:         public  octants_6_7
        !          1831: octants_6_7:
        !          1832:         neg     edx                     ;dN = -dN (now positive)
        !          1833:         neg     ebx                     ;M1 = -M1
        !          1834:         cmp     ecx,edx
        !          1835:         jge     octant_7
        !          1836: 
        !          1837:         public  octant_6
        !          1838: octant_6:
        !          1839:         mov     [esp].sf_pfnNextBank,offset bank_y_major_next_upper
        !          1840: 
        !          1841:         mov     esi,eax
        !          1842:         or      esi,ebx
        !          1843:         or      esi,ecx
        !          1844:         or      esi,edx
        !          1845:         and     esi,F - 1
        !          1846:         jnz     oct_6_non_integer
        !          1847: 
        !          1848:         mov     esi,[esp].sf_ppdev
        !          1849:         neg     ebx                     ;### untransform
        !          1850:         sar     eax,FLOG2               ;x0
        !          1851:         sar     ebx,FLOG2               ;y0
        !          1852: 
        !          1853:         cmp     ebx,[esi].pdev_rcl1WindowClip.yTop
        !          1854:         jl      short oct_6_map_in_bank
        !          1855: 
        !          1856:         cmp     ebx,[esi].pdev_rcl1WindowClip.yBottom
        !          1857:         jl      short oct_6_done_bank_map
        !          1858: 
        !          1859: oct_6_map_in_bank:
        !          1860:         push    eax
        !          1861:         push    ecx
        !          1862:         push    edx
        !          1863: 
        !          1864: ; ebx, esi, edi and ebp are preserved according to C calling conventions:
        !          1865: 
        !          1866:         ptrCall <dword ptr [esi].pdev_pfnBankControl>, \
        !          1867:                 <esi,ebx,JustifyBottom> ;###
        !          1868: 
        !          1869:         pop     edx
        !          1870:         pop     ecx
        !          1871:         pop     eax
        !          1872: 
        !          1873:         public  oct_6_done_bank_map
        !          1874: oct_6_done_bank_map:
        !          1875:         mov     edi,[esp].sf_lNextScan
        !          1876:         imul    edi,ebx
        !          1877:         add     edi,[esi].pdev_pvBitmapStart
        !          1878:         add     edi,eax                 ;edi now points to start byte
        !          1879: 
        !          1880:         mov     ebp,ebx                 ;###
        !          1881:         sub     ebp,[esi].pdev_rcl1WindowClip.yTop
        !          1882:         inc     ebp                     ;### ebp = # scans before end of bank
        !          1883: 
        !          1884:         mov     esi,edx
        !          1885:         sar     esi,FLOG2               ;esi = # of pixels to lay down
        !          1886: 
        !          1887:         sub     esi,ebp
        !          1888:         sbb     ebx,ebx
        !          1889:         and     ebx,esi
        !          1890:         add     ebp,ebx                 ;ebp = # of pels in this bank
        !          1891: 
        !          1892:         mov     [esp].sf_cAfterThisBank,esi
        !          1893:         mov     esi,[esp].sf_lNextScan
        !          1894:         neg     esi                     ;### going down!
        !          1895: 
        !          1896:         mov     ebx,-1                  ;### round x = 1/2 *DOWN* in value
        !          1897:         sub     ebx,edx
        !          1898:         sar     ebx,1                   ;now have error term
        !          1899: 
        !          1900:         mov     eax,[esp].sf_iColor
        !          1901:         jmp     oct_1_main_loop
        !          1902: 
        !          1903:         public  oct_6_non_integer
        !          1904: oct_6_non_integer:
        !          1905:         GIQR    ROUND_X_DOWN            ;### round x=1/2 down in value
        !          1906:                                         ;###  (remember that we're flipped
        !          1907:                                         ;###  in 'y')
        !          1908: 
        !          1909:         mov     esi,[esp].sf_ppdev
        !          1910: 
        !          1911:         neg     edi                     ;### untransform y0
        !          1912: 
        !          1913:         cmp     edi,[esi].pdev_rcl1WindowClip.yTop
        !          1914:         jl      short oct_6_nonint_map_in_bank
        !          1915: 
        !          1916:         cmp     edi,[esi].pdev_rcl1WindowClip.yBottom
        !          1917:         jl      short oct_6_nonint_done_bank_map
        !          1918: 
        !          1919: oct_6_nonint_map_in_bank:
        !          1920:         push    eax
        !          1921:         push    ecx
        !          1922:         push    edx
        !          1923: 
        !          1924:         ptrCall <dword ptr [esi].pdev_pfnBankControl>, \
        !          1925:                 <esi,edi,JustifyBottom> ;###
        !          1926: 
        !          1927:         pop     edx
        !          1928:         pop     ecx
        !          1929:         pop     eax
        !          1930: 
        !          1931: oct_6_nonint_done_bank_map:
        !          1932:         mov     [esp].sf_y0,edi
        !          1933:         imul    edi,[esp].sf_lNextScan
        !          1934:         add     edi,[esi].pdev_pvBitmapStart
        !          1935:         add     edi,eax                 ;edi points to start byte
        !          1936: 
        !          1937:         mov     ebp,[esp].sf_y0         ;###
        !          1938:         mov     esi,[esi].pdev_rcl1WindowClip.yTop
        !          1939:         dec     esi                     ;### make top exclusive
        !          1940:         sub     ebp,esi                 ;###
        !          1941:         add     esi,[esp].sf_y1         ;### don't forget that y1 wasn't un-
        !          1942:                                         ;###  transformed (so this is an 'add')
        !          1943: 
        !          1944:         jg      short @F                ;###
        !          1945:         add     ebp,esi                 ;###
        !          1946: @@:
        !          1947:         mov     [esp].sf_cAfterThisBank,esi
        !          1948: 
        !          1949:         mov     esi,[esp].sf_lNextScan
        !          1950:         neg     esi                     ;### going down!
        !          1951:         mov     eax,[esp].sf_iColor
        !          1952: 
        !          1953:         jmp     oct_1_main_loop
        !          1954: 
        !          1955: ;/////////////////////////////////////////////////////////////////////
        !          1956: ;// Octant 7
        !          1957: ;/////////////////////////////////////////////////////////////////////
        !          1958: 
        !          1959:         public  octant_7
        !          1960: octant_7:
        !          1961:         mov     esi,[esp].sf_lNextScan
        !          1962:         neg     esi
        !          1963:         mov     [esp].sf_lDelta,esi     ;we're going up
        !          1964:         mov     [esp].sf_pfnNextBank,offset bank_x_major_next_upper
        !          1965: 
        !          1966:         mov     esi,eax
        !          1967:         or      esi,ebx
        !          1968:         or      esi,ecx
        !          1969:         or      esi,edx
        !          1970:         and     esi,F - 1
        !          1971:         jnz     oct_7_non_integer
        !          1972: 
        !          1973:         neg     ebx                     ;### untransform y
        !          1974: 
        !          1975:         mov     esi,[esp].sf_ppdev
        !          1976:         sar     eax,FLOG2               ;x0
        !          1977:         sar     ebx,FLOG2               ;y0
        !          1978: 
        !          1979:         cmp     ebx,[esi].pdev_rcl1WindowClip.yTop
        !          1980:         jl      short oct_7_map_in_bank
        !          1981: 
        !          1982:         cmp     ebx,[esi].pdev_rcl1WindowClip.yBottom
        !          1983:         jl      short oct_7_done_bank_map
        !          1984: 
        !          1985: oct_7_map_in_bank:
        !          1986:         push    eax
        !          1987:         push    ecx
        !          1988:         push    edx
        !          1989: 
        !          1990: ; ebx, esi, edi and esi are preserved according to C calling conventions:
        !          1991: 
        !          1992:         ptrCall <dword ptr [esi].pdev_pfnBankControl>, \
        !          1993:                 <esi, ebx, JustifyBottom> ;###
        !          1994: 
        !          1995:         pop     edx
        !          1996:         pop     ecx
        !          1997:         pop     eax
        !          1998: 
        !          1999:         public  oct_7_done_bank_map
        !          2000: oct_7_done_bank_map:
        !          2001:         mov     edi,[esp].sf_lNextScan
        !          2002:         imul    edi,ebx
        !          2003:         add     edi,[esi].pdev_pvBitmapStart
        !          2004:         add     edi,eax                 ;edi now points to start byte
        !          2005: 
        !          2006:         mov     ebp,ebx                 ;###
        !          2007:         sub     ebp,[esi].pdev_rcl1WindowClip.yTop
        !          2008:         inc     ebp                     ;### ebp = # scans before end of bank
        !          2009: 
        !          2010:         mov     esi,ecx
        !          2011:         sar     esi,FLOG2               ;esi = # of pixels to lay down
        !          2012: 
        !          2013:         xor     ebx,ebx                 ;### round y = 1/2 *UP* in value
        !          2014:         sub     ebx,ecx
        !          2015:         sar     ebx,1                   ;now have error term
        !          2016: 
        !          2017:         mov     eax,[esp].sf_iColor
        !          2018:         sub     ecx,edx                 ;ecx = dM - dN
        !          2019:         cmp     edx,ecx
        !          2020:         jg      oct_07b
        !          2021:         jmp     oct_07a
        !          2022: 
        !          2023:         public  oct_7_non_integer
        !          2024: oct_7_non_integer:
        !          2025:         cmp     ecx,edx
        !          2026:         je      oct_7_slope_one
        !          2027:         GIQ     ROUND_X_DOWN            ;### round x=1/2 down in value
        !          2028:                                         ;###  (remember that we're flipped
        !          2029:                                         ;###  in 'y')
        !          2030: 
        !          2031: oct_7_common:
        !          2032:         mov     esi,[esp].sf_ppdev
        !          2033:         neg     edi                     ;### untransform y
        !          2034: 
        !          2035:         cmp     edi,[esi].pdev_rcl1WindowClip.yTop
        !          2036:         jl      short oct_7_nonint_map_in_bank
        !          2037: 
        !          2038:         cmp     edi,[esi].pdev_rcl1WindowClip.yBottom
        !          2039:         jl      short oct_7_nonint_done_bank_map
        !          2040: 
        !          2041: oct_7_nonint_map_in_bank:
        !          2042:         push    eax
        !          2043:         push    ecx
        !          2044:         push    edx
        !          2045: 
        !          2046:         ptrCall <dword ptr [esi].pdev_pfnBankControl>, \
        !          2047:                 <esi, edi, JustifyBottom>;###
        !          2048: 
        !          2049:         pop     edx
        !          2050:         pop     ecx
        !          2051:         pop     eax
        !          2052: 
        !          2053: oct_7_nonint_done_bank_map:
        !          2054:         mov     ebp,edi                 ;###
        !          2055:         sub     ebp,[esi].pdev_rcl1WindowClip.yTop
        !          2056:         inc     ebp                     ;### esp = # scans before end of bank
        !          2057: 
        !          2058:         imul    edi,[esp].sf_lNextScan
        !          2059:         add     edi,[esi].pdev_pvBitmapStart
        !          2060:         add     edi,eax                 ;edi now points to start byte
        !          2061: 
        !          2062:         mov     esi,[esp].sf_x1
        !          2063:         sub     esi,eax                 ;esi = # pixels to lay down
        !          2064: 
        !          2065:         mov     eax,[esp].sf_iColor
        !          2066: 
        !          2067:         sub     ecx,edx                 ;ecx = dM - dN
        !          2068:         cmp     edx,ecx
        !          2069:         jg      oct_07b
        !          2070:         jmp     oct_07a
        !          2071: 
        !          2072: ;-------------------------------------------------------------------;
        !          2073: ; We have to special case those lines with a slope of exactly -1 when
        !          2074: ; 'x' rounds down in value after normalizing:
        !          2075: 
        !          2076:         public  oct_7_slope_one
        !          2077: oct_7_slope_one:
        !          2078:         GIQ     ROUND_X_DOWN_SLOPE_ONE
        !          2079:         jmp     oct_7_common
        !          2080: 
        !          2081: ;-------------------------------------------------------------------------;
        !          2082: ; Function to get next lower bank for x-major lines.
        !          2083: ;-------------------------------------------------------------------------;
        !          2084: 
        !          2085:         public  bank_x_major_next_lower
        !          2086: bank_x_major_next_lower:
        !          2087:         push    ebx
        !          2088:         mov     ebx,[esp+4].sf_ppdev    ;NOTE: Add 4 because of above push!
        !          2089:         push    ecx
        !          2090:         push    edx
        !          2091:         push    esi
        !          2092: 
        !          2093:         mov     esi,[ebx].pdev_rcl1WindowClip.yBottom
        !          2094:         sub     edi,[ebx].pdev_pvBitmapStart
        !          2095: 
        !          2096:         ptrCall <dword ptr [ebx].pdev_pfnBankControl>, \
        !          2097:                 <ebx,esi,JustifyTop>
        !          2098: 
        !          2099:         add     edi,[ebx].pdev_pvBitmapStart
        !          2100:         mov     ebp,[ebx].pdev_rcl1WindowClip.yBottom
        !          2101:         sub     ebp,esi
        !          2102: 
        !          2103:         pop     esi
        !          2104:         pop     edx
        !          2105:         pop     ecx
        !          2106:         pop     ebx
        !          2107:         mov     eax,[esp].sf_iColor
        !          2108: 
        !          2109:         jmp     [esp].sf_pfnReturn
        !          2110: 
        !          2111: ;-------------------------------------------------------------------------;
        !          2112: ; Function to get next upper bank for x-major lines.
        !          2113: ;-------------------------------------------------------------------------;
        !          2114: 
        !          2115:         public  bank_x_major_next_upper
        !          2116: bank_x_major_next_upper:
        !          2117:         push    ebx
        !          2118:         mov     ebx,[esp+4].sf_ppdev    ;NOTE: Add 4 because of above push!
        !          2119:         push    ecx
        !          2120:         push    edx
        !          2121:         push    esi
        !          2122: 
        !          2123:         mov     esi,[ebx].pdev_rcl1WindowClip.yTop
        !          2124:         dec     esi
        !          2125:         sub     edi,[ebx].pdev_pvBitmapStart
        !          2126: 
        !          2127:         ptrCall <dword ptr [ebx].pdev_pfnBankControl>, \
        !          2128:                 <ebx,esi,JustifyBottom>
        !          2129: 
        !          2130:         add     edi,[ebx].pdev_pvBitmapStart
        !          2131:         lea     ebp,[esi+1]
        !          2132:         sub     ebp,[ebx].pdev_rcl1WindowClip.yTop
        !          2133: 
        !          2134:         pop     esi
        !          2135:         pop     edx
        !          2136:         pop     ecx
        !          2137:         pop     ebx
        !          2138:         mov     eax,[esp].sf_iColor
        !          2139: 
        !          2140:         jmp     [esp].sf_pfnReturn
        !          2141: 
        !          2142: ;-------------------------------------------------------------------------;
        !          2143: ; Function to get next lower bank for y-major lines.
        !          2144: ;-------------------------------------------------------------------------;
        !          2145: 
        !          2146:         public  bank_y_major_next_lower
        !          2147: bank_y_major_next_lower:
        !          2148: 
        !          2149: ; eax = # pels after this bank
        !          2150: 
        !          2151:         push    ebx
        !          2152:         mov     ebx,[esp+4].sf_ppdev    ;NOTE: Plus 4 because of above push!
        !          2153:         push    ecx
        !          2154:         push    edx
        !          2155:         push    esi
        !          2156: 
        !          2157:         mov     esi,[ebx].pdev_rcl1WindowClip.yBottom
        !          2158:         sub     edi,[ebx].pdev_pvBitmapStart
        !          2159: 
        !          2160:         push    eax
        !          2161:         ptrCall <dword ptr [ebx].pdev_pfnBankControl>, \
        !          2162:                 <ebx,esi,JustifyTop>
        !          2163:         pop     eax
        !          2164: 
        !          2165:         add     edi,[ebx].pdev_pvBitmapStart
        !          2166:         mov     ebp,[ebx].pdev_rcl1WindowClip.yBottom
        !          2167:         sub     ebp,esi                 ;ebp = # of pels can do in this bank
        !          2168:         sub     eax,ebp                 ;esi = # of pels after this bank
        !          2169:         sbb     ebx,ebx
        !          2170:         and     ebx,eax
        !          2171:         add     ebp,ebx                 ;ebp = # of pels in this bank
        !          2172: 
        !          2173:         pop     esi
        !          2174:         pop     edx
        !          2175:         pop     ecx
        !          2176:         pop     ebx
        !          2177: 
        !          2178:         mov     [esp].sf_cAfterThisBank,eax
        !          2179:                                         ;this has to be done after 'esp' is
        !          2180:                                         ; restored!
        !          2181: 
        !          2182:         mov     eax,[esp].sf_iColor
        !          2183: 
        !          2184:         jmp     [esp].sf_pfnReturn
        !          2185: 
        !          2186: ;-------------------------------------------------------------------------;
        !          2187: ; Function to get next upper bank for y-major lines.
        !          2188: ;-------------------------------------------------------------------------;
        !          2189: 
        !          2190:         public  bank_y_major_next_upper
        !          2191: bank_y_major_next_upper:
        !          2192: 
        !          2193: ; eax = # pels after this bank
        !          2194: 
        !          2195:         push    ebx
        !          2196:         mov     ebx,[esp+4].sf_ppdev    ;NOTE: Plus 4 because of above push!
        !          2197:         push    ecx
        !          2198:         push    edx
        !          2199:         push    esi
        !          2200: 
        !          2201:         mov     ebp,[ebx].pdev_rcl1WindowClip.yTop
        !          2202:         dec     ebp
        !          2203: 
        !          2204:         sub     edi,[ebx].pdev_pvBitmapStart
        !          2205: 
        !          2206:         push    eax
        !          2207:         ptrCall <dword ptr [ebx].pdev_pfnBankControl>, \
        !          2208:                 <ebx,ebp,JustifyBottom>
        !          2209:         pop     eax
        !          2210: 
        !          2211:         add     edi,[ebx].pdev_pvBitmapStart
        !          2212: 
        !          2213:         inc     ebp                     ;restore exclusiveness
        !          2214:         sub     ebp,[ebx].pdev_rcl1WindowClip.yTop
        !          2215:                                         ;ebp = # of pels can do in this bank
        !          2216:         sub     eax,ebp                 ;esi = # of pels after this bank
        !          2217:         sbb     ebx,ebx
        !          2218:         and     ebx,eax
        !          2219:         add     ebp,ebx                 ;ebp = # of pels in this bank
        !          2220: 
        !          2221:         pop     esi
        !          2222:         pop     edx
        !          2223:         pop     ecx
        !          2224:         pop     ebx
        !          2225: 
        !          2226:         mov     [esp].sf_cAfterThisBank,eax
        !          2227:                                         ;this has to be done after 'esp' is
        !          2228:                                         ; restored!
        !          2229: 
        !          2230:         mov     eax,[esp].sf_iColor
        !          2231: 
        !          2232:         jmp     [esp].sf_pfnReturn
        !          2233: 
        !          2234: ;/////////////////////////////////////////////////////////////////////
        !          2235: ;// Horizontal Line
        !          2236: ;/////////////////////////////////////////////////////////////////////
        !          2237: 
        !          2238:         public  flip_and_do_non_integer_horizontal_line
        !          2239: flip_and_do_non_integer_horizontal_line:
        !          2240:         mov     ebx,edi
        !          2241:         mov     ecx,[esp].sf_x1
        !          2242:         sub     ecx,eax
        !          2243:         jle     next_line
        !          2244:         add     eax,ecx
        !          2245:         neg     eax
        !          2246:         inc     eax                     ;x0' = -(-original x0 - dx) + 1
        !          2247:         jmp     short horizontal_common
        !          2248: 
        !          2249:         public  do_non_integer_horizontal_line
        !          2250: do_non_integer_horizontal_line:
        !          2251:         mov     ebx,edi
        !          2252:         mov     ecx,[esp].sf_x1
        !          2253:         sub     ecx,eax
        !          2254:         jg      short horizontal_common
        !          2255:         jmp     next_line
        !          2256: 
        !          2257:         public  flip_and_do_horizontal_line
        !          2258: flip_and_do_horizontal_line:
        !          2259: 
        !          2260: ; This 'flip' entry point is for lines that were originally right-to-left:
        !          2261: 
        !          2262:         add     eax,ecx
        !          2263:         neg     eax
        !          2264:         add     eax,F                   ;M0' = -(-original M0 - original dM) + 1
        !          2265: 
        !          2266:         public  do_horizontal_line
        !          2267: do_horizontal_line:
        !          2268:         sar     eax,FLOG2               ;x0 (we're now in pixel coordinates)
        !          2269:         sar     ebx,FLOG2               ;y0
        !          2270:         sar     ecx,FLOG2               ;dx
        !          2271:         jz      next_line
        !          2272: 
        !          2273: ; NOTE: Have to have some pixels to light at this point
        !          2274: ;
        !          2275: ; eax = x0 (in pixel coordinates)
        !          2276: ; ebx = y0
        !          2277: ; ecx = dx (# pixels to light)
        !          2278: 
        !          2279: horizontal_common:
        !          2280:         mov     esi,[esp].sf_ppdev
        !          2281: 
        !          2282:         cmp     ecx,NUM_PELS_NEEDED_FOR_PLANAR_HORIZONTAL
        !          2283:         jl      do_short_horizontal_line
        !          2284: 
        !          2285:         test    [esi].pdev_fl,DRIVER_PLANAR_CAPABLE
        !          2286:         jz      do_short_horizontal_line
        !          2287: 
        !          2288: ;---------------------------------------------------------------------;
        !          2289: ; Draw horizontal lines using planar mode.
        !          2290: ;
        !          2291: ; NOTE: This code assumes that the length is at least 8 pels long!
        !          2292: 
        !          2293:         public  horizontal_planar
        !          2294: horizontal_planar:
        !          2295:         mov     edi,[esi].pdev_lPlanarNextScan
        !          2296:         imul    edi,ebx
        !          2297: 
        !          2298:         cmp     ebx,[esi].pdev_rcl1PlanarClip.yTop
        !          2299:         jl      short hor_planar_map_bank
        !          2300: 
        !          2301:         cmp     ebx,[esi].pdev_rcl1PlanarClip.yBottom
        !          2302:         jl      short hor_planar_done_bank
        !          2303: 
        !          2304: hor_planar_map_bank:
        !          2305:         push    eax
        !          2306:         push    ecx
        !          2307: 
        !          2308: ; ebx, esi, edi and ebp are preserved according to C calling conventions:
        !          2309: 
        !          2310:         ptrCall <dword ptr [esi].pdev_pfnPlanarControl>, \
        !          2311:                 <esi,ebx,JustifyTop>
        !          2312: 
        !          2313:         pop     ecx
        !          2314:         pop     eax
        !          2315: 
        !          2316: hor_planar_done_bank:
        !          2317:         add     edi,[esi].pdev_pvBitmapStart
        !          2318: 
        !          2319:         mov     ebp,eax                 ;save x0
        !          2320:         sar     eax,2
        !          2321:         add     edi,eax                 ;edi now points to start byte
        !          2322: 
        !          2323:         and     ebp,3
        !          2324:         jz      short hor_planar_start_middle
        !          2325: 
        !          2326: ; When the left end doesn't start on a quadpixel boundary, we have to
        !          2327: ; adjust the start address and do some other stuff:
        !          2328: 
        !          2329:         mov     [esp].sf_pjStart,edi
        !          2330:         inc     edi
        !          2331:         sub     ebp,4
        !          2332:         add     ecx,ebp                 ;adjust byte count to account for
        !          2333:                                         ; fractional start
        !          2334: 
        !          2335: hor_planar_start_middle:
        !          2336:         mov     eax,[esp].sf_iColor     ;load the color
        !          2337:         mov     esi,ecx                 ;save length
        !          2338: 
        !          2339:         test    edi,1
        !          2340:         jz      short hor_planar_middle_aligned
        !          2341:         mov     [edi],al                ;handle unaligned whole start byte
        !          2342:         inc     edi
        !          2343:         sub     ecx,4
        !          2344: hor_planar_middle_aligned:
        !          2345:         shr     ecx,3                   ;NOTE: we look at the carry later!
        !          2346:         rep     stosw                   ;write middle as words
        !          2347:         jnc     short hor_planar_handle_ends
        !          2348:                                         ;NOTE: here we look at the carry!
        !          2349:         mov     [edi],al                ;handle whole end byte
        !          2350:         inc     edi
        !          2351: 
        !          2352: hor_planar_handle_ends:
        !          2353:         mov     edx,VGA_BASE + SEQ_DATA
        !          2354:         and     esi,3
        !          2355:         jz      short hor_planar_left
        !          2356: hor_planar_right:
        !          2357:         mov     ecx,esi
        !          2358:         mov     eax,0f0h
        !          2359:         rol     al,cl                   ;we compute the mask instead of
        !          2360:                                         ; using a look-up table, because the
        !          2361:                                         ; table probably wouldn't be in the
        !          2362:                                         ; cache
        !          2363: 
        !          2364: ; Set right mask by disabling some planes:
        !          2365: 
        !          2366:         out     dx,al
        !          2367: 
        !          2368:         push    eax                     ;we add a delay here because some
        !          2369:         pop     eax                     ; cards can't handle a write too soon
        !          2370:                                         ; after an out.  Hopefully this will
        !          2371:                                         ; help.
        !          2372: 
        !          2373:         mov     eax,[esp].sf_iColor
        !          2374:         mov     [edi],al
        !          2375: 
        !          2376: hor_planar_left:
        !          2377:         and     ebp,3
        !          2378:         jz      short hor_planar_done
        !          2379: 
        !          2380:         mov     ecx,ebp
        !          2381:         mov     eax,0fh
        !          2382:         shl     eax,cl
        !          2383: 
        !          2384: ; Set left mask by disabling some planes:
        !          2385: 
        !          2386:         out     dx,al
        !          2387: 
        !          2388:         push    eax                     ;we add a delay here because some
        !          2389:         pop     eax                     ; cards can't handle a write too soon
        !          2390:                                         ; after an out.  Hopefully this will
        !          2391:                                         ; help.
        !          2392: 
        !          2393:         mov     edi,[esp].sf_pjStart
        !          2394:         mov     eax,[esp].sf_iColor
        !          2395:         mov     [edi],al
        !          2396: 
        !          2397: hor_planar_done:
        !          2398:         mov     al,MM_ALL
        !          2399:         out     dx,al
        !          2400: 
        !          2401:         jmp     next_line
        !          2402: 
        !          2403: ;---------------------------------------------------------------------;
        !          2404: ; Draw horizontal lines using linear mode.
        !          2405: 
        !          2406:         public  do_short_horizontal_line
        !          2407: do_short_horizontal_line:
        !          2408:         mov     edi,[esp].sf_lNextScan
        !          2409:         imul    edi,ebx
        !          2410:         add     edi,eax
        !          2411: 
        !          2412:         cmp     ebx,[esi].pdev_rcl1WindowClip.yTop
        !          2413:         jl      short hor_map_in_bank
        !          2414: 
        !          2415:         cmp     ebx,[esi].pdev_rcl1WindowClip.yBottom
        !          2416:         jl      short hor_done_bank_map
        !          2417: 
        !          2418: hor_map_in_bank:
        !          2419:         push    ecx
        !          2420: 
        !          2421: ; ebx, esi, edi and ebp are preserved according to C calling conventions:
        !          2422: 
        !          2423:         ptrCall <dword ptr [esi].pdev_pfnBankControl>, \
        !          2424:                 <esi,ebx,JustifyTop>
        !          2425: 
        !          2426:         pop     ecx
        !          2427: 
        !          2428: hor_done_bank_map:
        !          2429:         add     edi,[esi].pdev_pvBitmapStart
        !          2430:                                         ;edi now points to start byte
        !          2431:         mov     eax,[esp].sf_iColor
        !          2432: 
        !          2433:         test    edi,1
        !          2434:         jz      short hor_aligned
        !          2435:         mov     [edi],al                ;write initial unaligned byte
        !          2436:         inc     edi
        !          2437:         dec     ecx
        !          2438:         jz      next_line
        !          2439: 
        !          2440: hor_aligned:
        !          2441:         shr     ecx,1                   ;NOTE: we look at the carry later!
        !          2442:         rep     stosw                   ;write middle words
        !          2443:         jnc     next_line               ;NOTE: here we look at the carry!
        !          2444:         mov     [edi],al                ;write last byte
        !          2445:         jmp     next_line
        !          2446: 
        !          2447: 
        !          2448: endProc vFastLine
        !          2449: 
        !          2450:         end

unix.superglobalmegacorp.com

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