;;	SGFX -- A Small Grafix Library for DOS
;;	Copyright (C) 1996,1997 Nils M. Holm
;;	This version has been modified for use in the TXX runtime engine.
;;	See the file LICENSE for conditions of use.

		.model	large

		.data

X		equ	6
Y		equ	8
X2		equ	10
Y2		equ	12

XLIM		equ	16000
YLIM		equ	12000
FX		equ	50		;; 16000 * 2 / 640
FY		equ	50		;; 12000 * 2 / 480
GCLEAR		equ	0
GSET		equ	1
GOR		equ	2
GXOR		equ	3


		public	_gfx_xmax, _gfx_ymax, _gfx_cmax
		public	_gfx_vmem

copyright	db	"SGFX -- A Small Graphics Library -- "
		db	"Copyright (C) 1996,1997 Nils M. Holm"
gfx_oldmode	db	255
gfx_rowsize	dw	0
_gfx_xmax	dw	0
_gfx_ymax	dw	0
_gfx_cmax	dw	0
_gfx_vmem	dd	0

xinc		dw	0
yinc		dw	0
ainc		dw	0
binc		dw	0
delta		dw	0

lmask		db	0
rmask		db	0
lbord		dw	0
rbord		dw	0

		public	_Fx, _Fy
_Fx		dw	?
_Fy		dw	?


		.code

		public	__g_init, _g_end, _g_point
		public	_g_box, _g_line, _g_clear
		public	_g_reshaped


;;	int _g_init(void);
;;
__g_init	PROC

		mov	ax,0f00h
		int	10h
		mov	gfx_oldmode,al

		mov	ax,0011h
		int	10h
		mov	ax,0f00h
		int	10h
		cmp	al,11h
		jz	init1

		mov	ax,-1
		ret

init1:		mov	gfx_rowsize,80
		mov	_gfx_xmax,640
		mov	_gfx_ymax,480
		mov	_gfx_cmax,2
		mov	word ptr _gfx_vmem,0
		mov	word ptr _gfx_vmem+2,0a000h

		mov	_Fx,50
		mov	_Fy,50

		xor	ax,ax
		ret

__g_init	ENDP


;;	void g_end(void);
;;
_g_end		PROC

		mov	al,gfx_oldmode
		cmp	al,255
		jz	endend

		xor	ah,ah
		int	10h

endend:		ret

_g_end		ENDP


gscale2		PROC NEAR
		mov	bx,FX
		mov	cx,FY
		mov	ax,[bp+6]
		add	ax,XLIM
		xor	dx,dx
		div	bx
		cmp	ax,640
		jb	noclp1
		dec	ax
noclp1:	
		mov	[bp+6],ax
		mov	ax,[bp+8]
		add	ax,YLIM
		xor	dx,dx
		div	cx
		cmp	ax,480
		jb	noclp1a
		dec	ax
noclp1a:	
		mov	[bp+8],ax
		ret
ENDP		gscale2


gscale4		PROC NEAR
		mov	bx,FX
		mov	cx,FY
		mov	ax,[bp+6]
		add	ax,XLIM
		xor	dx,dx
		div	bx
		cmp	ax,640
		jb	noclp2
		dec	ax
noclp2:	
		mov	[bp+6],ax
		mov	ax,[bp+8]
		add	ax,YLIM
		xor	dx,dx
		div	cx
		cmp	ax,480
		jb	noclp2a
		dec	ax
noclp2a:	
		mov	[bp+8],ax
		mov	ax,[bp+10]
		add	ax,XLIM
		xor	dx,dx
		div	bx
		cmp	ax,640
		jb	noclp3
		dec	ax
noclp3:	
		mov	[bp+10],ax
		mov	ax,[bp+12]
		add	ax,YLIM
		xor	dx,dx
		div	cx
		cmp	ax,480
		jb	noclp3a
		dec	ax
noclp3a:	
		mov	[bp+12],ax
		ret
ENDP		gscale4


;;	void g_point(int x, int y, int c);
;;
_g_point	PROC

		push	bp
		mov	bp,sp
		call	gscale2

		push	es

		mov	ax,word ptr _gfx_vmem+2
		mov	es,ax

		mov	ax,[bp+Y]
		mov	dx,[bp+X]
		mov	bx,[bp+10]

		call	far ptr gfxplot

		pop	es
		pop	bp
		ret

_g_point	ENDP


gfxplot		PROC

		push	bx
		push	dx
		mov	cx,gfx_rowsize
		mul	cx
		mov	bx,ax
		mov	cl,3
		pop	dx
		mov	ax,dx
		shr	dx,cl
		add	bx,dx
		and	al,7
		mov	ah,7
		xchg	al,ah
		sub	al,ah
		mov	cl,al
		mov	al,1
		shl	al,cl

		pop	cx
		or	cx,cx	;; cmp cx,GCLEAR
		jz	clrpx

		cmp	cx,GXOR
		jz	xorpx

		or	es:[bx],al
		ret

xorpx:		xor	es:[bx],al
		ret

clrpx:		xor	al,255
		and	es:[bx],al
		ret

gfxplot		ENDP


;;	========== g_line() subroutines ==========

doswap:		mov	ax,[bp+Y]
		mov	bx,[bp+Y2]
		mov	[bp+Y2],ax
		mov	[bp+Y],bx
		mov	ax,[bp+X]
		mov	bx,[bp+X2]
		mov	[bp+X2],ax
		mov	[bp+X],bx
		ret


xline:		mov	ax,[bp+Y]
		cmp	ax,[bp+Y2]
		jle	noswap1
		call	doswap
noswap1:	mov	yinc,1		;; yinc = y2>y2 -> 1, -1;
		mov	ax,[bp+X2]
		cmp	ax,[bp+X]
		jg	noneg1
		neg	yinc

noneg1:		mov	dx,[bp+Y2]	;; dx = x2-x1
		sub	dx,[bp+Y]
		mov	bx,[bp+X2]	;; dy = abs(y2-y1)
		sub	bx,[bp+X]
		jns	nosign1
		neg	bx

nosign1:	mov	ax,bx		;; delta = 2*dy - dx
		shl	ax,1
		sub	ax,dx
		mov	delta,ax
		mov	ax,bx		;; ainc = 2 * (dy-dx)
		sub	ax,dx
		shl	ax,1
		mov	ainc,ax
		shl	bx,1		;; binc = 2*dy
		mov	binc,bx

		mov	si,[bp+Y]
		mov	di,[bp+X]

		mov	ax,si		;; plot(x, y, c)
		mov	dx,di
		mov	bx,[bp+14]
		call	gfxplot
		inc	si

		mov	cx,[bp+Y2]
		sub	cx,si
		inc	cx
		or	cx,cx
		jz	endxl

line1:		cmp	delta,0
		jl	noinc1
		add	di,yinc
		mov	dx,delta
		add	dx,ainc
		mov	delta,dx
		jmp	incd1
noinc1:		mov	dx,delta
		add	dx,binc
		mov	delta,dx
incd1:		mov	ax,si
		mov	dx,di
		mov	bx,[bp+14]
		push	cx
		call	gfxplot
		pop	cx
		inc	si
		loop	line1
endxl:		ret


yline:		mov	ax,[bp+X]
		cmp	ax,[bp+X2]
		jle	noswap2
		call	doswap
noswap2:	mov	xinc,1		;; xinc = x2>x2 -> 1, -1;
		mov	ax,[bp+Y2]
		cmp	ax,[bp+Y]
		jg	noneg2
		neg	xinc

noneg2:		mov	dx,[bp+X2]	;; dy = y2-y1
		sub	dx,[bp+X]
		mov	bx,[bp+Y2]	;; dx = abs(x2-x1)
		sub	bx,[bp+Y]
		jns	nosign2
		neg	bx

nosign2:	mov	ax,bx		;; delta = 2*dx - dy
		shl	ax,1
		sub	ax,dx
		mov	delta,ax
		mov	ax,bx		;; ainc = 2 * (dx-dy)
		sub	ax,dx
		shl	ax,1
		mov	ainc,ax
		shl	bx,1		;; binc = 2*dy
		mov	binc,bx

		mov	si,[bp+Y]
		mov	di,[bp+X]

		mov	ax,si		;; plot(x, y, c)
		mov	dx,di
		mov	bx,[bp+14]
		call	gfxplot
		inc	di

		mov	cx,[bp+X2]
		sub	cx,di
		inc	cx
		or	cx,cx
		jz	endyl

line2:		cmp	delta,0
		jl	noinc2
		add	si,xinc
		mov	dx,delta
		add	dx,ainc
		mov	delta,dx
		jmp	incd2
noinc2:		mov	dx,delta
		add	dx,binc
		mov	delta,dx
incd2:		mov	ax,si
		mov	dx,di
		mov	bx,[bp+14]
		push	cx
		call	gfxplot
		pop	cx
		inc	di
		loop	line2
endyl:		ret

;;	void g_line(int x, int y, int dx, int dy, int c);
;;
PROC		_g_line

		push	bp
		mov	bp,sp
		call	gscale4

		push	es
		push	si
		push	di
		mov	ax,word ptr _gfx_vmem+2
		mov	es,ax

		mov	ax,[bp+Y2]
		sub	ax,[bp+Y]
		jns	_p1
		neg	ax
_p1:		mov	bx,[bp+X2]
		sub	bx,[bp+X]
		jns	_p2
		neg	bx
_p2:		cmp	ax,bx
		jge	_doxline
		call	yline
		jmp	_done
_doxline:	call	xline

_done: 		pop	di
		pop	si
		pop	es
		pop	bp
		ret
_g_line		ENDP


;;	void g_box(int x, int y, int dx, int dy, int c);
;;
_g_box		PROC

		push	bp
		mov	bp,sp
		call	gscale4

		mov	ax,[bp+X]
		cmp	ax,[bp+X2]
		jl	x_lt_dx
		xchg	ax,[bp+X2]
		mov	[bp+X],ax
x_lt_dx:	mov	ax,[bp+Y]
		cmp	ax,[bp+Y2]
		jl	y_lt_dy
		xchg	ax,[bp+Y2]
		mov	[bp+Y],ax
y_lt_dy:
		push	es
		push	si
		push	di

		mov	ax,word ptr _gfx_vmem+2
		mov	es,ax

		mov	cx,[bp+X]
		and	cx,7
		xor	al,al
		or	cx,cx
		jz	endshr
		mov	al,80h
		cmp	cx,1
		jle	endshr
		dec	cx
shrnxt:		sar	al,1
		loop	shrnxt

endshr:		xor	al,255
		mov	lmask,al
		mov	cx,[bp+X2]
		and	cx,7
		xor	al,al
		or	cx,cx
		jz	endshl
		mov	al,80h
		cmp	cx,1
		jle	endshl
		dec	cx
shlnxt:		sar	al,1
		loop	shlnxt

endshl:		mov	rmask,al
		mov	ax,[bp+X]
		mov	cl,3
		shr	ax,cl
		mov	lbord,ax
		mov	ax,[bp+X2]
		shr	ax,cl
		mov	rbord,ax
		cmp	ax,lbord
		jnz	fillwide

		mov	al,lmask
		xor	al,rmask
		xor	al,255
		mov	lmask,al

		mov	cx,[bp+Y2]
		mov	bx,[bp+Y]
		sub	cx,bx
		inc	cx
		mov	ax,gfx_rowsize
		mul	bx
		mov	bx,ax
		add	bx,lbord
		mov	al,lmask

		mov	dx,gfx_rowsize
		cmp	word ptr [bp+14],0
		jz	nclear

		cmp	word ptr [bp+14],2
		jz	putnext2

putnext1:	or	es:[bx],al
		add	bx,dx
		loop	putnext1
		jmp	endbox

nclear:		xor	al,255
putnext0:	and	es:[bx],al
		loop	putnext0
		jmp	endbox

putnext2:	xor	es:[bx],al
		add	bx,dx
		loop	putnext2
		jmp	endbox

fillwide:	mov	cx,[bp+Y2]
		mov	bx,[bp+Y]
		sub	cx,bx
		inc	cx
		mov	ax,gfx_rowsize
		mul	bx
		mov	bx,ax
		add	bx,lbord
		mov	dx,cx

		mov	cl,3
		mov	si,[bp+X2]
		shr	si,cl
		mov	di,[bp+X]
		shr	di,cl
		sub	si,di
		dec	si
		cld	

		cmp	word ptr [bp+14],GCLEAR
		jz	wclear

		cmp	word ptr [bp+14],GXOR
		jz	nextrow2

nextrow1:	mov	di,bx
		mov	al,lmask
		or	es:[di],al
		inc	di
		or	si,si
		jz	skip1
		mov	cx,si
		mov	al,255
		rep	stosb
skip1:		mov	al,rmask
		or	es:[di],al
		add	bx,gfx_rowsize
		dec	dx
		jnz	nextrow1
		jmp	endbox

wclear:		xor	lmask,255
		xor	rmask,255
nextrow0:	mov	di,bx
		mov	al,lmask
		and	es:[di],al
		inc	di
		or	si,si
		jz	skip0
		mov	cx,si
		xor	al,al
		rep	stosb
skip0:		mov	al,rmask
		and	es:[di],al
		add	bx,gfx_rowsize
		dec	dx
		jnz	nextrow0
		jmp	endbox

nextrow2:	mov	di,bx
		mov	al,lmask
		xor	es:[di],al
		inc	di
		or	si,si
		jz	skip2
		mov	cx,si
wfill:		xor	byte ptr es:[di],255
		inc	di
		loop	wfill
skip2:		mov	al,rmask
		xor	es:[di],al
		add	bx,gfx_rowsize
		dec	dx
		jnz	nextrow2

endbox:		pop	di
		pop	si
		pop	es
		pop	bp
		ret

_g_box		ENDP


;;	void g_clear(int mode);
;;
_g_clear	PROC

		push	bp
		mov	bp,sp
		push	es
		push	di

		mov	ax,word ptr _gfx_vmem+2
		mov	es,ax

		mov	ax,gfx_rowsize
		mov	cx,_gfx_ymax
		mul	cx
		mov	cx,ax

		mov	ax,[bp+6]
		or	ax,ax
		jz	clear0
		mov	al,0ffh
		jmp	clear
clear0:		xor	al,al

clear:		cld
		xor	di,di
		rep	stosb

		pop	di
		pop	es
		pop	bp
		ret

_g_clear	ENDP


;;	int g_reshaped(void);
;;
_g_reshaped	PROC
		xor	ax,ax
		ret
		ENDP


		END
