;
;	effect display functions for 'Magl.exp'
;
;			programmed by MALOR
;
	.386p

HeaderSize	equ	32/4
Plane2	equ	0104h
Plane1	equ	010ch

CODE	segment dword public use32 'CODE'
	assume cs:CODE,ds:DATA

;void falcom(int xbyte,int sy,int sofs,int slofs,int dseg,int dofs,int dlofs);
	public falcom
	db	'falcom',6
	align	4
falcom	proc

	pushad

	mov	eax,ss:[esp+36+0]		;x loop count
	mov	ds:[xloopc],eax
	mov	eax,ss:[esp+36+4]		;y loop count
	mov	ds:[yloopc],eax
	mov	esi,ss:[esp+36+8]		;souce offset
	mov	ds:[sofs],esi
	mov	eax,ss:[esp+36+12]		;souce 1line offset
	mov	ds:[slofs],eax
	mov	eax,ss:[esp+36+16]		;dest. selecter
	mov	es,ax
	mov	edi,ss:[esp+36+20]		;dest. offset
	mov	ds:[vofs],edi
	mov	eax,ss:[esp+36+24]		;dest. 1line offset
	mov	ds:[vlofs],eax

	xor	ebx,ebx
	align	4
#loop1:	mov	edi,ds:[vofs]
	mov	edx,ds:[yloopc]
	sub	edx,ebx
	align	4
#loop2:	mov	ecx,ds:[xloopc]
	shr	ecx,2
	rep movsd
	mov	ecx,ds:[xloopc]
	and	ecx,3
	rep movsb

	sub	esi,ds:[xloopc]
	sub	edi,ds:[xloopc]
	sub	edi,ds:[vlofs]

	dec	edx
	jnz	short #loop2

	add	esi,ds:[slofs]

	add	edi,ds:[vlofs]
	add	edi,ds:[vlofs]

	mov	ecx,ds:[xloopc]		;2ライン毎にしてしまえ!
	shr	ecx,2
	rep movsd
	mov	ecx,ds:[xloopc]
	and	ecx,3
	rep movsb

	sub	esi,ds:[xloopc]
	add	esi,ds:[slofs]

	add	ebx,2
;	inc	ebx
	cmp	ebx,ds:[yloopc]
	jb	short #loop1
;	jne	short #loop1

	mov	ax,ds
	mov	es,ax

	popad

	ret

falcom	endp

;void slide(int xbyte,int sy,int sofs,int slofs,int dseg,int dofs,int dlofs);
	public slide
	db	'slide',5
	align	4
slide	proc

	pushad

	mov	eax,ss:[esp+36+0]		;x loop count
	mov	ds:[xloopc],eax
	mov	eax,ss:[esp+36+4]		;y loop count
	mov	ds:[yloopc],eax
	mov	esi,ss:[esp+36+8]		;souce offset
	mov	ds:[sofs],esi
	mov	eax,ss:[esp+36+12]		;souce 1line offset
	mov	ds:[slofs],eax
	mov	eax,ss:[esp+36+16]		;dest. selecter
	mov	es,ax
	mov	edi,ss:[esp+36+20]		;dest. offset
	mov	ds:[vofs],edi
	mov	eax,ss:[esp+36+24]		;dest. 1line offset
	mov	ds:[vlofs],eax

	mov	ebx,0
	align	4
#loop1:	inc	ebx
	mov	edi,ds:[vofs]
	mov	esi,ds:[sofs]
	add	esi,ds:[xloopc]
	sub	esi,ebx
	mov	edx,ds:[yloopc]
	align	4
#loop2:	mov	ecx,ebx
	shr	ecx,2
	rep movsd
	mov	ecx,ebx
	and	ecx,3
	rep movsb
	sub	esi,ebx
	add	esi,ds:[slofs]
	add	esi,ds:[slofs]
	sub	edi,ebx
	add	edi,ds:[vlofs]
	add	edi,ds:[vlofs]
	sub	edx,2
	ja	#loop2

	mov	esi,ds:[sofs]
	add	esi,ds:[slofs]
	mov	edi,ds:[vofs]
	add	edi,ds:[vlofs]
	add	edi,ds:[xloopc]
	sub	edi,ebx
	mov	edx,ds:[yloopc]
	dec	edx
	align	4
#loop3:	mov	ecx,ebx
	shr	ecx,2
	rep movsd
	mov	ecx,ebx
	and	ecx,3
	rep movsb
	sub	esi,ebx
	add	esi,ds:[slofs]
	add	esi,ds:[slofs]
	sub	edi,ebx
	add	edi,ds:[vlofs]
	add	edi,ds:[vlofs]
	sub	edx,2
	ja	short #loop3

;	cmp	ebx,ds:[xloopc]		;1ドット毎のHigh-quality Version
;	jne	#loop1

	add	ebx,7			;8ドット毎だけど実用的な速さVersion
	cmp	ebx,ds:[xloopc]
	jb	#loop1

	mov	ax,ds
	mov	es,ax

	popad

	ret

slide	endp

;void sima2(int xbyte,int sy,int sofs,int slofs,int dseg,int dofs,int dlofs,int step);

	public sima2
	db	'sima2',5
	align	4
sima2	proc

	pushad

	mov	eax,ss:[esp+36+0]		;x loop count
	mov	ds:[xloopc],eax
	mov	eax,ss:[esp+36+4]		;y loop count
	mov	ds:[yloopc],eax
	mov	esi,ss:[esp+36+8]		;souce offset
	mov	ds:[sofs],esi
	mov	eax,ss:[esp+36+12]		;souce 1line offset
	mov	ds:[slofs],eax
	mov	eax,ss:[esp+36+16]		;dest. selecter
	mov	es,ax
	mov	edi,ss:[esp+36+20]		;dest. offset
	mov	ds:[vofs],edi
	mov	eax,ss:[esp+36+24]		;dest. 1line offset
	mov	ds:[vlofs],eax
	mov	eax,ss:[esp+36+28]		;dest. 1line offset
	mov	ds:[step],eax

	mov	eax,ds:[yloopc]
	mul	ds:[xloopc]
	mov	ecx,eax
	mov	ebp,eax
	xor	ebx,ebx
	align	4
#loop1:	add	ebx,ds:[step]
	cmp	ecx,ebx
	jnc	#next
	sub	ebx,ecx
	align	4
#next:	movsb
	mov	eax,ebx
	div	ds:[xloopc]
	mov	esi,ds:[sofs]
	add	esi,edx
	mov	edi,ds:[vofs]
	add	edi,edx
	push	eax
	mul	ds:[slofs]
	add	esi,eax
	pop	eax
	mul	ds:[vlofs]
	add	edi,eax
	dec	ebp
	jnz	#loop1

	mov	ax,ds
	mov	es,ax

	popad

	ret

sima2	endp

;void mosaic(int xbyte,int sy,int sofs,int slofs,int dseg,int dofs,int dlofs,int dx,int dy,int midofs);
	public mosaic
	db	'mosaic',5
	align	4
mosaic	proc

	pushad

	mov	eax,ss:[esp+36+0]		;x loop count
	mov	ds:[xloopc],eax
	mov	eax,ss:[esp+36+4]		;y loop count
	mov	ds:[yloopc],eax
	mov	esi,ss:[esp+36+8]		;souce offset
	mov	ds:[sofs],esi
	mov	eax,ss:[esp+36+12]		;souce 1line offset
	mov	ds:[slofs],eax
	mov	eax,ss:[esp+36+16]		;dest. selecter
	mov	fs,ax
	mov	edi,ss:[esp+36+20]		;dest. offset
	mov	ds:[vofs],edi
	mov	eax,ss:[esp+36+24]		;dest. 1line offset
	mov	ds:[vlofs],eax
	mov	ebp,ss:[esp+36+28]		;mosaic xsize
	mov	ds:[dxloopc],ebp
	mov	eax,ss:[esp+36+32]		;mosaic ysize
	mov	ds:[dyloopc],eax
	mov	eax,ss:[esp+36+36]		;mosaic middle offset
	mov	ds:[midofs],eax

	mov	edx,ds:[yloopc]

#loop1:
	cmp	edx,ds:[dyloopc]
	jnb	#next1
	mov	ds:[dyloopc],edx
#next1:	
	mov	ax,ds
	mov	es,ax

	mov	ebp,ds:[dxloopc]
	mov	edi,offset linebuf
	mov	eax,ds:[xloopc]
	mov	ds:[xloopc1],eax
	align	4
#loop2:	cmp	ds:[xloopc1],ebp
	jnb	#next2
	mov	ebp,ds:[xloopc1]
#next2:

	add	esi,ds:[midofs]
	mov	al,ds:[esi]
	sub	esi,ds:[midofs]
	mov	ah,al
	and	al,0fh
	shl	ah,4
	or	al,ah
	mov	ah,al
	movzx	ebx,ax
	shl	eax,16
	or	eax,ebx				;eax = alalalal  :-)

	mov	ecx,ebp
	shr	ecx,2
	rep stosd
	mov	ecx,ebp
	and	ecx,3
	rep stosb

	add	esi,ebp

	sub	ds:[xloopc1],ebp
	jnz	short #loop2

	mov	ax,fs
	mov	es,ax

	mov	ebx,ds:[dyloopc]
	mov	edi,ds:[vofs]
#loop3:	mov	esi,offset linebuf

	mov	ecx,ds:[xloopc]
	shr	ecx,2
	rep movsd
	mov	ecx,ds:[xloopc]
	and	ecx,3
	rep movsb

	mov	edi,ds:[vofs]
	add	edi,ds:[vlofs]
	mov	ds:[vofs],edi

	dec	ebx
	jnz	short #loop3

	push	edx
	mov	eax,ds:[slofs]
	mul	ds:[dyloopc]
	mov	esi,ds:[sofs]
	add	esi,eax
	mov	ds:[sofs],esi
	pop	edx

	sub	edx,ds:[dyloopc]
	jnz	#loop1

	mov	ax,ds
	mov	es,ax
	mov	fs,ax

	popad

	ret

mosaic	endp

;void mosaic256(int xbyte,int sy,int sofs,int slofs,int dseg,int dofs,int dlofs,int dx,int dy,int midofs);
	public mosaic256
	db	'mosaic256',9
	align	4
mosaic256	proc

	pushad

	mov	eax,ss:[esp+36+0]		;x loop count
	mov	ds:[xloopc],eax
	mov	eax,ss:[esp+36+4]		;y loop count
	mov	ds:[yloopc],eax
	mov	esi,ss:[esp+36+8]		;souce offset
	mov	ds:[sofs],esi
	mov	eax,ss:[esp+36+12]		;souce 1line offset
	mov	ds:[slofs],eax
	mov	eax,ss:[esp+36+16]		;dest. selecter
	mov	fs,ax
	mov	edi,ss:[esp+36+20]		;dest. offset
	mov	ds:[vofs],edi
	mov	eax,ss:[esp+36+24]		;dest. 1line offset
	mov	ds:[vlofs],eax
	mov	ebp,ss:[esp+36+28]		;mosaic xsize
	mov	ds:[dxloopc],ebp
	mov	eax,ss:[esp+36+32]		;mosaic ysize
	mov	ds:[dyloopc],eax
	mov	eax,ss:[esp+36+36]		;mosaic middle offset
	mov	ds:[midofs],eax

	mov	edx,ds:[yloopc]

#loop1:
	cmp	edx,ds:[dyloopc]
	jnb	#next1
	mov	ds:[dyloopc],edx
#next1:	
	mov	ax,ds
	mov	es,ax

	mov	ebp,ds:[dxloopc]
	mov	edi,offset linebuf
	mov	eax,ds:[xloopc]
	mov	ds:[xloopc1],eax
	align	4
#loop2:	cmp	ds:[xloopc1],ebp
	jnb	#next2
	mov	ebp,ds:[xloopc1]
#next2:

	add	esi,ds:[midofs]
	mov	al,ds:[esi]
	sub	esi,ds:[midofs]
	mov	ah,al
	mov	bx,ax
	shl	eax,16
	or	eax,ebx				;eax = alalalal

	mov	ecx,ebp
	shr	ecx,2
	rep stosd
	mov	ecx,ebp
	and	ecx,3
	rep stosb

	add	esi,ebp

	sub	ds:[xloopc1],ebp
	jnz	short #loop2

	mov	ax,fs
	mov	es,ax

	mov	ebx,ds:[dyloopc]
	mov	edi,ds:[vofs]
#loop3:	mov	esi,offset linebuf

	mov	ecx,ds:[xloopc]
	shr	ecx,2
	rep movsd
	mov	ecx,ds:[xloopc]
	and	ecx,3
	rep movsb

	mov	edi,ds:[vofs]
	add	edi,ds:[vlofs]
	mov	ds:[vofs],edi

	dec	ebx
	jnz	short #loop3

	push	edx
	mov	eax,ds:[slofs]
	mul	ds:[dyloopc]
	mov	esi,ds:[sofs]
	add	esi,eax
	mov	ds:[sofs],esi
	pop	edx

	sub	edx,ds:[dyloopc]
	jnz	#loop1

	mov	ax,ds
	mov	es,ax
	mov	fs,ax

	popad

	ret

mosaic256	endp

;void nijimi(int xbyte,int sy,int sofs,int slofs,int dseg,int dofs,int dlofs);
	public nijimi
	db	'nijimi',6
	align	4
nijimi	proc

	pushad

	mov	eax,ss:[esp+36+0]		;x loop count
	mov	ds:[xloopc],eax
	mov	eax,ss:[esp+36+4]		;y loop count
	mov	ds:[yloopc],eax
	mov	esi,ss:[esp+36+8]		;souce offset
	mov	ds:[sofs],esi
	mov	eax,ss:[esp+36+12]		;souce 1line offset
	mov	ds:[slofs],eax
	mov	eax,ss:[esp+36+16]		;dest. selecter
	mov	es,ax
	mov	edi,ss:[esp+36+20]		;dest. offset
	mov	ds:[vofs],edi
	mov	eax,ss:[esp+36+24]		;dest. 1line offset
	mov	ds:[vlofs],eax

	mov	edi,ds:[vofs]
	mov	edx,ds:[yloopc]
	align	4
#loop2:	mov	ecx,ds:[xloopc]
#loop1:	lodsb
	mov	ah,al
	mov	bx,ax
	and	ax,0f00fh
	shr	bh,4
	shl	bl,4
	or	ax,bx
	stosw
	loop	#loop1

	sub	esi,ds:[xloopc]
	sub	edi,ds:[xloopc]
	sub	edi,ds:[xloopc]
	add	esi,ds:[slofs]
	add	edi,ds:[vlofs]

	dec	edx
	jnz	short #loop2

	mov	ax,ds
	mov	es,ax

	popad

	ret

nijimi	endp

;int	setpal(int count,int wight,int nwight,char *beforepal,char *afterpal,int start);

	public setpal
	db	'setpal',6
setpal	proc

	mov	dx,0440h
	mov	al,30
	out	dx,al
	inc	dx
	inc	dx
	in	ax,dx
	and	ax,0c000h
	jz	#exit				;VSYNCでなければexit

#wait:
	in	ax,dx
	and	ax,0c000h
	jnz	short #wait

	push	ebx
	push	ebp
	push	esi
	push	edi
	cli

	mov	ecx,ss:[esp+20+0]			;転送色数
	mov	eax,ss:[esp+20+4]			;基本の重み
	mov	ds:[wight],al
	mov	eax,ss:[esp+20+8]			;目標の重み
	mov	ds:[nwight],al
	mov	esi,ss:[esp+20+12]			;基本パレット
	mov	edi,ss:[esp+20+16]			;目標パレット
	mov	ebp,ss:[esp+20+20]			;色開始番号
	mov	dx,0fd90h

	align	4
#loop:
	mov	dl,90h
	mov	ax,bp
	out	dx,al				;色番号
	inc	bp
	lodsb
	mul	ds:[wight]
	mov	bx,ax
	mov	al,ds:[edi]
	inc	edi
	mul	ds:[nwight]
	add	bx,ax
	shr	bx,6				;(apal*wight+bpal*nwight) / 32
	mov	al,bl
	mov	dl,92h
	out	dx,al				;青
	lodsb
	mul	ds:[wight]
	mov	bx,ax
	mov	al,ds:[edi]
	inc	edi
	mul	ds:[nwight]
	add	bx,ax
	shr	bx,6
	mov	al,bl
	mov	dl,94h
	out	dx,al				;赤
	lodsb
	mul	ds:[wight]
	mov	bx,ax
	mov	al,ds:[edi]
	inc	edi
	mul	ds:[nwight]
	add	bx,ax
	shr	bx,6
	mov	al,bl
	mov	dl,96h
	out	dx,al				;緑
	loop	#loop

	xor	eax,eax				;return -1
	dec	eax
	sti
	pop	edi
	pop	esi
	pop	ebp
	pop	ebx
#Exit:

	ret

setpal	endp

;void cls(int xbyte,int sy,int dseg,int dofs,int dlofs);
	public cls
	db	'cls',3
	align	4
cls	proc

	pushad

	mov	eax,ss:[esp+36+0]		;x loop count
	mov	ds:[xloopc],eax
	mov	eax,ss:[esp+36+4]		;y loop count
	mov	ds:[yloopc],eax
	mov	eax,ss:[esp+36+8]		;dest. selecter
	mov	es,ax
	mov	edi,ss:[esp+36+12]		;dest. offset
	mov	ds:[vofs],edi
	mov	eax,ss:[esp+36+16]		;dest. 1line offset
	mov	ds:[vlofs],eax

	xor	eax,eax
	mov	ebx,ds:[yloopc]
	align	4
#loop1:	mov	ecx,ds:[xloopc]
	shr	ecx,2
	rep stosd
	mov	ecx,ds:[xloopc]
	and	ecx,3
	rep stosb

	sub	edi,ds:[xloopc]
	add	edi,ds:[vlofs]

	dec	ebx
	jnz	#loop1

	mov	ax,ds
	mov	es,ax

	popad

	ret

cls	endp

CODE	ends

DATA	segment dword
	assume ds:DATA

xloopc	dd	0
yloopc	dd	0
sofs	dd	0
slofs	dd	0
vofs	dd	0
vlofs	dd	0

xloopc1	dd	0
dyloopc	dd	0
dxloopc	dd	0

step	dd	23

wight	db	0
nwight	db	0

midofs	dd	0

	align	4
linebuf	db	1024 dup(?)

DATA	ends

	end
