	.code16
	.arch	i8086
_start:	.global	_start
	call	screen1
	call	mouseinit
again:	call	mouseon
	call	wait4event
	call	mouseoff
	mov	event_key, %al
	or	$0x20, %al
	cmp	$'q', %al
	je	exit
	cmpb	$1, event_prevb
	jne	1f
	mov	event_y, %ax
	mov	event_x, %bx
	cmp	$320, %bx
	jb	2f
	mov	$319, %bx
2:	cmp	$200, %ax
	jb	2f
	mov	$199, %ax
2:	push	%ax
	push	%bx
	mov	event_prevy, %ax
	mov	event_prevx, %bx
	cmp	$320, %bx
	jb	2f
	mov	$319, %bx
2:	cmp	$200, %ax
	jb	2f
	mov	$199, %ax
2:	push	%ax
	push	%bx
	mov	$3, %cl
	call	line
	add	$2 * 4, %sp
	jmp	again
1:	cmpb	$0, event_prevb
	jne	1f
	cmpb	$2, event_b
	jne	1f
	mov	event_y, %ax
	mov	event_x, %bx
	cmp	$320, %bx
	jb	2f
	mov	$319, %bx
2:	cmp	$200, %ax
	jb	2f
	mov	$199, %ax
2:	push	%ax
	push	%bx
	call	pget
	mov	%al, %cl
	xor	$2, %cl
	pop	%bx
	pop	%ax
	mov	$3, %dl
	push	%dx
	push	%cx
	push	%ax
	push	%bx
	call	paint
	add	$2 * 4, %sp
1:	jmp	again
exit:	int	$0x20
screen1:
	mov	$4, %ax
	int	$0x10
	ret
mouseinit:
	mov	$0, %ax
	int	$0x33
	inc	%ax
	je	1f
	int	$0x20
1:	ret
mouseon:
	mov	$4, %ax
	mov	event_x, %cx
	mov	event_y, %dx
	int	$0x33
	mov	$1, %ax
	int	$0x33
	ret
mouseoff:
	mov	$0, %ax
	int	$0x33
	ret
geta:	# %ax=y %bx=x -> %es:%bx=addr %cl=bit position
	mov	$0xb800, %cx
	shr	%ax
	jnc	1f
	add	$0x200, %cx
1:	add	%ax, %cx
	shl	%ax
	shl	%ax
	add	%ax, %cx
	mov	%cx, %es
	mov	%bl, %cl
	not	%cl
	and	$3, %cl
	shl	%cl
	shr	%bx
	shr	%bx
	ret
pget:	# %ax=y %bx=x -> %al=color
	call	geta
	mov	%es:(%bx), %al
	shr	%cl, %al
	and	$3, %al
	ret
pset:	# %ax=y %bx=x %cl=color
	push	%cx
	call	geta
	pop	%ax
	mov	%al, %ch
	mov	$~3, %al
	rol	%cl, %al
	and	%es:(%bx), %al
	and	$3, %ch
	shl	%cl, %ch
	or	%ch, %al
	mov	%al, %es:(%bx)
	ret
wait4event:
	movb	$0, event_key
3:	mov	$1, %ah
	int	$0x16
	je	1f
	# Key down
	mov	$0, %ah
	int	$0x16
	mov	%al, event_key
	ret
1:	mov	$3, %ax
	int	$0x33
	xor	%ax, %ax
	cmp	%cx, event_x
	jne	1f
	cmp	%dx, event_y
	je	2f
1:	# Mouse move
	mov	event_x, %ax
	mov	%ax, event_prevx
	mov	event_y, %ax
	mov	%ax, event_prevy
	mov	%cx, event_x
	mov	%dx, event_y
	mov	$1, %al
2:	mov	event_b, %cl
	mov	%cl, event_prevb
	test	$3, %cl
	je	1f
	# Previously button down
	and	%cl, %bl
	cmp	%cl, %bl
	je	2f
	# Button up
	mov	%bl, event_b
	ret
2:	test	%ax, %ax
	je	3b
	# Mouse drag
	ret
1:	test	$1, %bl
	je	1f
	# Button 1 down
	movb	$1, event_b
	jmp	2f
1:	test	$2, %bl
	je	3b
	# Button 2 down
	movb	$2, event_b
2:	mov	event_x, %ax
	mov	%ax, event_prevx
	mov	event_y, %ax
	mov	%ax, event_prevy
	ret

event_x:	.space	2
event_y:	.space	2
event_b:	.space	1
event_prevx:	.space	2
event_prevy:	.space	2
event_prevb:	.space	1
event_key:	.space	1

	nop
	nop
	nop
	nop

line:	push	%bp
	mov	%sp, %bp
	# x1	4(%bp)
	# y1	6(%bp)
	# x2	8(%bp)
	# y2	10(%bp)
	# color	-2(%bp)
	# dx	-4(%bp)
	# dy	-6(%bp)
	# ro0	-7(%bp)
	# ro1	-8(%bp)
	# ro2	-9(%bp)
	# ro3	-10(%bp)
	# lo	-12(%bp)
	# s	-14(%bp)
	sub	$14, %sp
	mov	%cl, -2(%bp)
	movb	$1, -7(%bp)
	movb	$0, -8(%bp)
	movb	$0, -9(%bp)
	movb	$1, -10(%bp)
	mov	8(%bp), %ax
	sub	4(%bp), %ax
	jnb	1f
	neg	%ax
	negb	-7(%bp)
1:	mov	%ax, -4(%bp)
	mov	10(%bp), %ax
	sub	6(%bp), %ax
	jnb	1f
	neg	%ax
	negb	-10(%bp)
1:	mov	%ax, -6(%bp)
	cmp	-4(%bp), %ax
	jbe	1f
	mov	-7(%bp), %ah
	mov	-8(%bp), %al
	mov	%al, -7(%bp)
	mov	%ah, -8(%bp)
	mov	-9(%bp), %ah
	mov	-10(%bp), %al
	mov	%al, -9(%bp)
	mov	%ah, -10(%bp)
	mov	-4(%bp), %ax
	mov	-6(%bp), %bx
	mov	%bx, -4(%bp)
	mov	%ax, -6(%bp)
1:	incw	-4(%bp)
	incw	-6(%bp)
	mov	-4(%bp), %ax
	mov	%ax, -12(%bp)
	movw	$0, -14(%bp)
2:	mov	6(%bp), %ax
	mov	4(%bp), %bx
	mov	-2(%bp), %cl
	call	pset
	mov	-6(%bp), %ax
	add	%ax, -14(%bp)
	mov	-4(%bp), %ax
	cmp	%ax, -14(%bp)
	jb	1f
	sub	%ax, -14(%bp)
	mov	-8(%bp), %al
	cbtw
	add	%ax, 4(%bp)
	mov	-10(%bp), %al
	cbtw
	add	%ax, 6(%bp)
1:	mov	-7(%bp), %al
	cbtw
	add	%ax, 4(%bp)
	mov	-9(%bp), %al
	cbtw
	add	%ax, 6(%bp)
	decw	-12(%bp)
	jne	2b
	mov	%bp, %sp
	pop	%bp
	ret

paint:	push	%bp
	mov	%sp, %bp
	# x1		4(%bp)
	# y		6(%bp)
	# fillcolor	8(%bp)
	# wallcolor	10(%bp)
	# x2		-2(%bp)
	# state		-4(%bp)
	# hitlen	-6(%bp)
	# hitaddr	-8(%bp)
	# left		-10(%bp)
	# right		-12(%bp)
	# push up len	-2
	# push dn len	-4
	# push liney	-6
	# push linex1	-8
	# push linex2	-10
	# push up[] x1->x2
	# push dn[] x1->x2
	sub	$12, %sp
	mov	4(%bp), %ax
	mov	%ax, -2(%bp)
	xor	%ax, %ax
	mov	%al, -4(%bp)
	mov	%ax, -6(%bp)
	## A ball is at (x1, y).  Kick the ball to the left.
5:	xor	%ax, %ax
4:	mov	-8(%bp), %si
	mov	-6(%bp), %bx
	mov	4(%bp), %cx
	# %ax min left, %cx max left
1:	sub	$4, %bx
	jb	1f
	cmp	%ax, %ss:(%bx, %si)
	jb	1b
	cmp	%ss:2(%bx, %si), %cx
	jb	1b
	mov	%ss:(%bx, %si), %ax
	inc	%ax
	jmp	1b
1:	lea	-12(%bp), %bx
1:	cmp	%sp, %bx
	jbe	1f
	mov	%ss:-6(%bx), %dx
	cmp	%dx, 6(%bp)
	jne	2f
	cmp	%ax, %ss:-10(%bx)
	jb	2f
	cmp	%ss:-8(%bx), %cx
	jb	2f
	mov	%ss:-10(%bx), %ax
	inc	%ax
2:	mov	%ss:-2(%bx), %dx
	add	%ss:-4(%bx), %dx
	add	$10, %dx
	sub	%dx, %bx
	jmp	1b
1:	cmp	%ax, %cx
	jnb	1f
	# No space on the left.
2:	jmp	3f
1:	mov	%ax, %si
	mov	%cx, %di
	mov	6(%bp), %ax
	mov	%di, %bx
	call	pget
	cmp	10(%bp), %al
	mov	%di, %ax
	je	2b
1:	cmp	%si, %di
	jbe	1f
	dec	%di
	mov	6(%bp), %ax
	mov	%di, %bx
	call	pget
	cmp	10(%bp), %al
	jne	1b
	inc	%di
1:	mov	%di, -10(%bp)
	## A ball is at (x1+1, y).  Kick it to the right.
	mov	-8(%bp), %si
	mov	-6(%bp), %bx
	mov	$319, %cx
	mov	4(%bp), %ax
	inc	%ax
	# %ax min right, %cx max right
1:	sub	$4, %bx
	jb	1f
	cmp	%ax, %ss:(%bx, %si)
	jb	1b
	cmp	%ss:2(%bx, %si), %cx
	jb	1b
	mov	%ss:2(%bx, %si), %cx
	dec	%cx
	jmp	1b
1:	lea	-12(%bp), %bx
1:	cmp	%sp, %bx
	jbe	1f
	mov	%ss:-6(%bx), %dx
	cmp	%dx, 6(%bp)
	jne	2f
	cmp	%ax, %ss:-10(%bx)
	jb	2f
	cmp	%ss:-8(%bx), %cx
	jb	2f
	mov	%ss:-8(%bx), %cx
	dec	%cx
2:	mov	%ss:-2(%bx), %dx
	add	%ss:-4(%bx), %dx
	add	$10, %dx
	sub	%dx, %bx
	jmp	1b
1:	mov	%ax, %si
	mov	%cx, %di
1:	cmp	%si, %di
	jb	1f
	mov	6(%bp), %ax
	mov	%si, %bx
	call	pget
	cmp	10(%bp), %al
	je	1f
	inc	%si
	jmp	1b
1:	dec	%si
	mov	%si, -12(%bp)
	## Paint one line
	mov	8(%bp), %cl
	mov	6(%bp), %ax
	push	%ax
	push	%si
	push	%ax
	pushw	-10(%bp)
	call	line
	add	$2 * 4, %sp
	## Push information
	mov	%sp, %di
	xor	%ax, %ax
	push	%ax
	push	%ax
	pushw	6(%bp)
	mov	-10(%bp), %ax
	mov	-12(%bp), %cx
	push	%ax
	push	%cx
	# Up hit
	lea	-12(%bp), %bx
1:	cmp	%di, %bx
	jbe	1f
	mov	%ss:-6(%bx), %dx
	inc	%dx
	cmp	%dx, 6(%bp)
	jne	2f
	cmp	%ax, %ss:-10(%bx)
	jb	2f
	cmp	%ss:-8(%bx), %cx
	jb	2f
	pushw	%ss:-8(%bx)
	pushw	%ss:-10(%bx)
	addw	$4, %ss:-2(%di)
2:	mov	%ss:-2(%bx), %dx
	add	%ss:-4(%bx), %dx
	add	$10, %dx
	sub	%dx, %bx
	jmp	1b
1:	# Down hit
	lea	-12(%bp), %bx
1:	cmp	%di, %bx
	jbe	1f
	mov	%ss:-6(%bx), %dx
	dec	%dx
	cmp	%dx, 6(%bp)
	jne	2f
	cmp	%ax, %ss:-10(%bx)
	jb	2f
	cmp	%ss:-8(%bx), %cx
	jb	2f
	pushw	%ss:-8(%bx)
	pushw	%ss:-10(%bx)
	addw	$4, %ss:-4(%di)
2:	mov	%ss:-2(%bx), %dx
	add	%ss:-4(%bx), %dx
	add	$10, %dx
	sub	%dx, %bx
	jmp	1b
1:	mov	-12(%bp), %ax
3:	inc	%ax
	mov	%ax, 4(%bp)
	cmp	-2(%bp), %ax
	jnb	1f
	jmp	4b
1:	## State check
	cmpb	$2, -4(%bp)
	jne	1f
4:	movb	$0, -4(%bp)
	# Move information
	lea	-12(%bp), %bx
	mov	%bx, %si
	cmp	%sp, %bx
	jbe	1f
	sub	%ss:-2(%bx), %si
	sub	%ss:-4(%bx), %si
	sub	$10, %si
2:	cmp	%sp, %si
	jbe	3f
	sub	$2, %bx
	sub	$2, %si
	mov	%ss:(%si), %ax
	mov	%ax, %ss:(%bx)
	jmp	2b
3:	mov	%bx, %sp
1:	cmpb	$0, -4(%bp)
	jne	1f
	movb	$1, -4(%bp)
	# Get up-side information
	lea	-12(%bp), %bx
	cmp	%sp, %bx
	jbe	2f
	mov	%ss:-6(%bx), %ax
	sub	$1, %ax
	jb	1f
	mov	%ax, 6(%bp)
	mov	%ss:-8(%bx), %ax
	mov	%ax, 4(%bp)
	mov	%ss:-10(%bx), %ax
	mov	%ax, -2(%bp)
	lea	-10(%bx), %ax
	sub	%ss:-2(%bx), %ax
	mov	%ax, -8(%bp)
	mov	%ss:-2(%bx), %ax
	mov	%ax, -6(%bp)
	jmp	5b
1:	cmpb	$1, -4(%bp)
	jne	2f
	movb	$2, -4(%bp)
	# Get down-side information
	lea	-12(%bp), %bx
	cmp	%sp, %bx
	jbe	2f
	mov	%ss:-6(%bx), %ax
	cmp	$199, %ax
	jae	4b
	inc	%ax
3:	mov	%ax, 6(%bp)
	mov	%ss:-8(%bx), %ax
	mov	%ax, 4(%bp)
	mov	%ss:-10(%bx), %ax
	mov	%ax, -2(%bp)
	lea	-10(%bx), %ax
	sub	%ss:-2(%bx), %ax
	sub	%ss:-4(%bx), %ax
	mov	%ax, -8(%bp)
	mov	%ss:-4(%bx), %ax
	mov	%ax, -6(%bp)
	jmp	5b
2:	## End
	mov	%bp, %sp
	pop	%bp
	ret
