; VgaMem, 256 colors assembler source, Copr. 1994 Matthias K”ppe

; Major change: capabilities

		INCLUDE	vmemdef.asm
		INCLUDE	grserv.asm

		EXTRN	SelOfs: FAR, PageAddr: FAR, SaveRegs: FAR, \
			RestoreRegs: FAR

CODE		SEGMENT BYTE PUBLIC

Def_Mapping

		PUBLIC	Table_256

GetBPL_256	PROC NEAR
		ARG	x2: WORD, x1: WORD = ArgSize
		push	bp
		mov	bp, sp
		MOV	AX, x2
		SUB	AX, x1
		pop	bp
		retn	ArgSize
GetBPL_256	ENDP

GetSize_256	PROC NEAR
		ARG	y2: WORD, x2: WORD, y1: WORD, x1: WORD = ArgSize
		push	bp
		mov	bp, sp
		MOV	AX, x2
		SUB	AX, x1
		MOV	CX, y2
		SUB	CX, y1
		MUL	CX
		pop	bp
		retn	ArgSize
GetSize_256	ENDP

CS_Addr_256	PROC NEAR
		MOV     SI, _x1
		MOV	CX, _x2
		SUB	CX, SI			; Anzahl Quell-Bytes horizontal
		MOV     AX, _y1
		MUL     BX
		ADD     SI, AX			; Quelle in SI
		MOV     DI, _x3
		MOV     AX, _y3
		MUL     BX
		ADD     DI, AX			; Ziel in DI
		retn
CS_Addr_256	ENDP

CS_Copy_256	PROC NEAR
		MOV	BX, _BPL
		PUSH	DX
		MOV     DX, 03CEH		; GC
		MOV	AX, 0003H		; Data Rotate
		OUT	DX, AX
		MOV	AX, 4005H		; Write Mode 0
		OUT	DX, AX
		MOV	AX, 0001H		; Disable Set/Reset
		OUT	DX, AX
		MOV	DX, 03C4H		; SC
		MOV	AX, 0FF02H		; Map Mask
		OUT	DX, AX
		POP	DX

@@1:		PUSH	CX
		MOV	CX, DX
		PUSH	SI
		PUSH	DI
		REP SEGES MOVSB
		POP	DI
		POP	SI
		ADD     SI, BX
		ADD	DI, BX
		POP	CX
		LOOP    @@1
		retn
CS_Copy_256	ENDP

;
; Image support
;

ImageLong_256	PROC NEAR
		ARG	y2: WORD, x2: WORD, y1: WORD, x1: WORD = ArgSize
		push	bp
		mov	bp, sp
		MOV	AX, x2
		SUB	AX, x1
		INC	AX
		MOV	CX, y2
		SUB	CX, y1
		INC	CX
		MUL	CX
		add	ax, 14			; extra memory for BGI comp
		adc	dx, 0
		pop	bp
		retn	ArgSize
ImageLong_256	ENDP

GetImage_256	PROC NEAR
		ARG	Bitmap: DWORD, y2: WORD, x2: WORD, \
			y1: WORD, x1: WORD = ArgSize
		LOCAL	HorizCount: WORD, VertCount: WORD, \
			BPL: WORD, DSeg: WORD, VSeg: WORD = LocalSize
		enter	LocalSize, 0
		MOV	DX, 03C4H		; SC
		MOV	AX, 0FF02H		; Map Mask
		OUT	DX, AX
		MOV	DX, 03CEH
		MOV	AX, 4005H		; Lesemodus 0
		OUT	DX, AX

		LES	DI, Bitmap
		MOV	AX, x2
		SUB	AX, x1
		CLD
		STOSW
		INC	AX
		MOV	HorizCount, AX

		MOV	AX, y2
		SUB	AX, y1
		STOSW
		INC	AX
		MOV	VertCount, AX

		MOV	AX, y1
		ADD	AX, DrawOrigin.y
		MOV	BX, BytesPerLine
		MOV	BPL, BX
		IMUL	BX

		MOV	SI, x1
		ADD	SI, DrawOrigin.x
		ADD	AX, si
		adc	dx, 0
		add	ax, WORD PTR ActiveLinear32
		adc	dx, WORD PTR ActiveLinear32+2

		call	MapLinear		; dx:ax -> dx:ax

		mov	bx, WindowSize		; a Gr variable
		mov	DSeg, ds
		MOV	VSeg, dx
		mov	si, ax
		cld

@@Line:
		PushMapping DSeg, VSeg, ax
		push	si
		mov	cx, HorizCount
		DoRepMovsb si, bx,, SetDS, WORD
		pop	si
		PopMapping DSeg, VSeg, ax
		add	si, BPL
		MapNext	si, bx, SetDS

		dec	VertCount
		jnz	@@Line

		mov	ds, DSeg
		leave
		retn	ArgSize
GetImage_256	ENDP

Transfer	MACRO	Op, Negate, Back

	IFNB <Back>

  &Op&Negate&Back&b MACRO
		LOCAL	@@0
		lodsb
		cmp	al, BackColor
		jz	SHORT @@0

	  IFNB <Negate>
		not	al
	  ENDIF
		Op	es:[di], al
@@0:
		inc	di
		ENDM

	ELSE

  &Op&Negate&Back&b MACRO
		lodsb
	  IFNB <Negate>
		not	al
	  ENDIF
	  IFIDNI <Op>, <mov>
		stosb
	  ELSE
		Op	es:[di], al
		inc	di
	  ENDIF
		ENDM

  &Op&Negate&Back&w MACRO
		lodsw
	  IFNB <Negate>
		not	ax
	  ENDIF
	  IFIDNI <Op>, <mov>
		stosw
	  ELSE
		Op	es:[di], ax
		add	di, 2
	  ENDIF
		ENDM

	ENDIF

_&Op&Negate&Back& PROC NEAR

	IFB <Back>

	DoRep	di, bx,, SetDS, WORD, &Op&Negate&Back&

	ELSE

	DoRep	di, bx,, SetDS, BYTE, &Op&Negate&Back&

	ENDIF
		retn

		ENDP

		ENDM

TrOffset	MACRO	Op, Negate, Back

		DW	OFFSET _&Op&Negate&Back&

		ENDM

Transfers	MACRO	Op

	Transfer Op
	Transfer Op, n
	Transfer Op,, b
	Transfer Op, n, b

		ENDM

TransferTable	PROC NEAR

	TrOffset mov
	TrOffset xor
	TrOffset or
	TrOffset and

	TrOffset mov, n
	TrOffset xor, n
	TrOffset or, n
	TrOffset and, n

	TrOffset mov,, b
	TrOffset xor,, b
	TrOffset or,, b
	TrOffset and,, b

	TrOffset mov, n, b
	TrOffset xor, n, b
	TrOffset or, n, b
	TrOffset and, n, b

		ENDP

PutImage_256	PROC FAR
		ARG	BitBlt: WORD, Bitmap: DWORD, \
			aty: WORD, atx: WORD = ArgSize
		LOCAL	HorizCount: WORD, BmDelta: WORD, LnDelta: WORD, \
			VertCount: WORD, Left: WORD, Top: WORD, \
			DSeg: WORD, TransProc: WORD, BackColor: BYTE = LocalSize
_PutImage_256:
		enter	LocalSize, 0
		MOV	AX, DrawOrigin.x
		ADD	atx, AX
		MOV	AX, DrawOrigin.y
		ADD	aty, AX
		TEST	MetaState, ms_Record
		JZ	@@NR
		PUSH	LocalSize		; Locals
		PUSH	ArgSize			; Params
		PUSH	0
		MOV	AX, 3			; pushed
		CALL	[ExtSave]
		TEST	MetaState, ms_Record
		JNZ	@@NR
		MOV	AX, MetaOrigin.x
		ADD	atx, AX
		MOV	AX, MetaOrigin.y
		ADD	aty, AX
@@NR:		TEST	MetaState, ms_Draw
		JZ	@@ND

		MOV	DX, 03C4H		; SC
		MOV	AX, 0FF02H		; Map Mask
		OUT	DX, AX
		MOV	DX, 03CEH
		MOV	AX, 4005H		; Lesemodus 0
		OUT	DX, AX

		mov	ax, BkColor
		mov     BackColor, al
		MOV	AX, atx
		MOV	BX, BytesPerLine
		MOV	LnDelta, BX
		MOV	CX, ClipRect.A.x
		SUB	CX, AX
		MOV	BX, 0
		JLE	@@1

		MOV	AX, ClipRect.A.x	; AX wahrer Rand
		MOV	BX, CX			; BX Offset in Bits
@@1:
		MOV	DI, AX			; Bildschirmoffset
		mov	Left, ax

		MOV	AX, aty
		MOV	CX, ClipRect.A.y
		SUB	CX, AX
		MOV	SI, 0
		JLE	@@2

		MOV	AX, ClipRect.A.y
		MOV	SI, CX			; SI vert. Offset in Bits
@@2:
		MOV	Top, AX
		IMUL	BytesPerLine
		ADD	ax, di
		adc	dx, 0			; dx:ax Linear address
		add	ax, WORD PTR ActiveLinear32
		adc	dx, WORD PTR ActiveLinear32+2

		call	MapLinear
		mov	es, dx
		mov	di, ax			; es:di screen address

		mov	cx, si			; CX vert. Offset

		mov	DSeg, ds
		LDS	SI, BitMap
		MOV	AX, [SI]		; horiz. Ausdehnung - 1
		INC	AX
		mov	BmDelta, AX		; Abstand der Bitmap-Zeilen

		imul	cx
		ADD	ax, bx
		adc	dx, 0			; dx:ax linear in bitmap

					; forget about DX
		mov	bx, ax			; bx offset in bitmap

	; clip right

		MOV	AX, atx
		ADD	AX, [SI]
		mov	cx, [si + 2]
		mov	ds, DSeg

		INC	AX
		CMP	AX, ClipRect.B.x
		JLE	@@3

		MOV	AX, ClipRect.B.x
@@3:
		sub	ax, Left
		jle	@@0
		MOV	HorizCount, AX

	; clip down

		MOV	DX, aty
		add	dx, cx
		INC	DX
		CMP	DX, ClipRect.B.y
		JLE	@@4

		MOV	DX, ClipRect.B.y
@@4:
		SUB	DX, top
		JLE	@@0
		MOV	VertCount, DX		; vertikale Anzahl

		ADD	SI, BX
		ADD	SI, 4			; Bitmap-Offset korrigieren

		CLD

		MOV	BX, BitBlt
		shl	bx, 1
		jz 	SHORT @@Simple

		mov	bx, WORD PTR cs:TransferTable[bx]
		mov	TransProc, bx
		mov	bx, WindowSize

@@Line1:
		push	si
		PushMapping DSeg, <WORD PTR Bitmap[2]>, ax
		push	di
		mov	cx, HorizCount
		call	TransProc
		pop	di
		PopMapping DSeg, <WORD PTR Bitmap[2]>, ax
		add	di, LnDelta
		MapNext	di, bx, SetDS
		pop	si
		add	si, BmDelta

		dec	VertCount
		jnz	@@Line1

		jmp	@@0

	;
	; Simple BitBlt'ing
	;

@@Simple:
		mov	bx, WindowSize
@@Line:
		push	si
		PushMapping DSeg, <WORD PTR Bitmap[2]>, ax
		push	di
		mov	cx, HorizCount
		DoRepMovsb di, bx,, SetDS, WORD
		pop	di
		PopMapping DSeg, <WORD PTR Bitmap[2]>, ax
		add	di, LnDelta
		MapNext	di, bx, SetDS
		pop	si
		add	si, BmDelta

		dec	VertCount
		jnz	@@Line

	;
	; End
	;

@@0:
		mov	ds, DSeg
@@ND:
		leave
		retf	ArgSize
PutImage_256	ENDP

	Transfers mov
	Transfers and
	Transfers or
	Transfers xor

MaskImage_256	PROC	NEAR
		ARG	DstImg: DWORD, SrcImg: DWORD = ArgSize
		push	bp
		mov	bp, sp
		mov	bl, BYTE PTR BkColor
		push	ds
		lds	si, DstImg
		les	di, SrcImg
		mov	ax, es:[di]
		mov	[si], ax
		inc	ax
		mov	dx, es:[di+2]
		mov	[si+2], dx
		inc	dx
		mul	dx
		mov	cx, ax
		add	si, 4
		add	di, 4
		mov	al, bl
		cld
		jmp	SHORT @@2
@@1:
		mov	BYTE PTR [si], ah
		inc	si
		dec	cx
		jz	SHORT @@0
@@2:
		scasb
		mov	ah, 0
		jnz	@@1

		mov	ah, 0ffh
		mov	BYTE PTR es:[di-1], 0
		jmp	@@1
@@0:
		pop	ds
		pop	bp
		ret	ArgSize
MaskImage_256	ENDP

Dummy		PROC NEAR
		retn
Dummy		ENDP

Table_256	PROC NEAR
		DW	vmcImage + vmcCopy + vmcBackPut
		DW	vmcImage + vmcBackPut
		DW	GetBPL_256
		DW	GetSize_256
		DW	CS_Addr_256
		DW	CS_Copy_256
		DW	Dummy
		DW	Dummy
		DW	ImageLong_256
		DW	GetImage_256
		DW	_PutImage_256
		DW	MaskImage_256
Table_256	ENDP

CODE		ENDS

		END
