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
|