577 lines
		
	
	
		
			16 KiB
		
	
	
	
		
			NASM
		
	
	
	
	
	
			
		
		
	
	
			577 lines
		
	
	
		
			16 KiB
		
	
	
	
		
			NASM
		
	
	
	
	
	
| ;----------------------------- Module Header -----------------------------;
 | |
| ;
 | |
| ; dfbline.asm
 | |
| ;
 | |
| ; Contents:  Strip draw routines for writing lines onto device format bitmaps
 | |
| ;
 | |
| ; Notes:
 | |
| ;
 | |
| ; 1) We have 6 strip draw routines.  Horizontal, vertical, and diagonal
 | |
| ;    cases for each of Solid and Arbitrary styled lines.  Each routine
 | |
| ;    only has to draw left-to-right.
 | |
| ;
 | |
| ; 2) DFB Format:
 | |
| ;
 | |
| ;    The DFB format is a four plane bitmap.  Each bit in a 4 bit VGA colour
 | |
| ;    corresponds to a plane in the bitmap.  The bitmap has the format
 | |
| ;
 | |
| ;           PLANE 3	\
 | |
| ;           PLANE 2	 | - This is one scan line.
 | |
| ;           PLANE 1	 |   We are going UP in memory from PLANE 0
 | |
| ;           PLANE 0	/    on a scan line.
 | |
| ;
 | |
| ;    Where PLANE n corrosponds to bit n (counting from the right) in a VGA
 | |
| ;    colour.
 | |
| ;
 | |
| ;    The line code will call the appropriate strip routine 4 times to draw
 | |
| ;    a line: each time we'll draw on one plane of the DFB.
 | |
| ;
 | |
| ; 4) ROP Actions:
 | |
| ;
 | |
| ; 5) Output Routines:
 | |
| ;
 | |
| ;    The scope of the output routines is wildly inconsistant between functions.
 | |
| ;    Some write single bytes, some write the whole strips array onto a plane.
 | |
| ;    The overriding consideration was ease of implementation
 | |
| ;
 | |
| ;-------------------------------------------------------------------------;
 | |
| 
 | |
| 	PAGE , 132
 | |
| 	.386
 | |
| 
 | |
| 	.model  small,c
 | |
| 
 | |
| 	assume ds:FLAT,es:FLAT,ss:FLAT
 | |
| 	assume fs:nothing,gs:nothing
 | |
| 
 | |
| 	.xlist
 | |
| 	include stdcall.inc	      ;calling convention cmacros
 | |
| 	include i386\strucs.inc
 | |
| 	.list
 | |
| 	.code
 | |
| 
 | |
| 	include i386\lines.inc
 | |
| 
 | |
| ;--------------------------Private-Routine------------------------------;
 | |
| ; vBitmapSolidDiagonal
 | |
| ;
 | |
| ;   Draw diagonal strips left-to-right (handles both x-major and
 | |
| ;   y-major diagonal lines).
 | |
| ;
 | |
| ;-----------------------------------------------------------------------;
 | |
| 
 | |
| cProc   vBitmapSolidDiagonal,12,<  \
 | |
|         uses        esi edi ebx,   \
 | |
|         pStrips:    ptr STRIPS,    \
 | |
|         pls:        ptr LINESTATE, \
 | |
|         plStripEnd: ptr >
 | |
| 
 | |
|         mov     ebx, plStripEnd
 | |
|         mov     esi, pStrips
 | |
| 
 | |
| ; Do some initialization:
 | |
| 
 | |
|         mov     [ebx], esi                      ; save pStrips
 | |
|         mov     [ebx + 4], ebp
 | |
|         mov     al,  [esi].ST_jBitMask
 | |
|         mov     edi, [esi].ST_pjScreen
 | |
|         mov     ebp, [esi].ST_lNextScan
 | |
| 
 | |
| ; Set up ROP registers:
 | |
| 
 | |
|         mov     dl, al
 | |
|         mov     dh, al
 | |
|         and     edx, [esi].ST_ulBitmapROP
 | |
|         not     dl
 | |
| 
 | |
| ;                   al  = rotating bit
 | |
| ;                   ebx = pointer to end of strips
 | |
| ;                   ecx = pixel count
 | |
| ;                   dl  = and mask
 | |
| ;                   dh  = xor mask
 | |
| ;                   esi = current strip pointer
 | |
| ;                   edi = display memory pointer
 | |
| ;                   ebp = delta
 | |
| 
 | |
|         test    [esi].ST_flFlips, FL_FLIP_D
 | |
|         lea     esi, [esi].ST_alStrips
 | |
|         jnz     y_major_next_diagonal
 | |
| 
 | |
| x_major_next_diagonal:
 | |
|         mov     ecx, [esi]
 | |
|         add     esi, 4
 | |
| 
 | |
| x_major_diagonal_loop:
 | |
|         mov     ah, [edi]
 | |
|         and     ah, dl
 | |
|         xor     ah, dh
 | |
|         mov     [edi], ah
 | |
| 
 | |
|         ror     dl, 1
 | |
|         ror     dh, 1
 | |
|         ror     al, 1
 | |
|         adc     edi, ebp
 | |
|         dec     ecx
 | |
|         jnz     short x_major_diagonal_loop
 | |
| 
 | |
|         sub     edi, ebp
 | |
|         cmp     esi, ebx
 | |
|         jb      short x_major_next_diagonal
 | |
| 
 | |
|         jmp     short done_diagonal
 | |
| 
 | |
| y_major_next_diagonal:
 | |
|         mov     ecx, [esi]
 | |
|         add     esi, 4
 | |
| 
 | |
| y_major_diagonal_loop:
 | |
|         mov     ah, [edi]
 | |
|         and     ah, dl
 | |
|         xor     ah, dh
 | |
|         mov     [edi], ah
 | |
| 
 | |
|         ror     dl, 1
 | |
|         ror     dh, 1
 | |
|         ror     al, 1
 | |
|         adc     edi, ebp
 | |
|         dec     ecx
 | |
|         jnz     short y_major_diagonal_loop
 | |
| 
 | |
|         rol     dl, 1
 | |
|         rol     dh, 1
 | |
|         rol     al, 1
 | |
|         sbb     edi, 0
 | |
|         cmp     esi, ebx
 | |
|         jb      short y_major_next_diagonal
 | |
| 
 | |
| done_diagonal:
 | |
|         mov     esi, [ebx]                      ; esi = pStrips
 | |
|         mov     ebp, [ebx + 4]                  ; restore ebp
 | |
|         mov     [esi].ST_pjScreen, edi
 | |
|         mov     [esi].ST_jBitmask, al
 | |
|         cRet    vBitmapSolidDiagonal
 | |
| 
 | |
| endProc vBitmapSolidDiagonal
 | |
| 
 | |
| ;--------------------------Private-Routine------------------------------;
 | |
| ; vBitmapSolidVertical
 | |
| ;
 | |
| ;   Draw vertical strips left-to-right.
 | |
| ;
 | |
| ;-----------------------------------------------------------------------;
 | |
| 
 | |
| cProc   vBitmapSolidVertical,12,<  \
 | |
|         uses         esi edi ebx,   \
 | |
|         pStrips:     ptr STRIPS,    \
 | |
|         pls:         ptr LINESTATE, \
 | |
|         plStripEnd: ptr >
 | |
| 
 | |
|         mov     ebx, plStripEnd
 | |
|         mov     esi, pStrips
 | |
| 
 | |
| ; Do some initialization:
 | |
| 
 | |
|         mov     [ebx], esi                      ; save pStrips
 | |
|         mov     [ebx + 4], ebp
 | |
|         mov     al,  [esi].ST_jBitMask
 | |
|         mov     edi, [esi].ST_pjScreen
 | |
|         mov     ebp, [esi].ST_lNextScan
 | |
| 
 | |
| ; Set up ROP registers:
 | |
| 
 | |
|         mov     dl, al
 | |
|         mov     dh, al
 | |
|         and     edx, [esi].ST_ulBitmapROP
 | |
|         add     esi, offset ST_alStrips
 | |
|         not     dl
 | |
| 
 | |
| ;                   al  = rotating bit
 | |
| ;                   ebx = pointer to end of strips
 | |
| ;                   ecx = pixel count
 | |
| ;                   dl  = and mask
 | |
| ;                   dh  = xor mask
 | |
| ;                   esi = current strip pointer
 | |
| ;                   edi = display memory pointer
 | |
| ;                   ebp = delta
 | |
| 
 | |
| next_vertical:
 | |
|         mov     ecx, [esi]
 | |
|         add     esi, 4
 | |
| 
 | |
| vertical_loop:
 | |
|         mov     ah, [edi]
 | |
|         and     ah, dl
 | |
|         xor     ah, dh
 | |
|         mov     [edi], ah
 | |
| 
 | |
|         add     edi, ebp
 | |
|         dec     ecx
 | |
|         jnz     short vertical_loop
 | |
| 
 | |
| ; Okay, we're finished with the strip so we have to advance one pixel
 | |
| ; to the right:
 | |
| 
 | |
|         ror     dl, 1
 | |
|         ror     dh, 1
 | |
|         ror     al, 1
 | |
|         adc     edi, 0
 | |
| 
 | |
| ; See if there are any more strips:
 | |
| 
 | |
|         cmp     esi, ebx
 | |
|         jb      short next_vertical
 | |
| 
 | |
| ; We're done:
 | |
| 
 | |
|         mov     esi, [ebx]                      ; esi = pStrips
 | |
|         mov     ebp, [ebx + 4]                  ; restore ebp
 | |
|         mov     [esi].ST_pjScreen, edi
 | |
|         mov     [esi].ST_jBitmask, al
 | |
|         cRet    vBitmapSolidDiagonal
 | |
| 
 | |
| endProc vBitmapSolidVertical
 | |
| 
 | |
| ;--------------------------Private-Routine------------------------------;
 | |
| ; vBitmapSolidHorizontal
 | |
| ;
 | |
| ;   Draw vertical strips left-to-right.
 | |
| ;
 | |
| ;-----------------------------------------------------------------------;
 | |
| 
 | |
| cProc   vBitmapSolidHorizontal,12,< \
 | |
|         uses        esi edi ebx,    \
 | |
|         pStrips:    ptr STRIPS,     \
 | |
|         pls:        ptr LINESTATE,  \
 | |
|         plStripEnd: ptr >
 | |
| 
 | |
|         mov     ebx, plStripEnd
 | |
|         mov     esi, pStrips
 | |
| 
 | |
| ; Do some initialization:
 | |
| 
 | |
|         push    ebp
 | |
|         mov     [esi].ST_plStripEnd, ebx
 | |
|         mov     al,  [esi].ST_jBitMask
 | |
|         mov     edx, [esi].ST_ulBitmapROP
 | |
|         mov     edi, [esi].ST_pjScreen
 | |
|         lea     ebp, [esi].ST_alStrips
 | |
| 
 | |
| ;                   al  = rotating bit
 | |
| ;                   ebx = garbage
 | |
| ;                   ecx = pixel count
 | |
| ;                   edx = ulBitmapROP
 | |
| ;                   esi = pStrips
 | |
| ;                   edi = display memory pointer
 | |
| ;                   ebp = current strip pointer
 | |
| 
 | |
| next_horizontal:
 | |
|         mov     ecx, [ebp]
 | |
|         add     ebp, 4
 | |
| 
 | |
|         lea     ebx, [2 * eax - 1]      ; bl = start mask
 | |
|         ror     al, cl                  ; al = rotating bit for next scan
 | |
|         shr     ecx, 3
 | |
|         cmp     bl, al
 | |
|         adc     ecx, 0
 | |
|         jnz     short extends_out_of_first_byte
 | |
| 
 | |
|         sub     bl, al                  ; figure out rest of mask
 | |
|         sub     bl, al
 | |
|         inc     bl
 | |
| 
 | |
|         mov     bh, bl                  ; compute ROP values
 | |
|         and     ebx, edx
 | |
|         not     bl
 | |
| 
 | |
|         mov     ah, [edi]               ; actually write the byte
 | |
|         and     ah, bl
 | |
|         xor     ah, bh
 | |
|         mov     [edi], ah
 | |
| 
 | |
|         add     edi, [esi].ST_lNextScan ; increment to next scan
 | |
| 
 | |
|         cmp     ebp, [esi].ST_plStripEnd ; see if done all strips
 | |
|         jb      short next_horizontal
 | |
| 
 | |
|         pop     ebp                     ; clean up and leave
 | |
|         mov     [esi].ST_pjScreen, edi
 | |
|         mov     [esi].ST_jBitmask, al
 | |
|         cRet    vBitmapSolidHorizontal
 | |
| 
 | |
| extends_out_of_first_byte:
 | |
| 
 | |
| ; This part gets called when the current strip doesn't fit entirely
 | |
| ; into one byte:
 | |
| 
 | |
|         mov     bh, bl                  ; compute ROP values
 | |
|         and     ebx, edx
 | |
|         not     bl
 | |
| 
 | |
|         mov     ah, [edi]               ; actually write the byte
 | |
|         and     ah, bl
 | |
|         xor     ah, bh
 | |
|         mov     [edi], ah
 | |
| 
 | |
|         inc     edi                     ; move to next byte
 | |
| 
 | |
|         dec     ecx                     ; any bytes inbetween start & end byte?
 | |
|         jnz     short output_bunch
 | |
| 
 | |
| last_byte:
 | |
|         lea     ebx, [2 * eax - 1]      ; compute end mask
 | |
|         not     bl
 | |
| 
 | |
|         mov     bh, bl                  ; compute ROP values
 | |
|         and     ebx, edx
 | |
|         not     bl
 | |
| 
 | |
|         mov     ah, [edi]               ; actually write the byte
 | |
|         and     ah, bl
 | |
|         xor     ah, bh
 | |
|         mov     [edi], ah
 | |
| 
 | |
|         add     edi, [esi].ST_lNextScan ; go to next scan
 | |
| 
 | |
|         cmp     ebp, [esi].ST_plStripEnd ; was this the last strip?
 | |
|         jb      short next_horizontal
 | |
| 
 | |
|         pop     ebp                     ; clean up and leave
 | |
|         mov     [esi].ST_pjScreen, edi
 | |
|         mov     [esi].ST_jBitmask, al
 | |
|         cRet    vBitmapSolidHorizontal
 | |
| 
 | |
| output_bunch:
 | |
|         not     dl
 | |
| 
 | |
| bunch_loop:
 | |
| 
 | |
| ; We have a series of bytes to lay down:
 | |
| 
 | |
|         mov     ah, [edi]
 | |
|         and     ah, dl
 | |
|         xor     ah, dh
 | |
|         mov     [edi], ah
 | |
|         inc     edi
 | |
| 
 | |
|         dec     ecx                     ; we done all the whole bytes?
 | |
|         jnz     short bunch_loop
 | |
| 
 | |
|         not     dl
 | |
|         jmp     short last_byte
 | |
| 
 | |
| endProc vBitmapSolidHorizontal
 | |
| 
 | |
| ;--------------------------Private-Routine------------------------------;
 | |
| ; vBitmapStyledHorizontal
 | |
| ;
 | |
| ;   Draws arbitrarily styled horizontal strips left-to-right.
 | |
| ;
 | |
| ;-----------------------------------------------------------------------;
 | |
| 
 | |
| cProc   vBitmapStyledHorizontal,12,< \
 | |
|         uses        esi edi ebx,    \
 | |
|         pStrips:    ptr STRIPS,     \
 | |
|         pls:        ptr LINESTATE,  \
 | |
|         plStripEnd: ptr >
 | |
| 
 | |
|         mov     ebx, plStripEnd
 | |
|         mov     esi, pStrips
 | |
|         push    ebp
 | |
|         mov     ebp, esi
 | |
| 
 | |
| ; Do some initialization:
 | |
| 
 | |
|         mov     [ebp].ST_plStripEnd, ebx
 | |
|         lea     esi, [ebp].ST_alStrips
 | |
|         mov     al,  [ebp].ST_jBitmask
 | |
|         mov     ah,  [ebp].ST_jStyleMask
 | |
|         mov     edx, [ebp].ST_spRemaining
 | |
|         mov     edi, [ebp].ST_pjScreen
 | |
| 
 | |
| ;                   al  = rotating bit
 | |
| ;                   ah  = 0 if working on a dash, 0ffh if working on a gap
 | |
| ;                   bl  = accumulating mask
 | |
| ;                   ecx = pixel count
 | |
| ;                   edx = # of pixels to go in dash or gap (must be 32 bits)
 | |
| ;                   esi = current strip pointer
 | |
| ;                   edi = display memory pointer
 | |
| ;                   ebp = pStrips
 | |
| 
 | |
|         align   4
 | |
| 
 | |
| next_horizontal:
 | |
|         mov     ecx, [esi]              ; get new strip count
 | |
|         add     esi, 4
 | |
|         xor     bl, bl                  ; clear accumulating mask
 | |
| 
 | |
| horizontal_loop:
 | |
|         xor     bl, ah                  ; set bit in accumulating mask if
 | |
|         or      bl, al                  ;   ah says we're working on a dash
 | |
|         xor     bl, ah
 | |
| 
 | |
|         dec     edx
 | |
|         jz      short next_style_entry
 | |
| 
 | |
| next_pixel:
 | |
|         ror     al, 1
 | |
|         jc      short output_byte
 | |
|         dec     ecx                     ; another pixel done; continue with
 | |
|         jnz     short horizontal_loop   ;   with strip if there's more left
 | |
| 
 | |
| ; We're done a horizontal strip.  Now we do a diagonal step:
 | |
| 
 | |
| side_step:
 | |
|         mov     bh, bl                  ; do ROP stuff
 | |
|         and     ebx, [ebp].ST_ulBitmapROP
 | |
|         not     bl
 | |
| 
 | |
|         and     [edi], bl               ; write the byte
 | |
|         xor     [edi], bh
 | |
| 
 | |
|         add     edi, [ebp].ST_lNextScan
 | |
| 
 | |
|         cmp     [ebp].ST_plStripEnd, esi ; are we finished the strip array?
 | |
|         ja      short next_horizontal
 | |
| 
 | |
|         mov     [ebp].ST_pjScreen, edi  ; remember where we were
 | |
|         mov     [ebp].ST_jBitmask, al
 | |
|         mov     [ebp].ST_jStyleMask, ah
 | |
|         mov     [ebp].ST_spRemaining, edx
 | |
| 
 | |
|         pop     ebp
 | |
| 
 | |
|         cRet    vBitmapStyledHorizontal
 | |
| 
 | |
| output_byte:
 | |
|         mov     bh, bl                  ; do ROP stuff
 | |
|         and     ebx, [ebp].ST_ulBitmapROP
 | |
|         not     bl
 | |
| 
 | |
|         and     [edi], bl               ; write the byte
 | |
|         xor     [edi], bh
 | |
| 
 | |
|         xor     bl, bl                  ; clear accumulating mask
 | |
| 
 | |
|         inc     edi                     ; moved one byte to right
 | |
| 
 | |
|         dec     ecx
 | |
|         jnz     short horizontal_loop   ; more pels to go in strip
 | |
|         jmp     short side_step         ; need a new strip
 | |
| 
 | |
| ; We're onto a new entry in the style array:
 | |
| 
 | |
| next_style_entry:
 | |
|         mov     edx, [ebp].ST_psp       ; go to next style array entry
 | |
|         add     edx, 4
 | |
|         cmp     [ebp].ST_pspEnd, edx    ; if past end go back to start
 | |
|         jae     short @F
 | |
|         mov     edx, [ebp].ST_pspStart
 | |
| @@:
 | |
|         mov     [ebp].ST_psp, edx       ; save it for posterity
 | |
|         mov     edx, [edx]              ; new count
 | |
|         not     ah                      ; dash => gap or gap => dash
 | |
| 
 | |
|         jmp     short next_pixel
 | |
| 
 | |
| endProc vBitmapStyledHorizontal
 | |
| 
 | |
| 
 | |
| ;--------------------------Private-Routine------------------------------;
 | |
| ; vBitmapStyledVertical
 | |
| ;
 | |
| ;   Draw arbitrarily styled vertical strips left-to-right.
 | |
| ;
 | |
| ;-----------------------------------------------------------------------;
 | |
| 
 | |
| cProc   vBitmapStyledVertical,12,<  \
 | |
|         uses        esi edi ebx,    \
 | |
|         pStrips:    ptr STRIPS,     \
 | |
|         pls:        ptr LINESTATE,  \
 | |
|         plStripEnd: ptr >
 | |
| 
 | |
|         mov     ebx, plStripEnd
 | |
|         mov     esi, pStrips
 | |
|         push    ebp
 | |
|         mov     ebp, esi
 | |
| 
 | |
| ; Do some initialization:
 | |
| 
 | |
|         mov     [ebp].ST_plStripEnd, ebx
 | |
|         lea     esi, [ebp].ST_alStrips
 | |
|         mov     al,  [ebp].ST_jBitmask
 | |
|         mov     ah,  [ebp].ST_jStyleMask
 | |
|         mov     edx, [ebp].ST_spRemaining
 | |
|         mov     edi, [ebp].ST_pjScreen
 | |
| 
 | |
| ;                   al  = rotating bit
 | |
| ;                   ah  = 0 if working on a dash, 0ffh if working on a gap
 | |
| ;                   bl  = and mask
 | |
| ;                   bh  = xor mask
 | |
| ;                   ecx = pixel count
 | |
| ;                   edx = # of pixels to go in dash or gap (must be 32 bits)
 | |
| ;                   esi = current strip pointer
 | |
| ;                   edi = display memory pointer
 | |
| ;                   ebp = pStrips
 | |
| 
 | |
|         align   4
 | |
| 
 | |
| next_vertical:
 | |
|         mov     ecx, [esi]              ; get new strip count
 | |
|         add     esi, 4
 | |
| 
 | |
|         mov     bl, al                  ; load up bl and bh to handle ROP
 | |
|         mov     bh, al
 | |
|         and     ebx, [ebp].ST_ulBitmapROP
 | |
|         not     bl
 | |
| 
 | |
| vertical_loop:
 | |
|         or      ah, ah
 | |
|         jnz     short @F                ; don't output pixel if in a gap
 | |
|         and     [edi], bl
 | |
|         xor     [edi], bh
 | |
| @@:
 | |
|         dec     edx
 | |
|         jz      short next_style_entry
 | |
| 
 | |
| next_pixel:
 | |
|         add     edi, [ebp].ST_lNextScan
 | |
|         dec     ecx                     ; another pixel done; continue with
 | |
|         jnz     short vertical_loop     ;   with strip if there's more left
 | |
| 
 | |
| ; We're done a vertical strip.  Take a side step:
 | |
| 
 | |
|         ror     al, 1
 | |
|         adc     edi, 0
 | |
| 
 | |
|         cmp     esi, [ebp].ST_plStripEnd ; we done with all the strips?
 | |
|         jb      short next_vertical
 | |
| 
 | |
|         mov     [ebp].ST_pjScreen, edi  ; remember where we were
 | |
|         mov     [ebp].ST_jBitmask, al
 | |
|         mov     [ebp].ST_jStyleMask, ah
 | |
|         mov     [ebp].ST_spRemaining, edx
 | |
| 
 | |
|         pop     ebp
 | |
| 
 | |
|         cRet    vBitmapStyledVertical
 | |
| 
 | |
| ; We're onto a new entry in the style array:
 | |
| 
 | |
| next_style_entry:
 | |
|         mov     edx, [ebp].ST_psp       ; go to next style array entry
 | |
|         add     edx, 4
 | |
|         cmp     [ebp].ST_pspEnd, edx    ; if past end go back to start
 | |
|         jae     short @F
 | |
|         mov     edx, [ebp].ST_pspStart
 | |
| @@:
 | |
|         mov     [ebp].ST_psp, edx       ; save it for posterity
 | |
|         mov     edx, [edx]              ; new count
 | |
|         not     ah                      ; dash => gap or gap => dash
 | |
| 
 | |
|         jmp     short next_pixel
 | |
| 
 | |
| 
 | |
| endProc vBitmapStyledVertical
 | |
| 
 | |
|         end
 |