#
#	Mode 320x200x256 graphics routines 0.26
#	Special version for CT2
# Made by Ismo Horppu on 1996 - 1997
#

#	external/global variable defination
.align 4
.extern _dos_seg
.globl _maxx, _maxy
.globl _minx, _miny
.globl _virtual_buffer_offset

#	global variables defination
.data
.align 4

_minx:
	.int 0

_miny:
	.int 0

_maxx:
	.int 319

_maxy:
	.int 199

#	other variables defination
realx:
	.int 0

realy:
	.int 0

imagex:
	.int 0

imagey:
	.int 0

imageadj:
	.int 0

rightadj:
	.int 0

newwidth:
	.int 0

newheight:
	.int 0

_virtual_buffer_offset:
	.long 0xA0000

.globl _WriteMem
_WriteMem:
		pushl %ebp
		movl %esp, %ebp

		pushw %es
		pushl %edi
		pushl %eax

		movw _dos_seg, %ax
		movw %ax, %es
		movl $0xB8000, %edi
		addl 8(%ebp), %edi
		movl 12(%ebp), %eax
		stosb

		popl %eax
		popl %edi
		popw %es

		popl %ebp
		ret

#	functions
.globl _PutPixel
_PutPixel:
		# make copy of esp (so we won't mess the parameters)
		pushl %ebp
		movl %esp, %ebp

		# save regs being used in this routine
		pushl %edi
		pushl %eax
		pushw %es

		# es = base memory selector
		#movw _dos_seg, %es
		#movw _virtual_buffer_selector, %es

		# calculate VRAM offset (= x + y * xres + VRAM_base)
		movl 12(%ebp), %edi
		movl %edi, %eax
		# eax = edi = Ypos

		xchg %al, %ah
		shll $6, %edi
		addl %eax, %edi
		# edi = Ypos * 320

		#addl _virtual_buffer_offset, %edi
		addl 20(%ebp), %edi
		addl 8(%ebp), %edi
		# edi = VRAM offset

		# get color & write it
		movb 16(%ebp), %al
		movb %al, %es:(%edi)

		# restore regs
		popw %es
		popl %eax
		popl %edi

		# return bp
		popl %ebp
		ret

.globl _GetPixel
_GetPixel:
		# make copy of esp (so we won't mess the parameters)
		pushl %ebp
		movl %esp, %ebp

		# save regs being used in this routine
		pushl %edi
		pushw %es

		# es = base memory selector
		#movw _dos_seg, %es
		#movw _virtual_buffer_selector, %es


		# calculate VRAM offset (= x + y * xres + VRAM_base)
		movl 12(%ebp), %edi
		movl %edi, %eax
		# eax = edi = Ypos

		xchg %al, %ah
		shll $6, %edi
		addl %eax, %edi
		# edi = Ypos * 320

		#addl _virtual_buffer_offset, %edi
		#addl 8(%ebp), %edi
		
		addl 16(%ebp), %edi
		addl 8(%ebp), %edi
		
		# edi = VRAM offset

		# grab color from VRAM
		movb %es:(%edi), %al

		# restore regs
		popw %es
		popl %edi

		# return bp
		popl %ebp
		ret

#
#	very slow 8-bit putimage (no clipping), but a good
#	demonstration/learning source for beginners...
#
.globl _PutImage
_PutImage:
		pushl %ebp
		movl %esp, %ebp

		pushl %esi
		pushl %edi
		pushl %ecx
		pushl %edx
		pushl %ebx
		pushl %eax
		pushw %es

		movw _dos_seg, %es
		#movw _virtual_buffer_selector, %es

		# get image ptr
		movl 8(%ebp), %esi

		# calculate VRAM offset
		movl 16(%ebp), %edi
		movl %edi, %eax
		xchg %al, %ah
		shll $6, %edi
		addl %eax, %edi
		addl _virtual_buffer_offset, %edi
		addl 12(%ebp), %edi

		# grab width & height
		movl 20(%ebp), %ecx
		movl 24(%ebp), %edx

		# calculate step after each line
		movl $320, %ebx
		subl 20(%ebp), %ebx

PutImage_Loop:
		rep
		movsb
		orl 20(%ebp), %ecx
		addl %ebx, %edi
		decl %edx
		jnz PutImage_Loop

		popw %es
		popl %eax
		popl %ebx
		popl %ecx
		popl %edx
		popl %edi
		popl %esi
		popl %ebp
		ret

#
#	very slow 8-bit putinvimage, quite same as above but
#	includes invisible (0) color support
#
.globl _PutInvImage
_PutInvImage:
		pushl %ebp
		movl %esp, %ebp

		pushl %esi
		pushl %edi
		pushl %ecx
		pushl %edx
		pushl %ebx
		pushl %eax
		pushw %es

		movw _dos_seg, %es
		#movw _virtual_buffer_selector, %es


		# get image ptr
		movl 8(%ebp), %esi

		# calculate VRAM offset
		movl 16(%ebp), %edi
		movl %edi, %eax
		xchg %al, %ah
		shll $6, %edi
		addl %eax, %edi
		addl _virtual_buffer_offset, %edi
		addl 12(%ebp), %edi

		# grab width & height
		movl 20(%ebp), %ecx
		movl 24(%ebp), %edx

		# calculate step after each line
		movl $320, %ebx
		subl 20(%ebp), %ebx

PutInvImage_Loop:
		lodsb
		orb %al, %al
		jz PutInvImage_Skip
		stosb
		loop PutInvImage_Loop

		orl 20(%ebp), %ecx
		addl %ebx, %edi
		decl %edx
		jnz PutInvImage_Loop

		popw %es
		popl %eax
		popl %ebx
		popl %ecx
		popl %edx
		popl %edi
		popl %esi
		popl %ebp
		ret

PutInvImage_Skip:
		incl %edi
		loop PutInvImage_Loop

		orl 20(%ebp), %ecx
		addl %ebx, %edi
		decl %edx
		jnz PutInvImage_Loop

		popw %es
		popl %eax
		popl %ebx
		popl %ecx
		popl %edx
		popl %edi
		popl %esi
		popl %ebp
		ret


#
#	fast 32-bit putblock routine (no clipping)
#	this routine is really fast and if you don't
#	need clipping this is must for you
#	(ideal for fast smooth scrolling virtual buffer updating, 'cause
#	this is so fast/32b)
#
.globl _PutBlock
_PutBlock:
		pushl %ebp
		movl %esp, %ebp

		pushl %esi
		pushl %edi
		pushl %ecx
		pushl %edx
		pushl %ebx
		pushl %eax
		pushw %es

		movw _dos_seg, %es
		#movw _virtual_buffer_selector, %es

		# get image ptr
		movl 8(%ebp), %esi

		# calculate VRAM offset
		movl 16(%ebp), %edi
		movl %edi, %eax
		xchg %al, %ah
		shll $6, %edi
		addl %eax, %edi
		#addl _virtual_buffer_offset, %edi
		addl 12(%ebp), %edi

		# grab width & height
		movl 20(%ebp), %ecx
		shrl $2, %ecx
		movl 24(%ebp), %edx

		# calculate step after each line
		movl $320, %ebx
		subl 20(%ebp), %ebx

PutBlock_Loop:
		rep
		movsl
		orl 20(%ebp), %ecx
		shrl $2, %ecx
		addl %ebx, %edi
		decl %edx
		jnz PutBlock_Loop

		popw %es
		popl %eax
		popl %ebx
		popl %ecx
		popl %edx
		popl %edi
		popl %esi
		popl %ebp
		ret

#
#	very slow 8-bit putclippedinvimage, but perfect!
#
.globl _PutClippedInvImage
_PutClippedInvImage:
		pushl %ebp
		movl %esp, %ebp

		pushl %esi
		pushl %edi
		pushl %ecx
		pushl %edx
		pushl %ebx
		pushl %eax
		pushw %es

		#
		#	init variables to defaults
		#
		movw $0, imagey
		movw $0, imageadj
		movw $0, rightadj
		movw 12(%ebp), %ax
		movw %ax, realx
		movw 16(%ebp), %ax
		movw %ax, realy
		movw 20(%ebp), %ax
		movw %ax, newwidth
		movw 24(%ebp), %ax
		movw %ax, newheight

		#movw _dos_seg, %es

		#
		#	clipping code
		#
		movw 12(%ebp), %ax
		cmpw $0, %ax
		jge PCII_NoLeftClip

		#	left clip code
		neg %ax
		cmpw 20(%ebp), %ax
		jge ClippedImage

		#	calculate values needed for clipping
		movw $0, realx
		movw 12(%ebp), %ax
		neg %ax
		movw 20(%ebp), %bx
		subw %ax, %bx
		movw %bx, newwidth
		movw 20(%ebp), %ax
		subw newwidth, %ax
		movw %ax, imageadj
		jmp PCII_NoRightClip

PCII_NoLeftClip:
		movw _maxx, %bx
		incw %bx
		subw 20(%ebp), %bx
		cmpw %bx, %ax
		jle PCII_NoRightClip

		#	calculate newwidth
		movw _maxx, %bx
		subw %ax, %bx
		cmpw $0, %bx
		jl ClippedImage

		#	right clip code (ni)
		incw %bx
		movw %bx, newwidth
		movw 20(%ebp), %ax
		subw %bx, %ax
		movw %ax, rightadj

PCII_NoRightClip:
		#	get ypos
		movw 16(%ebp), %ax
		cmpw $0, %ax
		jge PCII_NoTopClip

		#	top clip code (ni)
		neg %ax
		movw %ax, imagey
		movw $0, realy
		movw 24(%ebp), %bx	# get height
		subw %ax, %bx
		cmpw $0, %bx
		jle ClippedImage
		movw %bx, newheight
		jmp PCII_NoBottomClip

PCII_NoTopClip:
		movw _maxy, %bx
		incw %bx
		subw 24(%ebp), %bx
		cmpw %bx, %ax
		jle PCII_NoBottomClip

		#	bottom clip code (ni)
		movw _maxy, %bx
		incw %bx
		subw %ax, %bx
		cmpw $0, %bx
		jle ClippedImage
		movw %bx, newheight

PCII_NoBottomClip:
		#	calculate start offset for Image
		movl 8(%ebp), %esi
		movzwl imagey, %eax
		xorl %edx, %edx
		imulw 20(%ebp), %ax
		addl %eax, %esi
		addw imageadj, %si
		movw rightadj, %ax
		addw %ax, imageadj

		#	calculate VRAM start offset
		movzwl realy, %edi
		movl %edi, %eax
		xchgb %al, %ah		# ax = y * 256
		shlw $6, %di		# di = y * 64
		addl %eax, %edi		# di = y * 320
		#addl _virtual_buffer_offset, %edi
		addl 28(%ebp), %edi
		movzwl realx, %eax
		addl %eax, %edi

		#	grab width & height
		movzwl newwidth, %ecx
		movzwl newheight, %edx

		#	calculate step after each line
		#	= xres - clipped_image_width
		movl $320, %ebx
		subw newwidth, %bx

PutClippedInvImage_Loop:
		lodsb
		orb %al, %al
		jz PCII_skip
		stosb
		loop PutClippedInvImage_Loop
		addw imageadj, %si
		orw newwidth, %cx
		addl %ebx, %edi
		decl %edx
		jnz PutClippedInvImage_Loop

ClippedImage:
		popw %es
		popl %eax
		popl %ebx
		popl %ecx
		popl %edx
		popl %edi
		popl %esi
		popl %ebp
		ret

PCII_skip:
		incl %edi
		decl %ecx
		jnz PutClippedInvImage_Loop

		addw imageadj, %si
		orw newwidth, %cx
		addl %ebx, %edi
		decl %edx
		jnz PutClippedInvImage_Loop

		popw %es
		popl %eax
		popl %ebx
		popl %ecx
		popl %edx
		popl %edi
		popl %esi
		popl %ebp
		ret

#
#	16-bit putclippedinvimage (quite fast, not perfect)
#
.globl _PutClippedInvImage16
_PutClippedInvImage16:
		pushl %ebp
		movl %esp, %ebp

		pushl %esi
		pushl %edi
		pushl %ecx
		pushl %edx
		pushl %ebx
		pushl %eax
		pushw %es

		#
		#	init variables to defaults
		#
		movw $0, imagey
		movw $0, imageadj
		movw $0, rightadj
		movw 12(%ebp), %ax
		movw %ax, realx
		movw 16(%ebp), %ax
		movw %ax, realy
		movw 20(%ebp), %ax
		movw %ax, newwidth
		movw 24(%ebp), %ax
		movw %ax, newheight

		#movw _dos_seg, %es

		#
		#	clipping code
		#
		movw 12(%ebp), %ax
		cmpw $0, %ax
		jge PCII_NoLeftClip16

		#	left clip code
		neg %ax
		cmpw 20(%ebp), %ax
		jge ClippedImage16

		#	calculate values needed for clipping
		movw $0, realx
		movw 12(%ebp), %ax
		neg %ax
		movw 20(%ebp), %bx
		subw %ax, %bx
		movw %bx, newwidth
		movw 20(%ebp), %ax
		subw newwidth, %ax
		movw %ax, imageadj
		jmp PCII_NoRightClip16

PCII_NoLeftClip16:
		movw _maxx, %bx
		incw %bx
		subw 20(%ebp), %bx
		cmpw %bx, %ax
		jle PCII_NoRightClip16

		#	calculate newwidth
		movw _maxx, %bx
		subw %ax, %bx
		cmpw $0, %bx
		jl ClippedImage16

		#	right clip code (ni)
		incw %bx
		movw %bx, newwidth
		movw 20(%ebp), %ax
		subw %bx, %ax
		movw %ax, rightadj

PCII_NoRightClip16:
		#	get ypos
		movw 16(%ebp), %ax
		cmpw $0, %ax
		jge PCII_NoTopClip16

		#	top clip code (ni)
		neg %ax
		movw %ax, imagey
		movw $0, realy
		movw 24(%ebp), %bx	# get height
		subw %ax, %bx
		cmpw $0, %bx
		jle ClippedImage
		movw %bx, newheight
		jmp PCII_NoBottomClip16

PCII_NoTopClip16:
		movw _maxy, %bx
		incw %bx
		subw 24(%ebp), %bx
		cmpw %bx, %ax
		jle PCII_NoBottomClip16

		#	bottom clip code (ni)
		movw _maxy, %bx
		incw %bx
		subw %ax, %bx
		cmpw $0, %bx
		jle ClippedImage16
		movw %bx, newheight

PCII_NoBottomClip16:
		#	calculate start offset for Image
		movl 8(%ebp), %esi
		movzwl imagey, %eax
		xorl %edx, %edx
		imulw 20(%ebp), %ax
		addl %eax, %esi
		addw imageadj, %si
		movw rightadj, %ax
		addw %ax, imageadj

		#	calculate VRAM start offset
		movzwl realy, %edi
		movl %edi, %eax
		xchgb %al, %ah		# ax = y * 256
		shlw $6, %di		# di = y * 64
		addl %eax, %edi		# di = y * 320
		#addl _virtual_buffer_offset, %edi
		addl 28(%ebp), %edi
		movzwl realx, %eax
		addl %eax, %edi

		#	grab width & height
		movzwl newwidth, %ecx
		movzwl newheight, %edx

		#	calculate step after each line
		#	= xres - clipped_image_width
		movl $320, %ebx
		subw newwidth, %bx

		shrw $1, %cx
		or %cx, %cx
		jz ClippedImage16

PutClippedInvImage_Loop16:
		lodsw
		orw %ax, %ax
		jz inv16                # ax = off

		orb %al, %al
		jz inv8al               # al = off, ah ?

		orb %ah, %ah
		jz inv8ah		# al = on, ah = off

		stosw
cont16:
		loop PutClippedInvImage_Loop16
		addw imageadj, %si
		orw newwidth, %cx
		shrw $1, %cx
		addl %ebx, %edi
		decl %edx
		jnz PutClippedInvImage_Loop16

ClippedImage16:
		popw %es
		popl %eax
		popl %ebx
		popl %ecx
		popl %edx
		popl %edi
		popl %esi
		popl %ebp
		ret

#
#	inv16 code
#
inv16:
		addl $2, %edi
		jmp cont16
#
#	inv8al code
#
inv8al:
		orb %ah, %ah
		jz inv8al_2
		movb %ah, 1(%edi)

inv8al_2:
		addl $2, %edi
		jmp cont16

#
#	inv8ah code
#
inv8ah:
		stosb
		incl %edi
		jmp cont16

#
#	copies virtual buffer to VRAM
#	(very fast 32-bit routine)
#
.globl _RefreshVRAM
_RefreshVRAM:
		pushl %ebp
		movl %esp, %ebp
		pushl %edi
		pushl %esi
		pushl %ecx
		pushl %eax
		pushw %es

		movw _dos_seg, %es
		movl $0xA0000, %edi	# es:edi = VRAM
		movl 8(%ebp), %esi
		movl $16000, %ecx	# copy 64000 bytes
		rep
		movsl

		popw %es
		popl %eax
		popl %ecx
		popl %esi
		popl %edi
		popl %ebp
		ret

#
#	Fast 32-bit virtual buffer clear routine
#
.globl _ClearVB
_ClearVB:
		pushl %ebp
		movl %esp, %ebp
		pushl %edi
		pushl %ecx
		pushl %eax
		pushw %es

		#movw _dos_seg, %es
		movl 8(%ebp), %edi	# es:edi = VRAM
		movl $16000, %ecx	# copy 64000 bytes
		xorl %eax, %eax
		rep
		stosl

		popw %es
		popl %eax
		popl %ecx
		popl %edi
		popl %ebp
		ret
		
.globl _TopBar
_TopBar:
		pushl %ebp
		movl %esp, %ebp
		pushl %edi
		pushl %ecx
		pushl %eax

		movl 8(%ebp), %edi	
		addl $53760, %edi
		movl $2560, %ecx	
		xorl %eax, %eax
		rep
		stosl

		popl %eax
		popl %ecx
		popl %edi
		popl %ebp
		ret
		
.globl _Mem2Mem
_Mem2Mem:
		pushl %ebp
		movl %esp, %ebp
		pushl %esi
		pushl %edi
		
		movl 8(%ebp), %esi
		movl 12(%ebp), %edi
		movl $16000, %ecx
		rep 
		movsl
		
		popl %edi
		popl %esi
		popl %ebp
		ret
