###############################################################################
# Interface test                                                              #
###############################################################################
#   Author: Ben Vanik - ben@vanik.net                                         #
#     Date: 2004-01-07                                                        #
# See-also:                                                                   #
###############################################################################
#                                                                             #
#                                                                             #
#                                                                             #
#                                                                             #
###############################################################################

###############################################################################
# Data                                                                        #
###############################################################################
.data
sz_newline:		.asciiz		"\n"
sz_menu_bar:	.asciiz		"########################################\n"
sz_menu_slot:	.asciiz		"#"
sz_menu_ws:		.asciiz		" "
n_menu_width:	.word		41

sz_test:		.asciiz		"foobar"

###############################################################################
# Program code                                                                #
###############################################################################
.text
__start:
		
	# Setup state
	jal		l_setupstate
	
	# Do menu as long as we need to
menuloop:
	bne		$v0, $0, done			# if return != 0 done
	jal		l_mainmenu				# do menu
	j		menuloop				# loop
	
#------------------------------------------------------------------------------
# Setup application state
#------------------------------------------------------------------------------
#     in: -
#    out: -
# unsafe: 
#------------------------------------------------------------------------------
l_setupstate:
	jr		$ra

#------------------------------------------------------------------------------
# Draw menu and get input
#------------------------------------------------------------------------------
#     in: -
#    out: v0 = user input (word)
# unsafe: $t9, $a0, $v*
#------------------------------------------------------------------------------
l_mainmenu:
	subu	$sp, $sp, 32			# grow stack
	sw		$ra, 20($sp)			# save return address
	sw		$fp, 16($sp)			# save frame pointer
	addiu	$fp, $sp, 28			# set frame pointer

	li		$v0, 4
	la		$a0, sz_menu_bar
	syscall

	la		$a0, sz_test
	jal l_drawmenuline

	li		$v0, 4
	la		$a0, sz_menu_bar
	syscall

	li		$v0, 1					# set return value
	lw		$ra, 20($sp)			# restore return address
	lw		$fp, 16($fp)			# restore frame pointer
	addiu	$sp, $sp, 32			# shrink stack
	jr		$ra

#------------------------------------------------------------------------------
# Draw a menu line
#------------------------------------------------------------------------------
#     in: a0 = source string (string address)
#    out: -
# unsafe: $t1, $t2, $t7, $t8, $v*
#------------------------------------------------------------------------------
l_drawmenuline:
	subu	$sp, $sp, 32			# grow stack
	sw		$ra, 20($sp)			# save return address
	sw		$fp, 16($sp)			# save frame pointer
	addiu	$fp, $sp, 28			# set frame pointer
	
	# Store arg a0
	move	$s0, $a0
	
	# Draw first char/ws
	li		$v0, 4					# print_string
	la		$a0, sz_menu_slot
	syscall
	li		$v0, 4					# print_string
	la		$a0, sz_menu_ws
	syscall
	
	# Draw string
	li		$v0, 4					# print_string
	move	$a0, $s0
	syscall
	
	# Get length of string
	move	$a0, $s0
	jal		l_strlen
	move	$t0, $v0				# save length
	
	# Find needed width
	lw		$t1, n_menu_width		# desired max width
	sub		$t1, $t1, $t0			# max - str
	li		$t2, 4					# 3 (2+1); slot + ws on head and slot on end
	sub		$t1, $t1, $t2			# cur - 4
	
	# Draw ws chars
	li		$t2, 1					# temp (for dec)
drawmenulinews:
	li		$v0, 4					# print_string
	la		$a0, sz_menu_ws
	syscall
	sub		$t1, $t1, $t2			# dec counter
	bne		$t1, $0, drawmenulinews	# loop if not yet 0
	
	# Draw last slot
	li		$v0, 4					# print_string
	la		$a0, sz_menu_slot
	syscall
	
	# Print newline
	li		$v0, 4					# print_string
	la		$a0, sz_newline
	syscall
	
	lw		$ra, 20($sp)			# restore return address
	lw		$fp, 16($fp)			# restore frame pointer
	addiu	$sp, $sp, 32			# shrink stack
	jr		$ra
	
#------------------------------------------------------------------------------
# Return length of given string
#------------------------------------------------------------------------------
#     in: a0 = source string (string address)
#    out: v0 = length of string (word)
# unsafe: $t0, $t1, $t2
#------------------------------------------------------------------------------
l_strlen:
	li		$t0, 0					# zero counter
	move	$t1, $a0				# get string address
	
strlenbeg:
	lb		$t2, ($t1)				# get next char
	beq		$t2, $0, strlenend		# see if we are done (null terminator hit)
	addi	$t1, $t1, 1				# inc our memory pointer to the string
	addi	$t0, $t0, 1				# inc our counter
	j		strlenbeg				# loop back to next char
	
strlenend:
	move	$v0, $t0				# set return value	
	jr		$ra

	# Exit
done:

###############################################################################
# EOF                                                                         #
###############################################################################
