;---------------------------Module-Header------------------------------; ; Module Name: strips.asm ; ; Routines used by line code to draw strips of pixels. ; ; Copyright (c) 1992 Microsoft Corporation ;-----------------------------------------------------------------------; .386 .model small,c assume cs:FLAT,ds:FLAT,es:FLAT,ss:FLAT assume fs:nothing,gs:nothing ; Set LOOP_UNROLL_SHIFT to the log2 of the number of times you want loops in ; this module unrolled. For example, LOOP_UNROLL_SHIFT of 3 yields 2**3 = 8 ; times unrolling. This is the only thing you need to change to control ; unrolling. LOOP_UNROLL_SHIFT equ 1 .xlist include stdcall.inc ;calling convention cmacros include i386\egavga.inc include i386\strucs.inc include i386\driver.inc include i386\lines.inc .list .code ;--------------------------Private-Routine------------------------------; ; vStripSolid0 ; ; Draw lines in the 1st half-octant. ; ;-----------------------------------------------------------------------; cProc vStripSolid0,12,< \ uses esi edi ebx, \ pStrips: ptr STRIPS, \ pls: ptr LINESTATE, \ plStripEnd: ptr > ; Do some initializing: mov esi, pStrips push ebp mov ebp, plStripEnd mov eax,[esi].ST_lNextScan mov [ebp],eax ;copy delta mov eax,[esi].ST_chAndXor mov bl,ah mov bh,ah mov ah,al mov edi,[esi].ST_pjScreen add esi,offset ST_alStrips ; ax = and mask ; bx = xor mask ; ecx = pixel count ; dx = temporary register ; esi = strip pointer ; edi = display pointer ; ebp = ends of strips pointer ; [ebp] = delta mov ecx,[esi] add esi,4 test edi,1 jnz short sol0_unaligned_start sol0_aligned_loop: sub ecx,2 jl short sol0_strip_end_unaligned je short sol0_strip_end_aligned mov dx,[edi] and edx,eax xor edx,ebx mov [edi],dx add edi,2 jmp short sol0_aligned_loop sol0_strip_end_aligned: mov dx,[edi] and edx,eax xor edx,ebx mov [edi],dx add edi,2 add edi,[ebp] ;go to next scan cmp esi,ebp jae short sol0_all_done mov ecx,[esi] add esi,4 jmp short sol0_aligned_loop sol0_strip_end_unaligned: mov dl,[edi] ;do last pixel and dl,al xor dl,bl mov [edi],dl inc edi add edi,[ebp] ;go to next scan cmp esi,ebp jae short sol0_all_done mov ecx,[esi] ;do first pixel of next strip add esi,4 sol0_unaligned_start: mov dl,[edi] and dl,al xor dl,bl mov [edi],dl inc edi dec ecx jnz short sol0_aligned_loop ; Have to be careful when there is only one pel in the strip and it starts ; on an unaligned address: add edi,[ebp] cmp esi,ebp jae short sol0_all_done mov ecx,[esi] add esi,4 jmp short sol0_aligned_loop sol0_all_done: pop ebp mov esi, pStrips mov [esi].ST_pjScreen,edi cRet vStripSolid0 endProc vStripSolid0 ;--------------------------Private-Routine------------------------------; ; vStripSolid1 ; ; Draws lines in the 2nd half-octant. ; ;-----------------------------------------------------------------------; cProc vStripSolid1,12,< \ uses esi edi ebx, \ pStrips: ptr STRIPS, \ pls: ptr LINESTATE, \ plStripEnd: ptr > mov esi,pStrips push ebp mov ebp,plStripEnd mov ecx,[esi].ST_lNextScan inc ecx ; Make delta advance 1 to right mov eax,[esi].ST_chAndXor mov edi,[esi].ST_pjScreen add esi,offset ST_alStrips ; al = and mask ; ah = xor mask ; ebx = pixel count ; ecx = delta ; dl = temporary register ; esi = strip pointer ; edi = memory pointer ; ebp = end of strips pointer sol1_next_diagonal: mov ebx,[esi] add esi, 4 sol1_diagonal_loop: mov dl,[edi] and dl,al xor dl,ah mov [edi],dl add edi,ecx dec ebx jnz short sol1_diagonal_loop sub edi,ecx inc edi cmp esi,ebp jb short sol1_next_diagonal pop ebp mov esi, pStrips mov [esi].ST_pjScreen,edi cRet vStripSolid1 endProc vStripSolid1 ;--------------------------Private-Routine------------------------------; ; vStripSolid2 ; ; Draws lines in the 3rd half-octant. ; ;-----------------------------------------------------------------------; cProc vStripSolid2,12,< \ uses esi edi ebx, \ pStrips: ptr STRIPS, \ pls: ptr LINESTATE, \ plStripEnd: ptr > mov esi,pStrips push ebp mov ebp,plStripEnd mov ecx,[esi].ST_lNextScan inc ecx ; Make delta advance 1 to right mov eax,[esi].ST_chAndXor mov edi,[esi].ST_pjScreen add esi,offset ST_alStrips ; al = and mask ; ah = xor mask ; ebx = pixel count ; ecx = delta ; dl = temporary register ; esi = strip pointer ; edi = memory pointer ; ebp = end of strips pointer sol2_next_diagonal: mov ebx,[esi] add esi,4 sol2_diagonal_loop: mov dl,[edi] and dl,al xor dl,ah mov [edi],dl add edi,ecx dec ebx jnz short sol2_diagonal_loop dec edi cmp esi,ebp jb short sol2_next_diagonal pop ebp mov esi, pStrips mov [esi].ST_pjScreen,edi cRet vStripSolid2 endProc vStripSolid2 ;--------------------------Private-Routine------------------------------; ; vStripSolid3 ; ; Draws lines in the 4th half-octant. ; ;-----------------------------------------------------------------------; cProc vStripSolid3,12,< \ uses esi edi ebx, \ pStrips: ptr STRIPS, \ pls: ptr LINESTATE, \ plStripEnd: ptr > mov esi,pStrips push ebp mov ebp,plStripEnd mov ecx,[esi].ST_lNextScan mov eax,[esi].ST_chAndXor mov edi,[esi].ST_pjScreen add esi,offset ST_alStrips ; al = and mask ; ah = xor mask ; ebx = pixel count ; ecx = delta ; dl = temporary register ; esi = strip pointer ; edi = memory pointer ; ebp = end of strips pointer sol3_next_vertical: mov ebx,[esi] add esi,4 sol3_vertical_loop: mov dl,[edi] and dl,al xor dl,ah mov [edi],dl add edi,ecx dec ebx jnz short sol3_vertical_loop inc edi cmp esi,ebp jb short sol3_next_vertical pop ebp mov esi,pStrips mov [esi].ST_pjScreen,edi cRet vStripSolid3 endProc vStripSolid3 ;--------------------------Private-Routine------------------------------; ; vStripStyled0 ; ; Draws styled lines in the 1st half-octant. ; ;-----------------------------------------------------------------------; cProc vStripStyled0,12,< \ uses esi edi ebx, \ pStrips: ptr STRIPS, \ pls: ptr LINESTATE, \ plStripEnd: ptr > local ulNumPixels: dword ;# of pixels in current style local pspEnd: dword ;pointer to end of style array local cjMajor: dword ;lNextScan for screen local cjStyleDelta: dword ;delta from end of style array to start ; al = and mask ; ah = xor mask ; ebx = # of pixels in current strip ; ecx = style pointer ; edx = temporary register ; esi = strips pointer ; edi = memory pointer mov esi,pStrips mov eax,[esi].ST_lNextScan mov cjMajor,eax mov eax,[esi].ST_pspEnd mov pspEnd,eax mov ebx,[esi].ST_pspStart sub ebx,eax ;compute cjStyleDelta sub ebx,4 ;make it exclusive mov cjStyleDelta,ebx mov edx,[esi].ST_spRemaining mov ulNumPixels,edx mov eax,[esi].ST_chAndXor mov ecx,[esi].ST_psp mov edx,[esi].ST_bIsGap mov edi,[esi].ST_pjScreen add esi,offset ST_alStrips mov ebx,[esi] add esi,4 or edx,edx jz short sty0_output_loop ;if working on a dash, start there jmp short sty0_skip_loop ;if working on a gap, start there sty0_prepare_for_output: add edi,ulNumPixels ;adjust to do remainder of strip add ecx,4 cmp pspEnd,ecx ;if (ecx == pspEnd + 4) sbb edx,edx ; then ecx = pspStart and edx,cjStyleDelta add ecx,edx mov ebx,ulNumPixels push eax mov eax,[ecx] ;get next style array element mov ulNumPixels,eax pop eax neg ebx jz short sty0_output_get_new_strip sty0_output_loop: mov dl,[edi] and dl,al xor dl,ah mov [edi],dl ;write pixel inc edi ;move one pixel to right dec ulNumPixels ;might have to go to next style element jz short sty0_prepare_for_skip dec ebx jnz short sty0_output_loop sty0_output_get_new_strip: add edi,cjMajor ;move up one scan cmp esi,plStripEnd jae short sty0_output_all_done mov ebx,[esi] ;get next strip add esi,4 jmp short sty0_output_loop sty0_output_all_done: mov esi,pStrips mov [esi].ST_pjScreen,edi mov [esi].ST_bIsGap,0 ;we were working on a dash mov edi,ulNumPixels mov [esi].ST_spRemaining,edi mov [esi].ST_psp,ecx cRet vStripStyled0 sty0_prepare_for_skip: add ecx,4 cmp pspEnd,ecx ;if (ecx == pspEnd + 4) sbb edx,edx ; then ecx = pspStart and edx,cjStyleDelta add ecx,edx dec ebx push eax mov eax,[ecx] ;get next style array element mov ulNumPixels,eax pop eax jz short sty0_skip_get_new_strip sty0_skip_loop: add edi,ebx ;assume we'll skip entire strip sub ulNumPixels,ebx ; (we'll correct it if not) jle short sty0_prepare_for_output sty0_skip_get_new_strip: add edi,cjMajor ;move up one scan cmp esi,plStripEnd jae short sty0_skip_all_done mov ebx,[esi] ;get next strip add esi,4 jmp short sty0_skip_loop sty0_skip_all_done: mov esi,pStrips mov [esi].ST_pjScreen,edi mov [esi].ST_bIsGap,0ffh ;we were working on a gap mov edi,ulNumPixels mov [esi].ST_spRemaining,edi mov [esi].ST_psp,ecx cRet vStripStyled0 endProc vStripStyled0 ;--------------------------Private-Routine------------------------------; ; vStripStyled123 ; ; Draws styled lines in the 2nd, 3rd and 4th half-octants. ; ;-----------------------------------------------------------------------; cProc vStripStyled123,12,< \ uses esi edi ebx, \ pStrips: ptr STRIPS, \ pls: ptr LINESTATE, \ plStripEnd: ptr > local ulNumPixels: dword ;# of pixels in current style local pspEnd: dword ;pointer to end of style array local cjMajor: dword ;delta to go in major direction local cjMinor: dword ;delta to go in minor direction local cjStyleDelta: dword ;delta from end of style array to start ; al = and mask ; ah = xor mask ; ebx = # of pixels in current strip ; ecx = style pointer ; edx = temporary register ; esi = strips pointer ; edi = memory pointer mov esi,pStrips ; If in half-octant 3, cjMajor = cjDelta and cjMinor = 1 ; If in half-octant 2, cjMajor = cjDelta + 1 and cjMinor = -1 ; If in half-octant 1, cjMajor = cjDelta + 1 and cjMinor = -cjDelta mov eax,[esi].ST_lNextScan mov ebx,[esi].ST_flFlips test ebx,FL_FLIP_HALF jz short sty3_halfoctant_3 inc eax mov cjMajor,eax mov cjMinor,-1 test ebx,FL_FLIP_D jnz short sty3_done_major_minor_comp neg eax inc eax mov cjMinor,eax jmp short sty3_done_major_minor_comp sty3_halfoctant_3: mov cjMajor,eax mov cjMinor,1 sty3_done_major_minor_comp: mov eax,[esi].ST_pspEnd mov pspEnd,eax mov ebx,[esi].ST_pspStart sub ebx,eax ;compute cjStyleDelta sub ebx,4 ;make it exclusive mov cjStyleDelta,ebx mov edx,[esi].ST_spRemaining mov ulNumPixels,edx mov eax,[esi].ST_chAndXor mov ecx,[esi].ST_psp mov edx,[esi].ST_bIsGap mov edi,[esi].ST_pjScreen add esi,offset ST_alStrips mov ebx,[esi] add esi,4 or edx,edx jz short sty3_output_loop ;if working on a dash, start there jmp short sty3_skip_loop ;if working on a gap, start there sty3_prepare_for_output: add ecx,4 cmp pspEnd,ecx ;if (ecx == pspEnd + 4) sbb edx,edx ; then ecx = pspStart and edx,cjStyleDelta add ecx,edx mov ebx,ulNumPixels push eax mov eax,[ecx] ;get next style array element mov ulNumPixels,eax pop eax neg ebx ;adjust to do remainder of strip jz short sty3_output_get_new_strip sty3_output_loop: mov dl,[edi] and dl,al xor dl,ah mov [edi],dl ;write pixel add edi,cjMajor ;move to next scan dec ulNumPixels ;might have to go to next style element jz short sty3_prepare_for_skip dec ebx jnz short sty3_output_loop sty3_output_get_new_strip: add edi,cjMinor ;move one pixel in minor direction cmp esi,plStripEnd jae short sty3_output_all_done mov ebx,[esi] ;get next strip add esi,4 jmp short sty3_output_loop sty3_output_all_done: mov esi,pStrips mov [esi].ST_pjScreen,edi mov [esi].ST_bIsGap,0 ;we were working on a dash mov edi,ulNumPixels mov [esi].ST_spRemaining,edi mov [esi].ST_psp,ecx cRet vStripStyled123 sty3_prepare_for_skip: add ecx,4 cmp pspEnd,ecx ;if (ecx == pspEnd + 4) sbb edx,edx ; then ecx = pspStart and edx,cjStyleDelta add ecx,edx dec ebx push eax mov eax,[ecx] ;get next style array element mov ulNumPixels,eax pop eax jz short sty3_skip_get_new_strip sty3_skip_loop: ; compute min(left in strip, left in style) sub ulNumPixels,ebx ;ulNumPixels = # style - # strip sbb edx,edx and edx,ulNumPixels add ebx,edx ;ebx = min(pels left in strip, ; pels left in style) mov edx,cjMajor imul edx,ebx add edi,edx ;adjust our pointer cmp ulNumPixels,0 jle sty3_prepare_for_output sty3_skip_get_new_strip: add edi,cjMinor ;move one pixel in minor direction cmp esi,plStripEnd jae short sty3_skip_all_done mov ebx,[esi] ;get next strip add esi,4 jmp short sty3_skip_loop sty3_skip_all_done: mov esi,pStrips mov [esi].ST_pjScreen,edi mov [esi].ST_bIsGap,0ffh ;we were working on a gap mov edi,ulNumPixels mov [esi].ST_spRemaining,edi mov [esi].ST_psp,ecx cRet vStripStyled123 endProc vStripStyled123 ;--------------------------Private-Routine------------------------------; ; vStripSolidSet0 ; ; Draw lines in the 1st half-octant. ; ;-----------------------------------------------------------------------; cProc vStripSolidSet0,12,< \ uses esi edi ebx, \ pStrips: ptr STRIPS, \ pls: ptr LINESTATE, \ plStripEnd: ptr > ; Do some initializing: mov esi, pStrips push ebp mov ebp, plStripEnd mov eax,[esi].ST_lNextScan mov [ebp],eax ;copy delta mov eax,[esi].ST_chAndXor mov bl,ah mov bh,ah mov ah,al mov edi,[esi].ST_pjScreen add esi,offset ST_alStrips ; ax = and mask ; bx = xor mask ; ecx = pixel count ; dx = temporary register ; esi = strip pointer ; edi = display pointer ; ebp = ends of strips pointer ; [ebp] = delta mov ecx,[esi] add esi,4 test edi,1 jnz short sol0s_unaligned_start sol0s_aligned_loop: sub ecx,2 jl short sol0s_strip_end_unaligned je short sol0s_strip_end_aligned mov [edi],bx add edi,2 jmp short sol0s_aligned_loop sol0s_strip_end_aligned: mov [edi],bx add edi,2 add edi,[ebp] ;go to next scan cmp esi,ebp jae short sol0s_all_done mov ecx,[esi] add esi,4 jmp short sol0s_aligned_loop sol0s_strip_end_unaligned: mov [edi],bl ;do last pixel inc edi add edi,[ebp] ;go to next scan cmp esi,ebp jae short sol0s_all_done mov ecx,[esi] ;do first pixel of next strip add esi,4 sol0s_unaligned_start: mov [edi],bl inc edi dec ecx jnz short sol0s_aligned_loop ; Have to be careful when there is only one pel in the strip and it starts ; on an unaligned address: add edi,[ebp] cmp esi,ebp jae short sol0s_all_done mov ecx,[esi] add esi,4 jmp short sol0s_aligned_loop sol0s_all_done: pop ebp mov esi, pStrips mov [esi].ST_pjScreen,edi cRet vStripSolidSet0 endProc vStripSolidSet0 ;--------------------------Private-Routine------------------------------; ; vStripSolidSet1 ; ; Draws lines in the 2nd half-octant. ; ;-----------------------------------------------------------------------; cProc vStripSolidSet1,12,< \ uses esi edi ebx, \ pStrips: ptr STRIPS, \ pls: ptr LINESTATE, \ plStripEnd: ptr > mov esi,pStrips push ebp mov ebp,plStripEnd mov ecx,[esi].ST_lNextScan inc ecx ; Make delta advance 1 to right mov eax,[esi].ST_chAndXor mov edi,[esi].ST_pjScreen add esi,offset ST_alStrips ; al = and mask ; ah = xor mask ; ebx = pixel count ; ecx = delta ; dl = temporary register ; esi = strip pointer ; edi = memory pointer ; ebp = end of strips pointer sol1s_next_diagonal: mov ebx,[esi] add esi, 4 sol1s_diagonal_loop: mov [edi],ah add edi,ecx dec ebx jnz short sol1s_diagonal_loop sub edi,ecx inc edi cmp esi,ebp jb short sol1s_next_diagonal pop ebp mov esi, pStrips mov [esi].ST_pjScreen,edi cRet vStripSolidSet1 endProc vStripSolidSet1 ;--------------------------Private-Routine------------------------------; ; vStripSolidSet2 ; ; Draws lines in the 3rd half-octant. ; ;-----------------------------------------------------------------------; cProc vStripSolidSet2,12,< \ uses esi edi ebx, \ pStrips: ptr STRIPS, \ pls: ptr LINESTATE, \ plStripEnd: ptr > mov esi,pStrips push ebp mov ebp,plStripEnd mov ecx,[esi].ST_lNextScan inc ecx ; Make delta advance 1 to right mov eax,[esi].ST_chAndXor mov edi,[esi].ST_pjScreen add esi,offset ST_alStrips ; al = and mask ; ah = xor mask ; ebx = pixel count ; ecx = delta ; dl = temporary register ; esi = strip pointer ; edi = memory pointer ; ebp = end of strips pointer sol2s_next_diagonal: mov ebx,[esi] add esi,4 sol2s_diagonal_loop: mov [edi],ah add edi,ecx dec ebx jnz short sol2s_diagonal_loop dec edi cmp esi,ebp jb short sol2s_next_diagonal pop ebp mov esi, pStrips mov [esi].ST_pjScreen,edi cRet vStripSolidSet2 endProc vStripSolidSet2 ;--------------------------Private-Routine------------------------------; ; vStripSolidSet3 ; ; Draws lines in the 4th half-octant. ; ;-----------------------------------------------------------------------; cProc vStripSolidSet3,12,< \ uses esi edi ebx, \ pStrips: ptr STRIPS, \ pls: ptr LINESTATE, \ plStripEnd: ptr > mov esi,pStrips push ebp mov ebp,plStripEnd mov ecx,[esi].ST_lNextScan mov eax,[esi].ST_chAndXor mov edi,[esi].ST_pjScreen add esi,offset ST_alStrips ; al = and mask ; ah = xor mask ; ebx = pixel count ; ecx = delta ; dl = temporary register ; esi = strip pointer ; edi = memory pointer ; ebp = end of strips pointer sol3s_next_vertical: mov ebx,[esi] add esi,4 sol3s_vertical_loop: mov [edi],ah add edi,ecx dec ebx jnz short sol3s_vertical_loop inc edi cmp esi,ebp jb short sol3s_next_vertical pop ebp mov esi,pStrips mov [esi].ST_pjScreen,edi cRet vStripSolidSet3 endProc vStripSolidSet3 ;--------------------------Private-Routine------------------------------; ; vStripStyledSet0 ; ; Draws styled lines in the 1st half-octant. ; ;-----------------------------------------------------------------------; cProc vStripStyledSet0,12,< \ uses esi edi ebx, \ pStrips: ptr STRIPS, \ pls: ptr LINESTATE, \ plStripEnd: ptr > local ulNumPixels: dword ;# of pixels in current style local pspEnd: dword ;pointer to end of style array local cjMajor: dword ;lNextScan for screen local cjStyleDelta: dword ;delta from end of style array to start ; al = and mask ; ah = xor mask ; ebx = # of pixels in current strip ; ecx = style pointer ; edx = temporary register ; esi = strips pointer ; edi = memory pointer mov esi,pStrips mov eax,[esi].ST_lNextScan mov cjMajor,eax mov eax,[esi].ST_pspEnd mov pspEnd,eax mov ebx,[esi].ST_pspStart sub ebx,eax ;compute cjStyleDelta sub ebx,4 ;make it exclusive mov cjStyleDelta,ebx mov edx,[esi].ST_spRemaining mov ulNumPixels,edx mov eax,[esi].ST_chAndXor mov ecx,[esi].ST_psp mov edx,[esi].ST_bIsGap mov edi,[esi].ST_pjScreen add esi,offset ST_alStrips mov ebx,[esi] add esi,4 or edx,edx jz short sty0s_output_loop ;if working on a dash, start there jmp short sty0s_skip_loop ;if working on a gap, start there sty0s_prepare_for_output: add edi,ulNumPixels ;adjust to do remainder of strip add ecx,4 cmp pspEnd,ecx ;if (ecx == pspEnd + 4) sbb edx,edx ; then ecx = pspStart and edx,cjStyleDelta add ecx,edx mov ebx,ulNumPixels push eax mov eax,[ecx] ;get next style array element mov ulNumPixels,eax pop eax neg ebx ;see if we also need a new strip jz short sty0s_output_get_new_strip sty0s_output_loop: mov [edi],ah ;write pixel inc edi ;move one pixel to right dec ulNumPixels ;might have to go to next style element jz short sty0s_prepare_for_skip dec ebx jnz short sty0s_output_loop sty0s_output_get_new_strip: add edi,cjMajor ;move up one scan cmp esi,plStripEnd jae short sty0s_output_all_done mov ebx,[esi] ;get next strip add esi,4 jmp short sty0s_output_loop sty0s_output_all_done: mov esi,pStrips mov [esi].ST_pjScreen,edi mov [esi].ST_bIsGap,0 ;we were working on a dash mov edi,ulNumPixels mov [esi].ST_spRemaining,edi mov [esi].ST_psp,ecx cRet vStripStyledSet0 sty0s_prepare_for_skip: add ecx,4 cmp pspEnd,ecx ;if (ecx == pspEnd + 4) sbb edx,edx ; then ecx = pspStart and edx,cjStyleDelta add ecx,edx dec ebx push eax mov eax,[ecx] ;get next style array element mov ulNumPixels,eax pop eax jz short sty0s_skip_get_new_strip sty0s_skip_loop: add edi,ebx ;assume we'll skip entire strip sub ulNumPixels,ebx ; (we'll correct it if not) jle short sty0s_prepare_for_output sty0s_skip_get_new_strip: add edi,cjMajor ;move up one scan cmp esi,plStripEnd jae short sty0s_skip_all_done mov ebx,[esi] ;get next strip add esi,4 jmp short sty0s_skip_loop sty0s_skip_all_done: mov esi,pStrips mov [esi].ST_pjScreen,edi mov [esi].ST_bIsGap,0ffh ;we were working on a gap mov edi,ulNumPixels mov [esi].ST_spRemaining,edi mov [esi].ST_psp,ecx cRet vStripStyledSet0 endProc vStripStyledSet0 ;--------------------------Private-Routine------------------------------; ; vStripStyledSet123 ; ; Draws styled lines in the 2nd, 3rd and 4th half-octants. ; ;-----------------------------------------------------------------------; cProc vStripStyledSet123,12,< \ uses esi edi ebx, \ pStrips: ptr STRIPS, \ pls: ptr LINESTATE, \ plStripEnd: ptr > local ulNumPixels: dword ;# of pixels in current style local pspEnd: dword ;pointer to end of style array local cjMajor: dword ;delta to go in major direction local cjMinor: dword ;delta to go in minor direction local cjStyleDelta: dword ;delta from end of style array to start ; al = and mask ; ah = xor mask ; ebx = # of pixels in current strip ; ecx = style pointer ; edx = temporary register ; esi = strips pointer ; edi = memory pointer mov esi,pStrips ; If in half-octant 3, cjMajor = cjDelta and cjMinor = 1 ; If in half-octant 2, cjMajor = cjDelta + 1 and cjMinor = -1 ; If in half-octant 1, cjMajor = cjDelta + 1 and cjMinor = -cjDelta mov eax,[esi].ST_lNextScan mov ebx,[esi].ST_flFlips test ebx,FL_FLIP_HALF jz short sty3s_halfoctant_3 inc eax mov cjMajor,eax mov cjMinor,-1 test ebx,FL_FLIP_D jnz short sty3s_done_major_minor_comp neg eax inc eax mov cjMinor,eax jmp short sty3s_done_major_minor_comp sty3s_halfoctant_3: mov cjMajor,eax mov cjMinor,1 sty3s_done_major_minor_comp: mov eax,[esi].ST_pspEnd mov pspEnd,eax mov ebx,[esi].ST_pspStart sub ebx,eax ;compute cjStyleDelta sub ebx,4 ;make it exclusive mov cjStyleDelta,ebx mov edx,[esi].ST_spRemaining mov ulNumPixels,edx mov eax,[esi].ST_chAndXor mov ecx,[esi].ST_psp mov edx,[esi].ST_bIsGap mov edi,[esi].ST_pjScreen add esi,offset ST_alStrips mov ebx,[esi] add esi,4 or edx,edx jz short sty3s_output_loop ;if working on a dash, start there jmp short sty3s_skip_loop ;if working on a gap, start there sty3s_prepare_for_output: add ecx,4 cmp pspEnd,ecx ;if (ecx == pspEnd + 4) sbb edx,edx ; then ecx = pspStart and edx,cjStyleDelta add ecx,edx mov ebx,ulNumPixels push eax mov eax,[ecx] ;get next style array element mov ulNumPixels,eax pop eax neg ebx ;adjust to do remainder of strip jz short sty3s_output_get_new_strip sty3s_output_loop: mov [edi],ah ;write pixel add edi,cjMajor ;move to next scan dec ulNumPixels ;might have to go to next style element jz short sty3s_prepare_for_skip dec ebx jnz short sty3s_output_loop sty3s_output_get_new_strip: add edi,cjMinor ;move in minor direction cmp esi,plStripEnd jae short sty3s_output_all_done mov ebx,[esi] ;get next strip add esi,4 jmp short sty3s_output_loop sty3s_output_all_done: mov esi,pStrips mov [esi].ST_pjScreen,edi mov [esi].ST_bIsGap,0 ;we were working on a dash mov edi,ulNumPixels mov [esi].ST_spRemaining,edi mov [esi].ST_psp,ecx cRet vStripStyledSet123 sty3s_prepare_for_skip: add ecx,4 cmp pspEnd,ecx ;if (ecx == pspEnd + 4) sbb edx,edx ; then ecx = pspStart and edx,cjStyleDelta add ecx,edx dec ebx push eax mov eax,[ecx] ;get next style array element mov ulNumPixels,eax pop eax jz short sty3s_skip_get_new_strip sty3s_skip_loop: ; compute min(left in strip, left in style) sub ulNumPixels,ebx ;ulNumPixels = # style - # strip sbb edx,edx and edx,ulNumPixels add ebx,edx ;ebx = min(pels left in strip, ; pels left in style) mov edx,cjMajor imul edx,ebx add edi,edx ;adjust our pointer cmp ulNumPixels,0 jle sty3s_prepare_for_output sty3s_skip_get_new_strip: add edi,cjMinor ;move in minor direction cmp esi,plStripEnd jae short sty3s_skip_all_done mov ebx,[esi] ;get next strip add esi,4 jmp short sty3s_skip_loop sty3s_skip_all_done: mov esi,pStrips mov [esi].ST_pjScreen,edi mov [esi].ST_bIsGap,0ffh ;we were working on a gap mov edi,ulNumPixels mov [esi].ST_spRemaining,edi mov [esi].ST_psp,ecx cRet vStripStyledSet123 endProc vStripStyledSet123 end