864 lines
		
	
	
		
			26 KiB
		
	
	
	
		
			NASM
		
	
	
	
	
	
			
		
		
	
	
			864 lines
		
	
	
		
			26 KiB
		
	
	
	
		
			NASM
		
	
	
	
	
	
;---------------------------Module-Header------------------------------;
 | 
						|
; Module Name: vgastrps.asm
 | 
						|
;
 | 
						|
; Routines used by line code to draw strips of pixels.
 | 
						|
;
 | 
						|
; Copyright (c) 1992 Microsoft Corporation
 | 
						|
;-----------------------------------------------------------------------;
 | 
						|
 | 
						|
        .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\egavga.inc
 | 
						|
        include i386\strucs.inc
 | 
						|
        include i386\lines.inc
 | 
						|
        .list
 | 
						|
 | 
						|
        .code
 | 
						|
 | 
						|
_TEXT$04   SEGMENT DWORD USE32 PUBLIC 'CODE'
 | 
						|
           ASSUME  DS:FLAT, ES:FLAT, SS:NOTHING, FS:NOTHING, GS:NOTHING
 | 
						|
 | 
						|
;---------------------------Public-Routine------------------------------;
 | 
						|
; vSetStrips
 | 
						|
;
 | 
						|
; Set the VGA into the appropriate mode for line drawing.
 | 
						|
;
 | 
						|
;-----------------------------------------------------------------------;
 | 
						|
 | 
						|
cProc   vSetStrips,8,<     \
 | 
						|
        clr:    dword,     \
 | 
						|
        mode:   dword      >
 | 
						|
 | 
						|
        mov     edx, VGA_BASE + GRAF_ADDR
 | 
						|
 | 
						|
        mov     al, GRAF_SET_RESET
 | 
						|
        mov     ah, byte ptr clr
 | 
						|
        out     dx, ax
 | 
						|
 | 
						|
        cmp     mode, DR_SET
 | 
						|
        je      @F
 | 
						|
 | 
						|
        mov     al, GRAF_DATA_ROT
 | 
						|
        mov     ah, byte ptr mode
 | 
						|
        out     dx, ax
 | 
						|
 | 
						|
@@:
 | 
						|
        mov     eax, GRAF_MODE + ((M_AND_WRITE + M_COLOR_READ) SHL 8)
 | 
						|
        out     dx, ax                  ;write mode 3 so we can do the masking
 | 
						|
                                        ; without OUTs, read mode 1 so we can
 | 
						|
                                        ; read 0xFF from memory always, for
 | 
						|
                                        ; ANDing (because Color Don't Care is
 | 
						|
                                        ; all zeros)
 | 
						|
        cRet    vSetStrips
 | 
						|
 | 
						|
endProc vSetStrips
 | 
						|
 | 
						|
;---------------------------Public-Routine------------------------------;
 | 
						|
; vClearStrips
 | 
						|
;
 | 
						|
; Restore the VGA to its default state.
 | 
						|
;
 | 
						|
;-----------------------------------------------------------------------;
 | 
						|
 | 
						|
cProc   vClearStrips,4,< \
 | 
						|
        oldmode: dword   >
 | 
						|
 | 
						|
; Restore the EGA/VGA to its default state:
 | 
						|
 | 
						|
        mov     edx, VGA_BASE + GRAF_ADDR
 | 
						|
 | 
						|
        cmp     oldmode, DR_SET
 | 
						|
        je      @F
 | 
						|
        mov     eax, (DR_SET shl 8) + GRAF_DATA_ROT
 | 
						|
        out     dx, ax
 | 
						|
 | 
						|
@@:
 | 
						|
        mov     eax, GRAF_MODE + ((M_PROC_WRITE + M_DATA_READ) SHL 8)
 | 
						|
        out     dx, ax                  ;restore read mode 0 and write mode 0
 | 
						|
 | 
						|
        cRet    vClearStrips
 | 
						|
 | 
						|
endProc vClearStrips
 | 
						|
 | 
						|
;--------------------------Private-Routine------------------------------;
 | 
						|
; vStripSolidDiagonalHorizontal
 | 
						|
;
 | 
						|
;   Draw an x-major near-diagonal strip left-to-right
 | 
						|
;
 | 
						|
;-----------------------------------------------------------------------;
 | 
						|
 | 
						|
cProc   vStripSolidDiagonalHorizontal,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     al,  [esi].ST_jBitMask
 | 
						|
        mov     edi, [esi].ST_pjScreen
 | 
						|
        add     esi, offset ST_alStrips
 | 
						|
 | 
						|
;                   al  = bit mask
 | 
						|
;                   ebx = pixel count
 | 
						|
;                   ecx = delta
 | 
						|
;                   edx = port #
 | 
						|
;                   esi = strip pointer
 | 
						|
;                   edi = memory pointer
 | 
						|
;                   ebp = end of strips pointer
 | 
						|
 | 
						|
next_diagonal:
 | 
						|
        mov     ebx, [esi]
 | 
						|
        add     esi, 4
 | 
						|
 | 
						|
diagonal_loop:
 | 
						|
        and     [edi], al
 | 
						|
        ror     al, 1
 | 
						|
        adc     edi, ecx
 | 
						|
        dec     ebx
 | 
						|
        jnz     short diagonal_loop
 | 
						|
 | 
						|
        sub     edi, ecx                        ; side step
 | 
						|
        cmp     esi, ebp
 | 
						|
        jl      short next_diagonal
 | 
						|
 | 
						|
        pop     ebp
 | 
						|
        mov     esi, pStrips
 | 
						|
        mov     [esi].ST_pjScreen, edi
 | 
						|
        mov     [esi].ST_jBitmask, al
 | 
						|
        cRet    vStripSolidDiagonalHorizontal
 | 
						|
 | 
						|
endProc vStripSolidDiagonalHorizontal
 | 
						|
 | 
						|
;--------------------------Private-Routine------------------------------;
 | 
						|
; vStripSolidDiagonalVertical
 | 
						|
;
 | 
						|
;   Draw a y-major near-diagonal strip left-to-right
 | 
						|
;
 | 
						|
;-----------------------------------------------------------------------;
 | 
						|
 | 
						|
cProc   vStripSolidDiagonalVertical,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     al,  [esi].ST_jBitMask
 | 
						|
        mov     edi, [esi].ST_pjScreen
 | 
						|
        add     esi, offset ST_alStrips
 | 
						|
 | 
						|
;                   al  = bit mask
 | 
						|
;                   ebx = pixel count
 | 
						|
;                   ecx = delta
 | 
						|
;                   edx = port #
 | 
						|
;                   esi = strip pointer
 | 
						|
;                   edi = memory pointer
 | 
						|
;                   ebp = end of strips pointer
 | 
						|
 | 
						|
next_diagonal:
 | 
						|
        mov     ebx, [esi]
 | 
						|
        add     esi, 4
 | 
						|
 | 
						|
diagonal_loop:
 | 
						|
        and      [edi], al
 | 
						|
        ror     al, 1
 | 
						|
        adc     edi, ecx
 | 
						|
        dec     ebx
 | 
						|
        jnz     short diagonal_loop
 | 
						|
 | 
						|
        rol     al, 1                           ; side step
 | 
						|
        sbb     edi, 0
 | 
						|
        cmp     esi, ebp
 | 
						|
        jl      short next_diagonal
 | 
						|
 | 
						|
        pop     ebp
 | 
						|
        mov     esi, pStrips
 | 
						|
        mov     [esi].ST_pjScreen, edi
 | 
						|
        mov     [esi].ST_jBitmask, al
 | 
						|
        cRet    vStripSolidDiagonalVertical
 | 
						|
 | 
						|
endProc vStripSolidDiagonalVertical
 | 
						|
 | 
						|
;--------------------------Private-Routine------------------------------;
 | 
						|
; vStripSolidHorizontal
 | 
						|
;
 | 
						|
;   Draw a horizontal strip left to right
 | 
						|
;
 | 
						|
;-----------------------------------------------------------------------;
 | 
						|
 | 
						|
cProc   vStripSolidHorizontal,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     edx, [esi].ST_lNextScan
 | 
						|
        mov     al,  [esi].ST_jBitMask
 | 
						|
        mov     edi, [esi].ST_pjScreen
 | 
						|
        add     esi, offset ST_alStrips
 | 
						|
 | 
						|
;       (al)  = rotating bit
 | 
						|
;       (bl)  = current mask
 | 
						|
;       (ecx) = pixel count
 | 
						|
;       (edx) = delta
 | 
						|
;       (esi) = strip pointer
 | 
						|
;       (edi) = display pointer
 | 
						|
;       (ebp) = end of strips pointer
 | 
						|
 | 
						|
next_horizontal:
 | 
						|
        mov     ecx, [esi]
 | 
						|
        add     esi, 4
 | 
						|
 | 
						|
        lea     ebx, [2 * eax - 1]      ; bl = start mask
 | 
						|
        ror     al, cl                  ; rotate bit
 | 
						|
        shr     ecx, 3                  ; compute # bytes to lay down
 | 
						|
        cmp     bl, al                  ; we have to adjust for wrap
 | 
						|
        adc     ecx, 0
 | 
						|
        jnz     short extends_out_of_first_byte
 | 
						|
 | 
						|
        sub     bl, al                  ; zero out end bits
 | 
						|
        sub     bl, al
 | 
						|
        inc     bl
 | 
						|
        and     [edi], bl               ; write result
 | 
						|
        add     edi, edx                ; increment to next scan
 | 
						|
        cmp     esi, ebp                ; see if done strips
 | 
						|
        jb      short next_horizontal
 | 
						|
 | 
						|
        pop     ebp                     ; we're done
 | 
						|
        mov     esi, pStrips
 | 
						|
        mov     [esi].ST_pjScreen, edi
 | 
						|
        mov     [esi].ST_jBitmask, al
 | 
						|
        cRet    vStripSolidHorizontal
 | 
						|
 | 
						|
extends_out_of_first_byte:
 | 
						|
 | 
						|
; This part gets called when the current strip doesn't fit entirely
 | 
						|
; into one byte:
 | 
						|
 | 
						|
        and     [edi], bl               ; output with start mask
 | 
						|
        inc     edi                     ; go on to next byte
 | 
						|
 | 
						|
        dec     ecx                     ; see if there's any bytes in
 | 
						|
        jnz     short output_bunch      ;    between start and end byte
 | 
						|
 | 
						|
last_byte:
 | 
						|
        lea     ebx, [2 * eax - 1]      ; compute end mask
 | 
						|
        not     bl
 | 
						|
        and     [edi], bl               ; write result
 | 
						|
        add     edi, edx                ; increment to next scan
 | 
						|
        cmp     esi, ebp                ; see if done strips
 | 
						|
        jb      short next_horizontal
 | 
						|
 | 
						|
        pop     ebp                     ; we're done
 | 
						|
        mov     esi, pStrips
 | 
						|
        mov     [esi].ST_pjScreen, edi
 | 
						|
        mov     [esi].ST_jBitmask, al
 | 
						|
        cRet    vStripSolidHorizontal
 | 
						|
 | 
						|
output_bunch:
 | 
						|
 | 
						|
; We have a bunch of complete bytes to lay down.
 | 
						|
 | 
						|
        mov     ebx, esi                ; we're gonna overwrite esi
 | 
						|
        mov     esi, edi
 | 
						|
        rep     movsb                   ; Write the bytes.  Mask is 0ffh because
 | 
						|
                                        ; we're in read mode 1, reading 0ffh,
 | 
						|
                                        ; which becomes the write mode 3 mask.
 | 
						|
 | 
						|
        mov     esi, ebx                ; restore esi
 | 
						|
 | 
						|
        jmp     short last_byte         ; do last byte in scan
 | 
						|
 | 
						|
endProc vStripSolidHorizontal
 | 
						|
 | 
						|
;--------------------------Private-Routine------------------------------;
 | 
						|
; vStripSolidHorizontalSet
 | 
						|
;
 | 
						|
;   Draw horizontal strips left to right for SRCCOPY lines.
 | 
						|
;
 | 
						|
;-----------------------------------------------------------------------;
 | 
						|
 | 
						|
cProc   vStripSolidHorizontalSet,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     edx, [esi].ST_lNextScan
 | 
						|
        mov     al,  [esi].ST_jBitMask
 | 
						|
        mov     edi, [esi].ST_pjScreen
 | 
						|
        add     esi, offset ST_alStrips
 | 
						|
 | 
						|
;       (al)  = rotating bit
 | 
						|
;       (bl)  = current mask
 | 
						|
;       (ecx) = pixel count
 | 
						|
;       (edx) = delta
 | 
						|
;       (esi) = strip pointer
 | 
						|
;       (edi) = display pointer
 | 
						|
;       (ebp) = end of strips pointer
 | 
						|
 | 
						|
next_horizontal:
 | 
						|
        mov     ecx, [esi]
 | 
						|
        add     esi, 4
 | 
						|
 | 
						|
        lea     ebx, [2 * eax - 1]      ; bl = start mask
 | 
						|
        ror     al, cl                  ; rotate bit
 | 
						|
        shr     ecx, 3                  ; compute # bytes to lay down
 | 
						|
        cmp     bl, al                  ; we have to adjust for wrap
 | 
						|
        adc     ecx, 0
 | 
						|
        jnz     short extends_out_of_first_byte
 | 
						|
 | 
						|
        sub     bl, al                  ; zero out end bits
 | 
						|
        sub     bl, al
 | 
						|
        inc     bl
 | 
						|
        and     [edi], bl               ; write result
 | 
						|
        add     edi, edx                ; increment to next scan
 | 
						|
        cmp     esi, ebp                ; see if done strips
 | 
						|
        jb      short next_horizontal
 | 
						|
 | 
						|
        pop     ebp                     ; we're done
 | 
						|
        mov     esi, pStrips
 | 
						|
        mov     [esi].ST_pjScreen, edi
 | 
						|
        mov     [esi].ST_jBitmask, al
 | 
						|
        cRet    vStripSolidHorizontalSet
 | 
						|
 | 
						|
extends_out_of_first_byte:
 | 
						|
 | 
						|
; This part gets called when the current strip doesn't fit entirely
 | 
						|
; into one byte:
 | 
						|
 | 
						|
        and     [edi], bl               ; output with start mask
 | 
						|
        inc     edi                     ; go on to next byte
 | 
						|
 | 
						|
        dec     ecx                     ; see if there's any bytes in
 | 
						|
        jnz     short output_bunch      ;    between start and end byte
 | 
						|
 | 
						|
last_byte:
 | 
						|
        lea     ebx, [2 * eax - 1]      ; compute end mask
 | 
						|
        not     bl
 | 
						|
        and     [edi], bl               ; write result
 | 
						|
        add     edi, edx                ; increment to next scan
 | 
						|
        cmp     esi, ebp                ; see if done strips
 | 
						|
        jb      short next_horizontal
 | 
						|
 | 
						|
        pop     ebp                     ; we're done
 | 
						|
        mov     esi, pStrips
 | 
						|
        mov     [esi].ST_pjScreen, edi
 | 
						|
        mov     [esi].ST_jBitmask, al
 | 
						|
        cRet    vStripSolidHorizontalSet
 | 
						|
 | 
						|
output_bunch:
 | 
						|
 | 
						|
; We have a bunch of complete bytes to lay down.  Since we're doing
 | 
						|
; the interior of the line and we have a SRCCOPY ROP, we don't have
 | 
						|
; to worry about loading the latches properly, so we can do this
 | 
						|
; without reading the VGA memory.  We also use 16 bit writes since
 | 
						|
; on some devices it's faster to write a single word than to write
 | 
						|
; two bytes -- doing so means we must be word-aligned.
 | 
						|
 | 
						|
        test    edi, 1
 | 
						|
        jz      now_aligned
 | 
						|
        mov     byte ptr [edi], 0ffh    ; write a byte to get alignment right
 | 
						|
        inc     edi
 | 
						|
        dec     ecx
 | 
						|
        jz      short last_byte         ; maybe that was only byte we had to do
 | 
						|
 | 
						|
now_aligned:
 | 
						|
        shr     ecx, 1                  ; divide by 2 to determine the number
 | 
						|
                                        ; of words to write
 | 
						|
                                        ; NOTE: We check the carry later on!
 | 
						|
 | 
						|
        jz      short last_byte_in_bunch ; small optimization: skip word stuff
 | 
						|
                                         ; if we've only got a single byte
 | 
						|
 | 
						|
        mov     ebx, eax                ; save eax
 | 
						|
        mov     eax, 0ffffh             ; prepare ax
 | 
						|
        rep     stosw                   ; lay those words down
 | 
						|
        mov     eax, ebx                ; restore eax
 | 
						|
        jnc     short last_byte         ; NOTE: NOW we're checking the carry!
 | 
						|
 | 
						|
last_byte_in_bunch:
 | 
						|
        mov     byte ptr [edi], 0ffh    ; write that last byte
 | 
						|
        inc     edi
 | 
						|
        jmp     short last_byte
 | 
						|
 | 
						|
endProc vStripSolidHorizontalSet
 | 
						|
 | 
						|
 | 
						|
;--------------------------Private-Routine------------------------------;
 | 
						|
; vStripSolidVertical
 | 
						|
;
 | 
						|
;   Draw a vertical strip left to right
 | 
						|
;
 | 
						|
;-----------------------------------------------------------------------;
 | 
						|
 | 
						|
cProc   vStripSolidVertical,12,<   \
 | 
						|
        uses        esi edi ebx,   \
 | 
						|
        pStrips:    ptr STRIPS,    \
 | 
						|
        pls:        ptr LINESTATE, \
 | 
						|
        plStripEnd: ptr >
 | 
						|
 | 
						|
; Do some initialization:
 | 
						|
 | 
						|
        mov     esi, pStrips
 | 
						|
        mov     edx, plStripEnd
 | 
						|
        mov     ecx, [esi].ST_lNextScan
 | 
						|
        mov     al,  [esi].ST_jBitmask
 | 
						|
        mov     edi, [esi].ST_pjScreen
 | 
						|
        add     esi, offset ST_alStrips
 | 
						|
        mov     [edx], ebp              ; save ebp
 | 
						|
 | 
						|
next_vertical:
 | 
						|
        mov     ebx, [esi]              ; ebx = # bits to set
 | 
						|
        add     esi, 4
 | 
						|
 | 
						|
;       (al)  = rotating bit
 | 
						|
;       (ebx) = # of loops to do
 | 
						|
;       (ecx) = minor add
 | 
						|
;       (edx) = end of strips pointer
 | 
						|
;       (esi) = strip pointer
 | 
						|
;       (edi) = address of byte to write
 | 
						|
;       (ebp) = garbage
 | 
						|
 | 
						|
vertical_strip_loop:
 | 
						|
        and     [edi], al               ; write the byte
 | 
						|
        add     edi, ecx                ; go to next scan
 | 
						|
        dec     ebx
 | 
						|
        jnz     vertical_strip_loop
 | 
						|
 | 
						|
; Adjust address and rotating bit for sidestep:
 | 
						|
 | 
						|
        ror     al, 1                   ; one to the right
 | 
						|
        adc     edi, 0
 | 
						|
 | 
						|
        cmp     esi, edx
 | 
						|
        jl      short next_vertical     ; hit end of array?
 | 
						|
 | 
						|
; Remember where we left off, for next time:
 | 
						|
 | 
						|
        mov     ebp, [edx]              ; restore ebp
 | 
						|
        mov     esi, pStrips
 | 
						|
        mov     [esi].ST_pjScreen, edi
 | 
						|
        mov     [esi].ST_jBitmask, al
 | 
						|
        cRet    vStripSolidVertical
 | 
						|
 | 
						|
endProc vStripSolidVertical
 | 
						|
 | 
						|
;--------------------------Private-Routine------------------------------;
 | 
						|
; vStripStyledHorizontal
 | 
						|
;
 | 
						|
;   Draws an arbitrarily styled horizontal strip left-to-right.
 | 
						|
;
 | 
						|
;-----------------------------------------------------------------------;
 | 
						|
 | 
						|
cProc   vStripStyledHorizontal,12,< \
 | 
						|
        uses        esi edi ebx,    \
 | 
						|
        pStrips:    ptr STRIPS,     \
 | 
						|
        pls:        ptr LINESTATE,  \
 | 
						|
        plStripEnd: ptr >
 | 
						|
 | 
						|
        local   aEnd:dword              ; end of length array
 | 
						|
        local   minoradd:dword
 | 
						|
        local   spToGo:dword
 | 
						|
 | 
						|
; So some initialization:
 | 
						|
 | 
						|
        mov     esi, pStrips
 | 
						|
        mov     eax, plStripEnd
 | 
						|
        mov     aEnd, eax
 | 
						|
 | 
						|
        mov     eax, [esi].ST_lNextScan
 | 
						|
        mov     bl,  [esi].ST_jBitmask
 | 
						|
        mov     edi, [esi].ST_pjScreen
 | 
						|
        mov     minoradd, eax
 | 
						|
 | 
						|
; Initialize styling:
 | 
						|
 | 
						|
        mov     eax, [esi].ST_spRemaining
 | 
						|
        mov     bh,  [esi].ST_jStyleMask
 | 
						|
        mov     spToGo, eax
 | 
						|
        add     esi, offset ST_alStrips
 | 
						|
 | 
						|
Strip_loop:
 | 
						|
        mov     ecx, [esi]              ; ecx = # bits to write
 | 
						|
        add     esi, 4
 | 
						|
 | 
						|
; Now we're going to paste the bytes to the screen
 | 
						|
;
 | 
						|
;       (al)  = used to accumulate the mask
 | 
						|
;       (bl)  = rotating bit
 | 
						|
;       (bh)  = jStyleMask
 | 
						|
;       (ecx) = # of bits to write
 | 
						|
;       (edx) =
 | 
						|
;       (esi) = ptr to spot in ST_alStrips
 | 
						|
;       (edi) = address of byte to write
 | 
						|
 | 
						|
        xor     al, al                  ; clear style mask
 | 
						|
 | 
						|
Strip_count:
 | 
						|
        xor     al, bh                  ; set bit in output mask if style bit 0
 | 
						|
        or      al, bl
 | 
						|
        xor     al, bh
 | 
						|
 | 
						|
        dec     spToGo
 | 
						|
        jz      short Next_style_entry
 | 
						|
 | 
						|
Next_bit:
 | 
						|
        ror     bl, 1
 | 
						|
        jc      short Output_byte
 | 
						|
        dec     ecx
 | 
						|
        jnz     short Strip_count
 | 
						|
 | 
						|
; Do sidestep
 | 
						|
 | 
						|
Side_step:
 | 
						|
        and     byte ptr [edi], al
 | 
						|
        add     edi, minoradd
 | 
						|
 | 
						|
        cmp     esi, aEnd
 | 
						|
        jl      short Strip_loop
 | 
						|
 | 
						|
        mov     esi, pStrips
 | 
						|
        mov     [esi].ST_pjScreen, edi
 | 
						|
        mov     [esi].ST_jBitmask, bl
 | 
						|
        mov     [esi].ST_jStyleMask, bh
 | 
						|
        mov     eax, spToGo
 | 
						|
        mov     [esi].ST_spRemaining, eax
 | 
						|
 | 
						|
        cRet    vStripStyledHorizontal
 | 
						|
 | 
						|
Output_byte:
 | 
						|
        and     byte ptr [edi], al
 | 
						|
        xor     al, al
 | 
						|
        inc     edi                     ; Moved one byte to right on screen
 | 
						|
        dec     ecx
 | 
						|
        jnz     short Strip_count
 | 
						|
        jz      short Side_step
 | 
						|
 | 
						|
; We're on to a new entry in the style array:
 | 
						|
 | 
						|
Next_style_entry:
 | 
						|
        push    eax
 | 
						|
        mov     edx, pStrips
 | 
						|
        mov     eax, [edx].ST_psp
 | 
						|
        add     eax, 4
 | 
						|
        cmp     [edx].ST_pspEnd, eax
 | 
						|
        jae     short @F
 | 
						|
        mov     eax, [edx].ST_pspStart  ; Go back to start of array
 | 
						|
@@:
 | 
						|
        mov     [edx].ST_psp, eax
 | 
						|
        mov     edx, [eax]              ; Load up new style entry
 | 
						|
 | 
						|
        add     spToGo, edx
 | 
						|
        not     bh                      ; jStyleMask = !jStyleMask
 | 
						|
 | 
						|
        pop     eax
 | 
						|
        jmp     short Next_bit
 | 
						|
 | 
						|
endProc vStripStyledHorizontal
 | 
						|
 | 
						|
 | 
						|
;--------------------------Private-Routine------------------------------;
 | 
						|
; vStripStyledVertical
 | 
						|
;
 | 
						|
;   Draw an arbitrarily styled vertical strip left-to-right.
 | 
						|
;
 | 
						|
;-----------------------------------------------------------------------;
 | 
						|
 | 
						|
cProc   vStripStyledVertical,12,<  \
 | 
						|
        uses        esi edi ebx,   \
 | 
						|
        pStrips:    ptr STRIPS,    \
 | 
						|
        pls:        ptr LINESTATE, \
 | 
						|
        plStripEnd: ptr >
 | 
						|
 | 
						|
        local   aEnd:dword              ; end of length array
 | 
						|
        local   minoradd:dword
 | 
						|
        local   spToGo:dword
 | 
						|
 | 
						|
; So some initialization:
 | 
						|
 | 
						|
        mov     esi, pStrips
 | 
						|
        mov     eax, plStripEnd
 | 
						|
        mov     aEnd, eax
 | 
						|
 | 
						|
        mov     ecx, [esi].ST_lNextScan
 | 
						|
        mov     al,  [esi].ST_jBitmask
 | 
						|
        mov     edi, [esi].ST_pjScreen
 | 
						|
        mov     minoradd, ecx
 | 
						|
 | 
						|
; Initialize styling:
 | 
						|
 | 
						|
        mov     ebx, [esi].ST_spRemaining
 | 
						|
        mov     ah,  [esi].ST_jStyleMask
 | 
						|
        mov     spToGo, ebx
 | 
						|
        add     esi, offset ST_alStrips
 | 
						|
 | 
						|
Strip_loop:
 | 
						|
        mov     ebx, [esi]              ; ebx = # bits to set
 | 
						|
        add     esi, 4
 | 
						|
 | 
						|
; Now we're going to paste the bytes to the screen
 | 
						|
;
 | 
						|
;       (al)  = rotating bit
 | 
						|
;       (ah)  = jStyleMask
 | 
						|
;       (ebx) = # of bits to write
 | 
						|
;       (ecx) = minor add
 | 
						|
;       (edx) =
 | 
						|
;       (esi) = ptr to spot in ST_alStrips
 | 
						|
;       (edi) = address of byte to write
 | 
						|
 | 
						|
Strip_count:
 | 
						|
        or      ah, ah
 | 
						|
        jnz     short @F                ; Don't output pixel if in a gap
 | 
						|
        and     [edi], al
 | 
						|
@@:
 | 
						|
        dec     spToGo
 | 
						|
        jz      short Next_style_entry
 | 
						|
 | 
						|
Minor_add:
 | 
						|
        add     edi, ecx
 | 
						|
        dec     ebx
 | 
						|
        jnz     short Strip_count
 | 
						|
 | 
						|
; Adjust address and rotating bit for sidestep
 | 
						|
 | 
						|
        ror     al, 1                   ; one to the right
 | 
						|
        adc     edi, 0
 | 
						|
 | 
						|
        cmp     esi, aEnd
 | 
						|
        jl      short Strip_loop        ; hit end of array?
 | 
						|
 | 
						|
        mov     esi, pStrips
 | 
						|
        mov     [esi].ST_pjScreen, edi
 | 
						|
        mov     [esi].ST_jBitmask, al
 | 
						|
        mov     [esi].ST_jStyleMask, ah
 | 
						|
        mov     eax, spToGo
 | 
						|
        mov     [esi].ST_spRemaining, eax
 | 
						|
 | 
						|
        cRet    vStripStyledVertical
 | 
						|
 | 
						|
Next_style_entry:
 | 
						|
        mov     edx, pStrips
 | 
						|
        mov     ecx, [edx].ST_psp
 | 
						|
        add     ecx, 4
 | 
						|
        cmp     [edx].ST_pspEnd, ecx
 | 
						|
        jae     short @F
 | 
						|
        mov     ecx, [edx].ST_pspStart  ; Go back to start of array
 | 
						|
@@:
 | 
						|
        mov     [edx].ST_psp, ecx       ; Save our pointer
 | 
						|
        mov     edx, [ecx]              ; Load up new style entry
 | 
						|
        add     spToGo, edx
 | 
						|
        not     ah                      ; jStyleMask = !jStyleMask
 | 
						|
 | 
						|
; Restore the registers we used:
 | 
						|
 | 
						|
        mov     ecx, minoradd
 | 
						|
        jmp     short Minor_add
 | 
						|
 | 
						|
endProc vStripStyledVertical
 | 
						|
 | 
						|
 | 
						|
;--------------------------Private-Routine------------------------------;
 | 
						|
; vStripMaskedHorizontal
 | 
						|
;
 | 
						|
;   Draws a mask-styled horizontal strip left to right.
 | 
						|
;
 | 
						|
;-----------------------------------------------------------------------;
 | 
						|
 | 
						|
cProc   vStripMaskedHorizontal,12,< \
 | 
						|
        uses        esi edi ebx,    \
 | 
						|
        pStrips:    ptr STRIPS,     \
 | 
						|
        pls:        ptr LINESTATE,  \
 | 
						|
        plStripEnd: ptr >
 | 
						|
 | 
						|
        local   aEnd:dword              ; end of length array
 | 
						|
        local   minoradd:dword
 | 
						|
        local   density:dword
 | 
						|
 | 
						|
; So some initialization:
 | 
						|
 | 
						|
        mov     esi, pStrips
 | 
						|
        mov     eax, plStripEnd
 | 
						|
        mov     aEnd, eax
 | 
						|
        mov     eax, [esi].ST_lNextScan
 | 
						|
        mov     bl,  [esi].ST_jBitmask
 | 
						|
        mov     edi, [esi].ST_pjScreen
 | 
						|
        mov     minoradd, eax
 | 
						|
 | 
						|
; Initialize styling:
 | 
						|
 | 
						|
        mov     ecx,          [esi].ST_xyDensity
 | 
						|
        mov     ah,  byte ptr [esi].ST_spRemaining
 | 
						|
        mov     bh,           [esi].ST_jStyleMask
 | 
						|
        mov     density, ecx
 | 
						|
        add     esi, offset ST_alStrips
 | 
						|
 | 
						|
Strip_loop:
 | 
						|
        mov     ecx, [esi]              ; ecx = # bits to write
 | 
						|
        add     esi, 4
 | 
						|
 | 
						|
; Now we're going to paste the bytes to the screen
 | 
						|
;
 | 
						|
;       (al)  = used to accumulate style mask
 | 
						|
;       (ah)  = # pixels left in style
 | 
						|
;       (bl)  = rotating bit
 | 
						|
;       (bh)  = style mask
 | 
						|
;       (ecx) = # of bits to write
 | 
						|
;       (esi) = ptr to spot in ST_alStrips
 | 
						|
;       (edi) = address of byte to write
 | 
						|
 | 
						|
        xor     al, al                  ; clear output mask
 | 
						|
 | 
						|
Strip_count:
 | 
						|
        xor     al, bh                  ; set bit in output mask if style bit 0
 | 
						|
        or      al, bl
 | 
						|
        xor     al, bh
 | 
						|
 | 
						|
        dec     ah
 | 
						|
        jnz     short @F
 | 
						|
        rol     bh, 1
 | 
						|
        mov     ah, byte ptr density
 | 
						|
@@:     ror     bh, 1
 | 
						|
        ror     bl, 1
 | 
						|
        jc      short Output_byte
 | 
						|
        dec     ecx
 | 
						|
        jnz     short Strip_count
 | 
						|
 | 
						|
; Do sidestep
 | 
						|
 | 
						|
Side_step:
 | 
						|
        and     byte ptr [edi], al
 | 
						|
        add     edi, minoradd
 | 
						|
 | 
						|
        cmp     esi, aEnd
 | 
						|
        jl      short Strip_loop
 | 
						|
 | 
						|
        mov     esi, pStrips
 | 
						|
 | 
						|
        mov              [esi].ST_pjScreen, edi
 | 
						|
        mov              [esi].ST_jBitmask, bl
 | 
						|
        mov              [esi].ST_jStyleMask, bh
 | 
						|
        mov     byte ptr [esi].ST_spRemaining, ah
 | 
						|
 | 
						|
        cRet    vStripMaskedHorizontal
 | 
						|
 | 
						|
Output_byte:
 | 
						|
        and     byte ptr [edi], al
 | 
						|
        xor     al, al
 | 
						|
        inc     edi
 | 
						|
        dec     ecx
 | 
						|
        jnz     short Strip_count
 | 
						|
        jz      short Side_step
 | 
						|
 | 
						|
endProc vStripMaskedHorizontal
 | 
						|
 | 
						|
;--------------------------Private-Routine------------------------------;
 | 
						|
; vStripMaskedVertical
 | 
						|
;
 | 
						|
;   Draw a mask-styled vertical strip left to right.
 | 
						|
;
 | 
						|
;-----------------------------------------------------------------------;
 | 
						|
 | 
						|
cProc   vStripMaskedVertical,12,<  \
 | 
						|
        uses        esi edi ebx,   \
 | 
						|
        pStrips:    ptr STRIPS,    \
 | 
						|
        pls:        ptr LINESTATE, \
 | 
						|
        plStripEnd: ptr >
 | 
						|
 | 
						|
        local   aEnd:dword              ; end of length array
 | 
						|
        local   minoradd:dword
 | 
						|
        local   density:dword
 | 
						|
 | 
						|
; So some initialization:
 | 
						|
 | 
						|
        mov     esi, pStrips
 | 
						|
        mov     al,  [esi].ST_jBitmask
 | 
						|
        mov     edi, [esi].ST_pjScreen
 | 
						|
        mov     ebx, [esi].ST_lNextScan
 | 
						|
        mov     ecx, plStripEnd
 | 
						|
        mov     minoradd, ebx
 | 
						|
        mov     aEnd, ecx
 | 
						|
 | 
						|
; Initialize styling:
 | 
						|
 | 
						|
        mov     ecx,          [esi].ST_xyDensity
 | 
						|
        mov     ah,  byte ptr [esi].ST_spRemaining
 | 
						|
        mov     bh,           [esi].ST_jStyleMask
 | 
						|
        mov     density, ecx
 | 
						|
        add     esi, offset ST_alStrips
 | 
						|
 | 
						|
Strip_loop:
 | 
						|
        mov     ecx, [esi]              ; ecx = # bits to set
 | 
						|
        add     esi, 4
 | 
						|
 | 
						|
; Now we're going to paste the bytes to the screen
 | 
						|
;       (al) = rotating bit
 | 
						|
;       (ah) = # pixels left in style
 | 
						|
;       (bh) = style mask
 | 
						|
;       (ecx) = # bits to write
 | 
						|
;       (dx) = io address of mask register
 | 
						|
;       (esi) = ptr to spot in ST_alStrips
 | 
						|
;       (edi) = address of byte to write
 | 
						|
 | 
						|
Strip_count:
 | 
						|
        test    bh, al
 | 
						|
        jnz     short @F                ; don't output pixel if style bit is 1
 | 
						|
        and     [edi], al
 | 
						|
@@:
 | 
						|
        dec     ah                      ; we've advanced 1 pel in the style
 | 
						|
        jnz     short @F
 | 
						|
        mov     ah, byte ptr density
 | 
						|
        rol     bh, 1
 | 
						|
@@:
 | 
						|
        add     edi, minoradd
 | 
						|
 | 
						|
        dec     ecx
 | 
						|
        jnz     short Strip_count
 | 
						|
 | 
						|
; Adjust address, style mask and rotating bit for sidestep:
 | 
						|
 | 
						|
        ror     bh, 1                   ; rotate style mask to stay in sync
 | 
						|
        ror     al, 1                   ; move rotating bit one to the right
 | 
						|
        adc     edi, 0
 | 
						|
 | 
						|
        cmp     esi, aEnd
 | 
						|
        jl      short Strip_loop        ; hit end of array?
 | 
						|
 | 
						|
        mov     esi, pStrips
 | 
						|
 | 
						|
        mov              [esi].ST_pjScreen, edi
 | 
						|
        mov              [esi].ST_jBitmask, al
 | 
						|
        mov              [esi].ST_jStyleMask, bh
 | 
						|
        mov     byte ptr [esi].ST_spRemaining, ah
 | 
						|
 | 
						|
        cRet    vStripMaskedVertical
 | 
						|
 | 
						|
endProc vStripMaskedVertical
 | 
						|
 | 
						|
_TEXT$04   ends
 | 
						|
 | 
						|
        end
 |