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