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
|