; MetaGraph metafile functions
; Copyright 1994, 96 by Daniel Mahrenholz

include metagr.str
include metagr.con
include grdef.asm
include metagr.def

IDEAL

SEGMENT	data	WORD PUBLIC
ASSUME  ds:data

extrn	ValidBuffer	: Word
extrn	ValidStack	: Word
extrn	DrawPtr		: DWord
extrn	BackPtr		: Word
extrn	ExtPtr		: Word
extrn	EndPtr		: Word
extrn	daError		: Word
extrn	MetaError	: Word
extrn	ErrorProc	: DWord
extrn	MetaStack	: DWord
extrn	csAlias		: Word
extrn	FillFlag	: Word

	SaveBP		dw	?

ENDS

P386

extrn	MemAllocSeg	: far
extrn	CallFreeMem	: near
extrn	InitData	: near

SEGMENT	code	BYTE PUBLIC
ASSUME	cs: code

PROC	Save	NEAR
PUBLIC	Save

; Input	:	CX 	= ParamSize in words
;		DX	= starting address of saved function

	test	[ValidBuffer], 1
	jnz	@@1
	mov	ax, me_Buffer
	call	DefaultErrorProc
@@1:
	cld
	les	di, [DrawPtr]
	mov	si, sp
	add	si, 2				; don't save calling addr
	push	ds
	push	ss
	pop	ds
	mov	bx, cx
	inc	bx				; one word for [Start]
	shl	bx, 1
	cmp	[(TMetaStack es:di).Free], bx
	jb	@@2
	add	di, [(TMetaStack es:di).Top]
	mov     ax, dx
	stosw					; starting address
	rep	movsw				; params
	mov	di, 0
	inc	[(TMetaStack es:di).Count]
	add	[(TMetaStack es:di).Top], bx
	sub	[(TMetaStack es:di).Free], bx
	pop	ds
	retn
@@2:
	pop	ds
	mov	ax, me_Full
	call	DefaultErrorProc

	retn

ENDP

PROC 	DefaultErrorProc far
PUBLIC	DefaultErrorProc

	mov	[daError], ax
	mov	[MetaError], ax
	mov	ebx, [ErrorProc]
	or	ebx, ebx
	jz	@@1
	call	[ErrorProc]
@@1:
	ret

ENDP

PROC	LastError far
PUBLIC	LastError

	mov	ax, [daError]
	mov	[daError], ax
	ret

ENDP

PROC	SaveRegs near
PUBLIC	SaveRegs

	pushf
	cld
	mov	di, SMALL offset (UserRegArea)
	mov	ax, ds
	mov	es, ax
	mov	dx, 03ceh
	mov	al, 3
	out	dx, al
	inc	dx
	in	al, dx
	dec	dx
	stosb
	mov	al, 1
	out	dx, al
	inc	dx
	in	al, dx
	dec	dx
	stosb
	mov	al, 8
	out	dx, al
	inc	dx
	in	al, dx
	dec	dx
	stosb
	mov	al, 5
	out	dx, al
	inc	dx
	in	al, dx
	stosb
	mov	dx, 03c4h
	mov	al, 2
	out	dx, al
	inc	dx
	in	al, dx
	stosb
	popf
	ret

ENDP

PROC 	RestoreRegs near
PUBLIC	RestoreRegs

	pushf
	cld
	mov	si, SMALL offset (UserRegArea)
	mov	dx, 03ceh
	mov	ah, 3
        lodsb
	xchg	ah, al
	out	dx, ax
	mov	ah, 1
	lodsb
	xchg	ah, al
	out	dx, ax
	mov	ah, 8
	lodsb
	xchg	ah, al
	out	dx, ax
	inc	si
	mov	dx, 03c4h
	mov	ah, 2
	lodsb
	xchg	ah, al
	out	dx, ax
	popf
	ret

ENDP

PROC	MetaFunctions far
PUBLIC	MetaFunctions

	mov	ax, [ValidBuffer]
	and	ax, [ValidStack]
	ret

ENDP

PROC	LastMetaError far
PUBLIC	LastMetaError

	mov	ax, [MetaError]
	mov	[MetaError], me_NoError
	ret

ENDP

PROC	MaxBufferSize far
PUBLIC	MaxBufferSize

	mov	ax, (65520-msInfo-msSecurity) and 0fffch
	ret

ENDP

PROC	GetBuffer far
PUBLIC	GetBuffer

	arg	BufSize: Word = ArgSize
	push	bp
	mov	bp, sp
	cmp	[BufSize], (65520-msInfo-msSecurity) and 0fffch
	jna	@@1
	mov	[BufSize], (65520-msInfo-msSecurity) and 0fffch
@@1:
	add	[BufSize], msInfo+msSecurity	; buffer infos and security space
	and	[BufSize], 0fffch		; dword alligned
	push	[BufSize]
	call	MemAllocSeg
	mov	es, dx
	mov	di, ax
	push	dx ax
	or	ax, dx
	jz	@@2
	test	[MetaState], ms_Clear
	jz	@@4
	mov	cx, [BufSize]
	shr	cx, 2
	mov	eax, 0
	rep	stosd
@@4:
	mov	di, 0
	mov	ax, [BufSize]
	mov	[(TMetaStack es:di).Size], ax
	mov	[(TMetaStack es:di).Count], 1
	mov	[(TMetaStack es:di).Top], msInfo
	sub	ax, msInfo+msSecurity
	mov	[(TMetaStack es:di).Free], ax
	mov	bx, [EndPtr]
	mov	[(TMetaStack es:di).EndPtr], bx
	mov	[daError], me_NoError
	jmp	@@3
@@2:
	mov	ax, me_Memory
	call	DefaultErrorProc
@@3:
	pop	ax dx bp
	ret	ArgSize

ENDP

PROC	SetBuffer far
PUBLIC	SetBuffer

	arg	Buffer: DWord = ArgSize
	push	bp
	mov	bp, sp
	mov	eax, [Buffer]
	or	eax, eax
	jnz	@@1
	mov	ax, me_Buffer
	call    DefaultErrorProc
	mov	[ValidBuffer], 0
	jmp	@@2
@@1:
	mov	[DrawPtr], eax
	mov	[daError], me_NoError
	mov	[ValidBuffer], 1
@@2:
	pop	bp
	ret	ArgSize

ENDP

PROC	FreeBuffer far
PUBLIC	FreeBuffer

	arg	Buffer: DWord = ArgSize
	push	bp
	mov	bp, sp
	cmp	[Buffer], 0
	jne	@@1
	mov	ax, me_Buffer
	call	DefaultErrorProc
	jmp	@@2
@@1:
	les	di, [Buffer]
	mov	cx, [es:di]
	push	es di cx
	call	CallFreeMem
	mov	[daError], me_NoError
	mov	eax, [DrawPtr]
	cmp	eax, [Buffer]
	jne	@@2
	mov	[DrawPtr], 0
	mov	[ValidBuffer], 0
@@2:
	pop	bp
	ret	ArgSize

ENDP

PROC	ClearBuffer far
PUBLIC	ClearBuffer

	arg	Buffer: DWord = ArgSize
	push	bp
	mov	bp, sp
	cmp	[Buffer], 0
	jne	@@1
	mov	ax, me_Buffer
	call	DefaultErrorProc
	jmp	@@2
@@1:
	les	di, [Buffer]
	mov	[(TMetaStack es:di).Count], 1
	mov	[(TMetaStack es:di).Top], msInfo
	mov	ax, [(TMetaStack es:di).Size]
	sub	ax, msInfo+msSecurity
	mov	[(TMetaStack es:di).Free], ax
@@2:
	pop	bp
	ret	ArgSize

ENDP

PROC	FullBuffer far
PUBLIC	FullBuffer

	arg	DataSize: Word, Buffer: DWord = ArgSize
	push	bp
	mov	bp, sp
	mov	ax, [(word Buffer)]
	mov	bx, [(word Buffer+2)]
	mov	cx, bx
	or	cx, ax
	jnz	@@1
	mov	ax, me_Buffer
	call	DefaultErrorProc
	mov	ax, 1
	jmp	@@2
@@1:
	mov	es, bx
	mov	di, ax
	mov	bx, [(TMetaStack es:di).Free]
	mov	ax, 0
	cmp	bx, [DataSize]
	ja	@@2
	mov	ax, 1
@@2:
	pop	bp
	ret	ArgSize

ENDP

PROC	SaveExt	far
PUBLIC	SaveExt

	mov	[SaveBP], bp
	test	[ValidBuffer], 1
	jnz	@@1
	mov	ax, me_Buffer
	call	DefaultErrorProc
	jmp	@@2
@@1:
	and	[MetaState], not ms_Play
	mov	bp, sp
	inc	[(word ss:bp+4)]
	and	[(word ss:bp+4)], 0fffeh
	inc	[(word ss:bp+8)]
	and	[(word ss:bp+8)], 0fffeh
	mov	cx, [bp+6]
	mov	dx, cx
	les	di, [DrawPtr]
	mov	bx, cx
	add	bx, msInfo+msSecurity
	add	bx, [bp+4]
	cmp	bx, [(TMetaStack es:di).Free]
	jna	@@3
	mov	ax, me_Full
	call	DefaultErrorProc
	jmp	@@2
@@3:
	mov	di, [(TMetaStack es:di).Top]
	mov	ax, [ExtPtr]
	stosw
	mov	ax, [bp]
	stosw
	mov	ax, [bp+2]
	stosw
	mov	ax, [bp+4]
	stosw
	mov	ax, [bp+8]
	stosw
	push	ds ss
	pop	ds
	mov	si, sp
	add	si, 12
	add	si, [bp+8]
	sub	si, [bp+4]
	mov	cx, [bp+4]
	or	cx, cx
	jz	@@4
	rep	movsb
@@4:
	pop	ds
	mov	ax, bp
	stosw
	mov	ax, [BackPtr]
	stosw
	mov	ax, cs
	stosw
	push	ds ss
	pop	ds
	mov	si, sp
	add	si, 18
	add	si, [bp+8]
	mov	cx, [bp+6]
	rep	movsb
	pop	ds
	add	dx, 16
	add	dx, [bp+4]
	les	di, [DrawPtr]
	sub	[(TMetaStack es:di).Free], dx
	add	[(TMetaStack es:di).Top], dx
	inc	[(TMetaStack es:di).Count]
@@2:
	pop	ax bx
	add	sp, 6
	push	bx ax
	mov	bp, [SaveBP]
	ret

ENDP

PROC	DrawBuffer far
PUBLIC	DrawBuffer

	arg	Buffer: DWord = ArgSize
	push	bp
	mov	bp, sp
	and	[MetaState], not ms_Record
	or	[MetaState], ms_Play
	mov	[SaveBP], bp

IFDEF	uBGI
	test	[MetaState], ms_BGI
	jz	@@1
	call	SaveRegs
@@1:
ENDIF

	test	[ValidBuffer], 1
	jnz	@@7
	mov	ax, me_Buffer
	call	DefaultErrorProc
	jmp	@@11
@@7:
	test	[ValidStack], 1
	jnz	@@8
	mov	ax, me_Stack
	call	DefaultErrorProc
	jmp	@@11
@@8:
	cld
	mov	bx, ds
	les	di, [MetaStack]
	mov	di, 0
	lds	si, [Buffer]
	mov	cx, [(TMetaStack ds:di).Top]
	sub	di, cx
	mov	ax, [(TMetaStack ds:si).Count]
	cmp	ax, 1
	je	@@9
	sub	cx, 10
	add	si, 8
	lodsw
	sub	di, 12
	push	di
	rep	movsb
@@9:
	stosw
	mov	ax, ss
	stosw
	mov	ax, sp
	sub	ax, 2
	stosw
	pop	di
	push	es
	pop	ss
	mov	sp, di
	mov	ds, bx
DBBackPtr:

@@10:
	retn
DBExtPtr:
@@5:
	pop	ax bx di si
	mov	bp, sp
	add	bp, di
	sub	sp, si
	sub	sp, di
	push	bx ax
	retf
@@3:
	jmp	@@10
DBEndPtr:
@@4:
	pop	ax bx
	add	bx, 4
	mov	sp, bx
	mov	ss, ax
@@6:

IFDEF	uBGI
	test	[MetaState], ms_BGI
	jz	@@11
	call	RestoreRegs
ENDIF
@@11:

	mov	bp, [SaveBP]
	pop	bp
	retf	ArgSize

ENDP

PROC	InternalInit near
PUBLIC	InternalInit

	mov	[ValidBuffer], 0
	mov	[ValidStack], 0
	mov	[BackPtr], SMALL Offset DBBackPtr
	mov	[EndPtr],  SMALL offset DBEndPtr
	mov	[ExtPtr],  SMALL Offset DBExtPtr
	mov	ax, cs
	mov	[csAlias], ax
	mov	[FillFlag], Fill_Line
	call	InitData
	ret

ENDP

ENDS

END