ReC98/libs/master.lib/grcg_polygon_c.asm

394 lines
8.1 KiB
NASM
Raw Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

PAGE 98,120
; grcg - polygon - convex - Point
;
; DESCRIPTION:
; 凸多角形描画(青プレーンのみ)
;
; FUNCTION:
; void far _pascal grcg_polygon_c( Point far pts[], int npoint ) ;
;
; PARAMETERS:
; Point pts[] 座標リスト
; int npoint 座標数( 2〜 )
;
; Binding Target:
; Microsoft-C / Turbo-C / Turbo Pascal
;
; Running Target:
; NEC PC-9801 Normal mode
;
; REQUIRING RESOURCES:
; CPU: V30
; GRAPHICS ACCELARATOR: GRAPHIC CHARGER
; ・上記は、すべて draw_trapezoid に依ります。
;
; NOTES:
; ・色指定は、グラフィックチャージャーを使用してください。
; ・クリッピング枠によって描画を制限できます。( grc_setclip()参照 )
; ・左右の境界クリップは、台形描画ルーチンに依存しています。
; ・データが下記の条件に当てはまる場合、正しく描画しません。
; ○同じy座標を経由する辺が2つを超える場所がある場合。
; →条件により、ゼロ除算が発生したり、おかしな図形になります。
; (凸多角形でなくても、上記以外なら正しく描画します)
;
; COMPILER/ASSEMBLER:
; TASM 3.0
; OPTASM 1.6
;
; 関連関数:
; grc_setclip()
; make_linework
; draw_trapezoid
;
; AUTHOR:
; 恋塚昭彦
;
; HISTORY:
; 92/5/18 Initial(C版)
; 92/5/19 bugfix
; 92/5/20 とりあえず、左右と下端のクリップをやった。
; 92/5/21 左右の先判定と、上もクリップしたぞ。(あーのんびり。)
; 92/6/4 Initial(asm版 gc_4corn.asm)
; 92/6/5 gc_polyg.asm
; 92/6/6 ClipYT_seg対応
; 92/6/16 TASM対応
; 92/6/19 gc_polgc.asm
; 92/6/21 Pascal対応
IF datasize EQ 2
MOVPTS macro to, from
mov to,ES:from
endm
CMPPTS macro pts, dat
cmp ES:pts,dat
endm
SUBPTS macro reg,pts
sub reg,ES:pts
endm
LODPTS macro reg
les reg,[BP+@@pts]
endm
ELSE
MOVPTS macro to, from
mov to,from
endm
CMPPTS macro pts, dat
cmp pts,dat
endm
SUBPTS macro reg,pts
sub reg,pts
endm
LODPTS macro reg
mov reg,[BP+@@pts]
endm
ENDIF
MRETURN macro
pop SI
pop DI
leave
ret (datasize+1)*2
EVEN
endm
; void _pascal grcg_polygon_c( Point pts[], int npoint ) ;
;
func GRCG_POLYGON_C
push BP
mov BP,SP
sub SP,12 ; ローカル変数のサイズ
push DI
push SI
; パラメータ
@@pts = (RETSIZE+2)*2
@@npoint = (RETSIZE+1)*2
; ローカル変数
@@ry = -2 ; 左のy
@@ty = -4 ; 上端のy
@@ly = -6 ; 右のy
@@nl = -8 ; 左の点の添え字(byte単位)
@@nr = -10 ; 右の点の添え字(byte単位)
@@by = -12 ; 下端のy
mov AX,[BP+@@npoint]
dec AX
mov CX,AX ; CX = 本来の npoint
shl AX,2
mov [BP+@@npoint],AX ; npoint = (npoint-1)*4
; 頂上を探す〜 ----------------
LODPTS SI ; SI = pts
xor AX,AX
mov [BP+@@nl],AX ; nl = 0
mov [BP+@@nr],AX ; nr = 0
MOVPTS AX,[SI+2]
mov [BP+@@ty],AX ; ty = pts[0].y
mov [BP+@@by],AX ; by = pts[0].y
MOVPTS AX,[SI] ; AX = pts[0].x (AX=lx)
mov DI,AX ; DI = pts[0].x (DI=rx)
mov BX,4 ; BX = 1*4
@@LOOP1: ; x,y の各最大値と最小値を得るループ
MOVPTS DX,[BX+SI+2] ; pts[i].y
cmp DX,[BP+@@ty]
jge short @@S10
mov [BP+@@nl],BX ; nlは、頂上の最初にみつけた点
mov [BP+@@nr],BX ; nrは、頂上の最後に見つけた点
mov [BP+@@ty],DX
jmp short @@S30
EVEN
@@S10:
cmp [BP+@@ty],DX
jne short @@S20
mov [BP+@@nr],BX
jmp short @@S30
EVEN
@@S20:
cmp [BP+@@by],DX
jge short @@S30
mov [BP+@@by],DX
@@S30:
MOVPTS DX,[BX+SI] ; pts[].x
cmp AX,DX
jl short @@S40
mov AX,DX
jmp short @@S50
EVEN
; へんなところに潜ってるが、クリップの近場にreturn処理が
; いるのだ〜
@@RETURN1:
MRETURN
EVEN
@@S40: ; else
cmp DI,DX
jge short @@S50
mov DI,DX
@@S50:
add BX,4
loop short @@LOOP1
; ループ終り ----------------
; 範囲検査
cmp ClipXR,AX
jl short @@RETURN1 ; 完全に右に外れてる
cmp ClipXL,DI
jg short @@RETURN1 ; 完全に左に外れてる
mov AX,[BP+@@ty]
cmp ClipYB,AX
jl short @@RETURN1 ; 完全に下に外れてる
mov DX,[BP+@@by]
cmp ClipYT,DX
jg short @@RETURN1 ; 完全に上に外れてる
; **** さあ、ここに来たからには、かならず描画できるんだぞ。 ****
; (台形による最後のクリップを宛てにしてるから)
; 描画セグメント設定
IF datasize NE 2
mov ES,ClipYT_seg
ENDIF
; 下のy座標を先にクリップ枠で切断する
mov AX,ClipYB
cmp AX,DX
jge short @@S100
mov DX,AX
@@S100:
mov [BP+@@by],DX
; nlが最初、nr最後ならば、入れ換え。わかりにくい〜
; 凸多角形ならば、ある点の他に同じy座標の点はつ以下にしか
; ならない。従って、頂上を共有する点は2つ以内なので、座標列の
; 端をまたがるのはこのパターンのみとなる)
mov AX,[BP+@@npoint]
cmp WORD PTR [BP+@@nl],0
jne short @@S110
cmp [BP+@@nr],AX
jne short @@S110
mov [BP+@@nl],AX
mov WORD PTR [BP+@@nr],0
@@S110:
; 左側辺の、上にはみ出ている部分を飛ばし ***
mov BX,[BP+@@nl] ; BX = nl
mov DX,[BP+@@npoint]
mov AX,ClipYT
@@LOOPL:
mov CX,BX
sub BX,4
jns short @@SKIPL
mov BX,DX
@@SKIPL:
CMPPTS [BX+SI+2],AX
jl short @@LOOPL
MOVPTS AX,[BX+SI+2]
mov [BP+@@ly],AX ; ly = pts[nl].y
mov [BP+@@nl],BX
; 最初の左側辺データを作成
mov BX,CX ; BX = i
MOVPTS DX,[SI+BX+2] ; DX = ty = pts[i].y
MOVPTS DI,[SI+BX] ; DI = wx = pts[i].x
mov BX,[BP+@@nl]
cmp DX,ClipYT
jge short @@S200
mov AX,DX
sub AX,[BP+@@ly] ; push (ty-ly)
PUSH AX
mov AX,DI ; AX = ((DI=wx) - pts[nl].x)
SUBPTS AX,[SI+BX]
mov CX,ClipYT
sub CX,DX ; CX = (ClipYT - (DX=ty))
imul CX
POP CX
idiv CX ; DI = (wx-pts[nl].x) * (ClipYT-ty)
add DI,AX ; / (ty-ly) + wx
mov DX,ClipYT ; ty = ClipYT
@@S200:
mov [BP+@@ty],DX
xchg DI,DX
MOVPTS AX,[SI+BX] ; pts[nl].x
mov CX,[BP+@@ly]
sub CX,DI ; CX = (ly-ty)
mov BX,offset trapez_a
call make_linework
; 右側辺の、上にはみ出ている部分を飛ばし ***
mov BX,[BP+@@nr] ; BX = nr
mov CX,[BP+@@npoint]
mov AX,ClipYT
@@LOOPR:
mov DI,BX ; DI = i
add BX,4 ; BX = nr
cmp BX,CX
jle short @@SKIPR
xor BX,BX
@@SKIPR:
CMPPTS [SI+BX+2],AX
jl short @@LOOPR
MOVPTS AX,[SI+BX+2]
mov [BP+@@ry],AX
mov [BP+@@nr],BX
; 最初の右側辺データを作成
add DI,SI
MOVPTS CX,[DI+2] ; CX = pts[i].y
MOVPTS DI,[DI] ; DI = wx = pts[i].x
MOVPTS BX,[SI+BX] ; BX = pts[nr].x
cmp CX,[BP+@@ty]
jge short @@S300
mov AX,ClipYT ; (ClipYT - pts[i].y)
sub AX,CX
push CX
mov CX,DI ; (wx - pts[nr].x)
sub CX,BX
imul CX
pop CX
sub CX,[BP+@@ry] ; (pts[i].y - ry)
idiv CX
add DI,AX ; + wx
@@S300:
mov DX,DI
mov AX,BX ; pts[nr].x
mov CX,[BP+@@ry]
sub CX,[BP+@@ty]
mov BX,offset trapez_b
call make_linework
; 実際に描画していくんだ[よーん] ========================
mov SI,[BP+@@ty] ; SI = ty
@@DRAWLOOP:
mov DI,[BP+@@ly] ; DI = y2
cmp DI,[BP+@@ry]
jle short @@S400
mov DI,[BP+@@ry]
@@S400:
cmp [BP+@@by],DI ; 下クリップ
jle short @@S500
PUSH DI
lea DX,[DI-1]
sub DX,SI ; DX = y2-1 - ty
sub SI,ClipYT
mov AX,SI ; SI = ty*80
shl SI,2
add SI,AX
shl SI,4
IF datasize EQ 2
mov ES,ClipYT_seg
ENDIF
call draw_trapezoid ; **** DRAW ****
POP SI
LODPTS DI ; DI = pts
cmp SI,[BP+@@ly] ; if ( ty == ly )
jne short @@S410
mov BX,[BP+@@nl]
MOVPTS DX,[BX+DI] ; DX = pts[nl].x
sub BX,4
jns short @@S405
mov BX,[BP+@@npoint]
@@S405:
mov [BP+@@nl],BX
MOVPTS AX,[DI+BX] ; AX = pts[nl].x
MOVPTS CX,[DI+BX+2] ; CX = (ly = pts[nl].y) - ty
mov [BP+@@ly],CX
sub CX,SI
mov BX,offset trapez_a
; DX = last pts[nl].x
call make_linework
@@S410: ; if ( ty == ry )
cmp [BP+@@ry],SI
jne short @@DRAWLOOP
mov BX,[BP+@@nr] ; BX = nr
MOVPTS DX,[BX+DI]
add BX,4
cmp BX,[BP+@@npoint]
jle short @@S420
xor BX,BX
@@S420:
mov [BP+@@nr],BX
MOVPTS AX,[DI+BX] ; AX = pts[nr].x
MOVPTS CX,[DI+BX+2] ; CX = pts[nr].y
mov [BP+@@ry],CX ; ry = CX
sub CX,SI ; CX -= SI
mov BX,offset trapez_b
push offset @@DRAWLOOP
jmp make_linework ; まさか!!
EVEN
; 一番下の台形
@@S500:
IF datasize EQ 2
mov ES,ClipYT_seg
ENDIF
mov DX,[BP+@@by]
sub DX,SI ; DX = by - ty
sub SI,ClipYT
mov AX,SI ; SI = ty*80
shl SI,2
add SI,AX
shl SI,4
call draw_trapezoid
MRETURN
endfunc