; Gr assembler routines, Copr. 1994 Matthias K”ppe

		INCLUDE	grdef.asm		; Gr Definitions
		INCLUDE	grserv.asm		; Gr Services

		EXTRN	SelOfs: FAR, GrModeTable: FAR, \
			InitGraphics: FAR, CloseGraphics: FAR

_code

		PUBLIC	PageSeg, PageLinear, PageAddr, SegLinear, SegAddr, \
			SetActivePage, SetVisualPage, ReserveSegs, \
			SetFreeSegsBack, GetFreeSegs, SetVgaDispStart, \
			SetGrMode, LinearToAddress, MapToNextWindow, \
			MapToPrevWindow, SetActiveWindow

	; SegToLinear creates a linear video address out of a
	; pseudo segment, using Granularity and MapFlags.
	;
	; in:	ax	pseudo segment
	; out:	dx:ax	linear video address

	Def_SegToLinear

	; SegLinear is a Pascal interface to SegToLinear.

SegLinear	PROC FAR
		ARG	ASeg: WORD = ArgSize
		push	bp
		mov	bp, sp
		mov	ax, ASeg
		call	SegToLinear
		pop	bp
		retf
SegLinear	ENDP

	; SegAddr returns a pointer to the position in the video memory
	; specified by a "segment" value and maps the video memory.

SegAddr		PROC FAR
		ARG	ASeg: WORD = ArgSize
		push	bp
		mov	bp, sp
		mov	ax, ASeg
		call	SegToLinear
		call    MapLinear
		pop	bp
		retf
SegAddr		ENDP

	; GetPageSeg returns the pseudo segment of the specified
	; screen page, or of the current page.
	;
	; in:	bx      page
	; out:	ax	pseudo segment

	Def_GetPageSeg

	; PageSeg is a Pascal interface to GetPageSeg.

PageSeg		PROC FAR
		ARG	APage: WORD = ArgSize
		push	bp
		mov	bp, sp
		mov     bx, APage
		call	GetPageSeg
		pop	bp
		retf	ArgSize
PageSeg		ENDP

	; PageLinear returns the linear video start address of a page.

PageLinear	PROC FAR
		ARG	APage: WORD = ArgSize
		push	bp
		mov	bp, sp
		mov	bx, APage
		call	GetPageSeg
		call	SegToLinear
		pop	bp
		retf	ArgSize
PageLinear	ENDP

	; PageAddr returns a pointer to the beginning of a certain
	; screen page in the video memory and maps the video memory.

PageAddr	PROC FAR
		ARG	APage: WORD = ArgSize
		push	bp
		mov	bp, sp
		push	es bx cx si di
		mov	bx, APage
		call	GetPageSeg
		call	SegToLinear
		call	MapLinear
		pop	di si cx bx es
		pop	bp
		retf    ArgSize
PageAddr	ENDP

	; DoSetActivePage sets the active page but does not
	; send a notification.
	;
	; in:	bx	page

DoSetActivePage	PROC NEAR
		mov	ActivePage, bx
		call	GetPageSeg
		mov	ActiveSeg, ax
		call	SegToLinear
		mov	WORD PTR ActiveLinear32[0], ax
		mov	WORD PTR ActiveLinear32[2], dx
		call	MapLinear
		mov     ActivePOfs, ax
		mov     ActivePSeg, dx
		mov	ax, WindowNum
		mov	ActiveWindow, ax
		retn
DoSetActivePage	ENDP

	; SetActivePage calls DoSetActivePage and the notification.

SetActivePage	PROC FAR
		ARG	APage: WORD = ArgSize
		push	bp
		mov	bp, sp
		mov	bx, APage
		call	DoSetActivePage
		mov     ax, 0
		call    ActivePageProc
		pop	bp
		retf	ArgSize
SetActivePage	ENDP

	; SetVisualPage determines the linear address and calls the
	; low-level SetDispStart procedure.

SetVisualPage	PROC FAR
		ARG	APage: WORD = ArgSize
		push	bp
		mov	bp, sp
		mov	bx, APage
		call	GetPageSeg
		call	SegToLinear
		push	dx ax
		call    SetDispStartProc
		pop	bp
		retf	ArgSize
SetVisualPage	ENDP

	; SetDispStart for VGA devices

SetVgaDispStart	PROC FAR
		ARG	Linear: DWORD = ArgSize
		push	bp
		mov	bp, sp
		mov	bx, WORD PTR Linear[0]
		mov	dx, 03d4h
		mov     al, 0ch
		mov	ah, bh
		out	dx, ax
		inc	al
		mov	ah, bl
		out	dx, ax
		pop	bp
		retf	ArgSize
SetVgaDispStart	ENDP

	; Set logical mode

SetGrMode	PROC FAR
		ARG	Mode: WORD = ArgSize
		push	bp
		mov	bp, sp
		cmp	GrActive, 0
		jz	@@1
		call	CloseGraphics
		mov	GrActive, 1
@@1:
		MOV     BX, DS
		MOV     ES, BX
		MOV     AX, Mode
		MOV     GrMode, AX
		mov	cx, SEG GrModeTable
		mov	ds, cx
		mov	si, OFFSET GrModeTable
		SHL     AX, 2
		ADD     SI, AX
		SHL     AX, 2
		ADD     SI, AX
		MOV     CX, 10
		MOV     DI, OFFSET SizeX
		CLD
		REP     MOVSW
		MOV     DS, BX
		MOV     AX, SizeX
		CMP     GrFlags, 1
		JZ      @@2
		SHR     AX, 3
@@2:
		MOV     RealBytesPerLine, AX
		mov	WORD PTR RealBytesPerLine32[2], 0
		MOV     BytesPerLine, AX
		mov	WORD PTR BytesPerLine32[2], 0
		XOR     AX, AX
		MOV     DI, OFFSET DrawOrigin
		STOSW
		STOSW
		STOSW
		STOSW
		MOV     AX, SizeX
		STOSW
		MOV     AX, SizeY
		STOSW
		mov	ActivePage, 0
		mov	ax, Page0Seg
		mov	ActiveSeg, ax
		mov	ActivePOfs, 0
		mov	ax, SegA000
		mov	ActivePSeg, ax

	; Set mapping data

		mov	WORD PTR WindowAddr[0], 0
		mov	WORD PTR WindowAddr[2], ax
		mov	WindowSize, 0			; $10000
		mov     WORD PTR WindowSize32[2], 1
		mov	OffsetMask, 0FFFFh
		mov	WORD PTR OffsetMask32[2], 0
		mov	MapGranMask, 0FFFFh
		mov	WORD PTR MapGranMask32[2], 0
		mov	GransPerWindow, 1
		mov	MapGranRight, 16
		mov	MapGranLeft, 0
		mov	MapGran32, 0
		mov	WindowNum, 0

	; Initialize graphics if needed

		cmp	GrActive, 0
		jz	@@4
		mov	GrActive, 0
		call	InitGraphics
@@4:		pop	bp
		retf	ArgSize
SetGrMode	ENDP

	; ReserveSegs reserves video memory in granularity units.

ReserveSegs	PROC FAR
		ARG	ASize: WORD = ArgSize
		push	bp
		mov	bp, sp
		MOV     CX, ASize
		CMP     CX, -1
		JNZ     @@1
		MOV     CX, Page1Seg
		ADD     CX, Free1Seg
		SUB     CX, EndSeg
		SUB     CX, Free0Seg
		MOV     BX, OFFSET Free0Seg
		MOV     AX, Page1Seg
		JNS     @@2
		MOV     BX, OFFSET Free1Seg
		MOV     AX, EndSeg
		JMP     @@2
@@1:    	XOR     DX, DX
		MOV     BX, OFFSET Free0Seg
		MOV     AX, [BX]
		ADD     AX, CX
		CMP     AX, Page1Seg
		JB      @@2
		MOV     BX, OFFSET Free1Seg
		MOV     AX, [BX]
		ADD     AX, CX
		CMP     AX, EndSeg
		JB      @@2
		MOV     AX, Page0Seg
		XOR     DX, DX
		pop	bp
		retf	ArgSize
@@2:    	MOV     DX, AX
		SUB     DX, [BX]
		XCHG    AX, [BX]
@@3:            pop	bp
		retf	ArgSize
ReserveSegs	ENDP

SetFreeSegsBack	PROC FAR
		ARG	Segs: DWORD = ArgSize
		push	bp
		mov	bp, sp
		mov	ax, WORD PTR Segs
		cmp	ax, Free0Seg
		jae	@@1			; only backmoves allowed
		mov	Free0Seg, ax
@@1:		mov	ax, WORD PTR Segs [2]
		cmp	ax, Free1Seg
		jae	@@2			; only backmoves allowed
		mov	Free1Seg, ax
@@2:		pop	bp
		retf	ArgSize
SetFreeSegsBack	ENDP

GetFreeSegs	PROC FAR
		mov	ax, Free0Seg
		mov	dx, Free1Seg
		retf
GetFreeSegs	ENDP

;
; video memory mapping support
;

	Def_Mapping

LinearToAddress	PROC FAR
		ARG	Linear: DWORD = ArgSize
		push	bp
		mov	bp, sp
		mov	dx, WORD PTR Linear[2]
		mov	ax, WORD PTR Linear[0]
		call	MapLinear
		pop	bp
		retf
LinearToAddress	ENDP

MapToNextWindow	PROC FAR
		call	NextWindow
		retf
MapToNextWindow	ENDP

MapToPrevWindow	PROC FAR
		call	PrevWindow
		retf
MapToPrevWindow	ENDP

SetActiveWindow	PROC FAR
		push	dx
		mov	dx, ActiveWindow
		call	CallMapAddr
		pop	dx
		retf
SetActiveWindow	ENDP

__code

END
