ReC98/libs/master.lib/grcg_polygon_c.asm

394 lines
8.1 KiB
NASM
Raw Normal View History

2014-09-01 04:52:28 +00:00
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