; fasm example of writing 16-bit COM program

	org	100h			; code starts at offset 100h
	use16

	inputlen = 40

	mov	ah,09h
	mov	dx,intro
	int	21h
	mov	cx,10
prod:
	mov	bx,cx
	shl	bx,1
	mov	di,[ds:bx+freq]
	mov	bx,25
	call	sound
	loop	prod
		      
	mov	ah,09h
	mov	dx,namereq
	int	21h

	mov	cx,inputlen ; Input name
	mov	ax,3f00h
	xor	bx,bx
	mov	dx,keybuff
	int	21h
	jc	endp
	sub	al,2  ; We won't include the CR/LF as part of the message.
	add	byte [messagelen], al

	mov	ah,02h	; Hide the cursor
	xor	bx,bx
	mov	dx,01900h  ; Row 25, column 0 in hex
	int	10h

	mov	ah,0fh
	int	10h
	cmp	al,7
	jne	.vga
	mov	ax,0b000h
	jmp	.vga2
.vga:
	mov	ax,0b800h
.vga2:
	mov	es,ax
	xor	di,di
	mov	cx,2000
	mov	ax,0301h
	rep	stosw ; Fill screen with cyan 'W's
	xor	di,di
	mov	ah,10h
	int	16h

	call	erasescreen


	mov	si,message
	mov	cx,2000
	xor	bx,bx
	xor	bp,bp
.writemessage2:
	mov	dl,[ds:si+bp]
	mov	[es:bx],dl
	inc	bp
	add	bx,2
	inc	al
	cmp	bp,[messagelen]
	jl	.return2
	xor	bp,bp
.return2:
	dec	cx
	jnz	.writemessage2
	mov	al,1
.startloop:
	and	al,0fh		; We only need the next number between 1 and 15
	jnz	.skip		; If we haven't gone back to 0 skip
	or	al,1		; Otherwise, set back to one.
.skip:
	mov	cx,2000
	mov	dl,al
	mov	bx,1
.loop42:
	mov	byte [es:di+bx],dl
	inc	dl
	and	dl,0fh		; Use the last 4 bits to get a number between 1 and 15
	jnz	.return 	; If zero
	or	dl,1		; Make it one, as we don't want to use black.
.return:
	add	bx,2
	loop	.loop42
	inc	al
;	call	waitretrace
	call	delay
	push	ax
	mov	ah,0bh	; Set border color.  BL already contains colour
	mov	bl,dl
	xor	bh,bh
	int	10h
	mov	ah,01h
	int	16h
	pop	ax
	jz	.startloop

	xor	ax,ax
	int	16h
	mov	ah,0bh	; Reset border to black
	xor	bx,bx
	int	10h

	call	erasescreen

	mov	ah,02h ;Set cursor
	xor	bx,bx
	xor	dx,dx
	int	10h

	mov	ah,09h
	mov	dx,bye
	int	21h
endp:
	mov	ax,4c00h	 ; Send exit code to dos
	int	21h		; Send command to DOS

;waitretrace:
;	push	dx
;	push	ax
;.retrace:
;	mov	dx,03dah
;	in	al,dx
;	test	al,08h
;	jnz	.retrace
;.retrace2:			;
;	in	al,dx
;	test	al,08h
;	jz	.retrace2
;	pop	ax
;	pop	dx
;	ret

delay:
	push	ax
	push	cx
	push	dx
	mov	ah,86h
	mov	cx,1
	mov	dx,0ffffh
	int	15h
	pop	dx
	pop	cx
	pop	ax
	ret

sound:
  ; Frequency in DI register
  ; Duration in BX register (hundredth of a second)
	push	ax
	push	cx
	push	dx
	push	ds
	push	es
	push	si

	in	al,61h
	mov	cl,al
	or	al,3
	out	61h,al
	mov	al,0b6h
	out	43h,al
	mov	dx,14h
	mov	ax,4f38h
	div	di
	out	42h,al
	mov	al,ah
	out	42h,al

	mov	ax,91
	mul	bx
	mov	bx,500
	div	bx
	mov	bx,ax
	xor	ah,ah
	int	1ah
	add	dx,bx
	mov	bx,dx
.cycle:
	int	1ah
	cmp	dx,bx
	jne	.cycle
	in	al,61h
	mov	al,cl
	and	al,0fch
	out	61h,al
exits:
	pop	si
	pop	es
	pop	ds
	pop	dx
	pop	cx
	pop	ax
	ret


erasescreen:
	push	di ; Bottom row to erase
	push	si ; Top row to erase
	push	ax
	push	bx
	push	cx

	xor	ax,ax ; Row in al
	xor	si,si
	mov	cx,1000
	mov	di,4000-2
@@:
	mov	word [es:si],0720h
	mov	word [es:di],0720h
	add	si,2
	inc	ax

	sub	di,2
	cmp	ax,80
	jl	.skipit
	call	pauseerase
.skipit:
	loop	@b
	mov	di,0
   
	pop	cx
	pop	bx
	pop	ax
	pop	si
	pop	di
	ret
	
pauseerase:
	push	cx
	push	bx
	xor	ax,ax
	mov	cl,4
	mov	bx,30
	push	di
	shr	di,cl
	call	sound
	pop	di
	pop	bx
	pop	cx
	ret
  
	freq	dw  0,988,880,784,699,659,587,523,880,988,784
	bye	db  "Goodbye!",10,13,"By Dennis Katsonis, July 2020",10,13,24h
	intro	db  "Colourful name printing demo",13,10,24h
	namereq db  "What is your name? ",24h
	messagelen dw 7  ; Initial size of message
align 4
	message db 32,1,32,3,32,14,32
	keybuff rb inputlen  ; This must be immediately after message
