|
|
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
This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.