ReC98/libs/master.lib/draw_trapezoid.asm

208 lines
5.0 KiB
NASM
Raw Normal View History

PAGE 98,120
; gc_poly library - grcg - trapezoid - PC98V
;
; Subroutines:
; draw_trapezoid
;
; Variables:
; trapez_a, trapez_b 台形描画作業変数
;
; Description:
; 台形塗りつぶし(grc_setclip()で設定した領域が対象)
;
; Binding Target:
; asm routine
;
; Running Target:
; NEC PC-9801 Normal mode
;
; Requiring Resources:
; CPU: V30
; GRAPHICS ACCELARATOR: GRAPHIC CHARGER
;
; Assembler:
; TASM 3.0
; OPTASM 1.6
;
; Notes:
; ・グラフィック画面の青プレーンにのみ描画します。
; ・色をつけるには、グラフィックチャージャーを利用してください。
; ・grc_setclip()によるクリッピングに対応しています。
;  y座標が上境界にかかっていると遅くなります。
;  (上境界との交点を計算せずに、上から順に調べているため)
; ・側辺同士が交差している場合、ねじれた台形(2つの三角形が頂点で
;  接している状態)を描画します。
;
; Author:
; 恋塚昭彦
;
; 関連関数:
; grc_setclip()
;
; Revision History:
; 92/3/21 Initial
; 92/3/29 bug fix, 台形に側辺の交差を認めるようにした
; 92/4/2 少々加速
; 92/4/18 三角形ルーチンから分離。クリッピング付加。
; 92/4/19 少々加速
; 92/5/7 自己書き換えにより加速
; 92/5/20 任意クリッピングの横にだけ対応。:-)
; 92/5/22 ↑これも自己書き換え〜
; 92/6/4 grcg_trapezoid()関数をgc_zoid.asmに分割。
; 92/6/5 bugfix(make_lineworkのCXが0の時のdiv 0回避)
; 92/6/5 下端クリップ対応
; 92/6/12 加速〜
; 92/6/16 TASMに対応
; 92/7/13 make_lin.asmを分離
; 93/ 5/29 [M0.18] .CONST->.DATA
; 94/ 2/23 [M0.23] make_lineworkのEXTRNを削除(それだけ(^^;)
; LINEWORK構造体の各メンバの定義
; 名称 - オフセット - 説明
koizoid_x = 0 ; 現在のx座標
koizoid_dlx = 2 ; 誤差変数への加算値
koizoid_s = 4 ; 誤差変数
koizoid_d = 6 ; 最小横移動量(符号付き)
;-------------------------------------------------------------------------
; draw_trapezoid - 台形の描画
; IN:
; SI : unsigned yadr ; 描画する三角形の上のラインの左端のVRAMオフセット
; DX : unsigned ylen ; 描画する三角形の上下のライン差(y2-y1)
; ES : unsigned gseg ; 描画するVRAMのセグメント(ClipYT_seg)
; trapez_a ; 側辺aのxの初期値と傾き
; trapez_b ; 側辺bのxの初期値と傾き
; ClipYB_adr ; 描画するVRAMの最下座標の左端のアドレス
; ClipXL ; 描画するVRAMの左側切り落とし x 座標
; ClipXW ; ClipXLと、右側 x 座標の差(正数)
; BREAKS:
; AX,BX,CX,DX,SI,DI,flags
;
public draw_trapezoid
draw_trapezoid PROC NEAR
mov AX,ClipYB_adr
mov CS:[koizoid_yb_adr],AX
mov AX,[trapez_a+koizoid_d]
mov CS:[koizoid_trapez_a_d],AX
mov AX,[trapez_b+koizoid_d]
mov CS:[koizoid_trapez_b_d],AX
mov AX,[trapez_a+koizoid_dlx]
mov CS:[koizoid_trapez_a_dlx],AX
mov AX,[trapez_b+koizoid_dlx]
mov CS:[koizoid_trapez_b_dlx],AX
mov AX,ClipXL
mov CS:[koizoid_clipxl_1],AX
mov CS:[koizoid_clipxl_2],AX
mov AX,ClipXW
mov CS:[koizoid_clipxw_1],AX
jmp short $+2
push BP
mov CX,[trapez_a+koizoid_x]
mov BP,[trapez_b+koizoid_x]
@@YLOOP:
; 水平線 (with clipping) start ===================================
; IN: SI... x=0の時のVRAM ADDR(y*80) BP,CX... 二つのx座標
cmp SI,1234h
org $-2
koizoid_yb_adr dw ?
ja short @@SKIP_HLINE ; yが範囲外 → skip
mov AX,1234h ; クリップ枠左端分ずらす
org $-2
koizoid_clipxl_1 dw ? ; ClipXL
sub CX,AX
mov BX,BP
sub BX,AX
test CX,BX ; xが共にマイナスなら範囲外
js short @@SKIP_HLINE
cmp CX,BX
jg short @@S10
xchg CX,BX ; CXは必ず非負になる
@@S10:
cmp BH,80h ; if BX < 0 then BX := 0
sbb AX,AX
and BX,AX
mov DI,1234h ; ClipXW
org $-2
koizoid_clipxw_1 dw ?
sub CX,DI ; if CX >= ClipXW then CX := ClipXW
sbb AX,AX
and CX,AX
add CX,DI
sub CX,BX ; CX := bitlen
; BX := left-x
jl short @@SKIP_HLINE ; ともに右に範囲外 → skip
add BX,1234h ; ClipXL
org $-2
koizoid_clipxl_2 dw ?
mov DI,BX ; addr := yaddr + xl div $10 * 2
shr DI,4
shl DI,1
add DI,SI
and BX,0Fh ; BX := xl and $0F
add CX,BX
sub CX,16
shl BX,1
mov AX,[EDGES+BX] ; 左エッジ
not AX
if GAME ge 3
and AX,trapezoid_hmask
endif
mov BX,CX ;
and BX,0Fh
shl BX,1
sar CX,4
js short @@LASTW
stosw
if GAME ge 3
mov AX,trapezoid_hmask
else
mov AX,0FFFFh
endif
rep stosw
@@LASTW: and AX,[EDGES+2+BX] ; 右エッジ
stosw
; 水平線 (with clipping) end ===================================
@@SKIP_HLINE:
add [trapez_a+koizoid_s],1234h
org $-2
koizoid_trapez_a_dlx dw ?
mov CX,[trapez_a+koizoid_x]
adc CX,1234h
org $-2
koizoid_trapez_a_d dw ?
mov [trapez_a+koizoid_x],CX
add [trapez_b+koizoid_s],1234h
org $-2
koizoid_trapez_b_dlx dw ?
adc BP,1234h
org $-2
koizoid_trapez_b_d dw ?
add SI,80 ; yadr
dec DX ; ylen
js short @@OWARI
jmp @@YLOOP ; うぐぐ(;_;)
@@OWARI:
mov [trapez_b+koizoid_x],BP
pop BP
ret
EVEN
draw_trapezoid ENDP