Mouse click event for concentration game in MIPS assembly
- Deal the cards face down.
- Add a polling loop at the beginning of your main program to request the character for the level of difficulty. (this will randomize the syscall random.
- Create a map structure to map mouse click co-ordinates to cards. Initialize it to NULL pointers, and then fill it with card pointers as you create the cards.
- Add a polling loop at the end of initializations in main to wait for mouse clicks.
- Add card.click() method. Using a global (static) state variable, and two global (static) card pointers, implement this state machine:
Solution
# { box class
box: .struct
ul: .byte 0 # upper left
top: .byte 0
ur: .byte 0 # upper right
left: .byte 0
middle: .byte 0
right: .byte 0
ll: .byte 0 # lower left
bot: .byte 0 # bottom
lr: .byte 0 # lower right
.data
# { card class
card: .struct
word: .word 0
x: .word 0
y: .word 0
match: .byte 0
faceup: .byte 0
.byte 0
.byte 0
.data
.align 4
infile: .asciiz “wordfile.txt”
words: .space 2444 #611*4
.extern state,4
.extern card1,4
.extern card2,4
# { instances of box}
boxBlank:
.ascii ” ”
boxd: .byte 201,205,187
.byte 186,32,186
.byte 200,205,188
boxs: .byte 218,196,191
.byte 179,32,179
.byte 192,196,217
boxw: .ascii “¬Þ¬Þ¬Þ”
.ascii “§ ˆ ”
.ascii “‡‡‡”
boxg1: .ascii “¬¡¬¡¬¡¬¡ ¬¡¬¡¬¡¬¡”
boxb: .ascii “¬Ã¬Ã¬Ã¬à ¬Ã¬Ã¬Ã¬Ô
.extern lfsr,4
.data
keyboard: .struct 0xa0000000 #start from hardware base address
flags: .byte 0
mask: .byte 0
.half 0
keypress: .byte 0,0,0
presscon: .byte 0
keydown: .half 0
shiftdown: .byte 0
downcon: .byte 0
keyup: .half 0
upshift: .byte 0
upcon: .byte 0
#——————————————————————————-
# void box::draw(int x:a0, int y:a1, int w:a2, int h:a3,box *this:s0)
.code
box.draw:
mov $t9,$a0 # save x for re-use
syscall $xy #
lb $a0,box.ul($s0)
syscall $print_char
lb $a0,box.top($s0)
mov $t0,$a2
b 2f
1: syscall $print_char
addi $t0,$t0,-1
2: bgtz $t0,1b
lb $a0,box.ur($s0)
syscall $print_char
mov $a0,$t9
addi $a1,$a1,1
syscall $xy
b 4f
3: lb $a0,box.left($s0)
syscall $print_char
lb $a0,box.middle($s0) #
mov $t0,$a2
b 2f
1: syscall $print_char
addi $t0,$t0,-1
2: bgtz $t0,1b
lb $a0,box.right($s0)
syscall $print_char
mov $a0,$t9
addi $a1,$a1,1
syscall $xy
addi $a3,$a3,-1
4: bgtz $a3,3b
lb $a0,box.ll($s0)
syscall $print_char
lb $a0,box.bot($s0)
mov $t0,$a2
b 2f
1: syscall $print_char
addi $t0,$t0,-1
2: bgtz $t0,1b
lb $a0,box.lr($s0)
syscall $print_char
jr $ra
#——————————————————————————-
# int random()
# random generator that uses the Galois LFSR PRNG function
random:
li $v0,0x0d000001
lw $t0,lfsr($gp)
srl $t1,$t0,1
andi $t0,$t0,1
beqz $t0,1f
li $t0,-1
1: and $v0,$v0,$t0
xor $v0,$v0,$t1
sw $v0,lfsr($gp)
jr $ra
#——————————————————————————-
#void Fileread(a0: char * filename,a1: char * buffer)
Fileread:
or $t0,$a1,$0 # save pointer to place to load file
add $a1,$0,$0
add $a2,$0,$0
syscall $open
add $a0,$v0,$0 # save file descriptor
or $a1,$t0,$0 # recover pointer to buffer
ori $a2,$0,1 # read a single char at a time
ori $t1,$0,611 # counter of words
1: syscall $read # read a char
lb $t0,($a1) # load read char in t3
beqz $t0,2f
beq $t0,13,1b # if it’s CR, continue
beq $t0,10,2f # if we reached end of line, continue
addi $a1,$a1,1
b 1b
2: sb $0,($a1) # insert end of string
addi $a1,$a1,1
addi $t1,$t1,-1
bnez $t1,1b
syscall $close
jr $ra
#——————————————————————————-
# void card.card(card * c)
card.draw:
addi $sp,$sp,-12
sw $ra,0($sp) # save return address
sw $s0,4($sp)
sw $s1,8($sp)
or $s1,$0,$a0
lw $a0,card.x($s1)
lw $a1,card.y($s1)
ori $a2,$0,3
ori $a3,$0,1
lb $t0,card.match($s1)
beqz $t0,0f
la $s0,boxBlank
b 2f
0: lb $t1,card.faceup($s1)
bnez $t1,1f # draw up
la $s0,boxd
b 2f
1: la $s0,boxs
2: jalbox.draw
lb $t0,card.faceup($s1)
beqz $t0,3f # for face down, don’t draw word
lw $a0,card.x($s1)
addi $a0,$a0,1
lw $a1,card.y($s1)
addi $a1,$a1,1
syscall $xy # else, put the word
lw $t0,card.word($s1)
sll $t0,$t0,2
la $t1,words
add $a0,$t1,$t0
syscall $print_string
3: lw $ra,0($sp)
lw $s0,4($sp)
lw $s1,8($sp)
add $sp,$sp,12
jr $ra
#——————————————————————————-
# void card.card(card * c)
card.card:
addi $sp,$sp,-4
sw $ra,0($sp) # save return address
sw $0,card.word($a0)
sw $0,card.x($a0)
sw $0,card.y($a0)
sb $0,card.match($a0)
ori $t0,$0,0
sb $t0,card.faceup($a0)
lw $ra,0($sp)
add $sp,$sp,4
jr $ra
#——————————————————————————-
# card * card.new()
card.new:
addi $sp,$sp,-12
sw $ra,0($sp) # save return address
sw $s0,4($sp)
sw $a0,8($sp)
ori $a0,$0,16 # reserve space for a card
syscall $malloc
or $s0,$0,$v0
or $a0,$0,$v0
jalcard.card
or $v0,$0,$s0
lw $ra,0($sp)
lw $s0,4($sp)
lw $a0,8($sp)
add $sp,$sp,12
jr $ra
#——————————————————————————-
#void Shuffle(card * array[ ]:a0, int N:a1)
Shuffle:
addi $sp,$sp,-8
sw $ra,0($sp) # save return address
sw $a1,4($sp)
1: jal random
div $v0,$a1
mfhi $t0
sll $t0,$t0,2
add $t0,$t0,$a0
lw $t2,($t0)
addi $a1,$a1,-1
sll $t1,$a1,2
add $t1,$t1,$a0
lw $t3,($t1)
lw $t4,card.word($t2) # shuffle only the words…
lw $t5,card.word($t3)
sw $t5,card.word($t2)
sw $t4,card.word($t3)
bgtz $a1,1b
lw $ra,0($sp)
lw $a1,4($sp)
add $sp,$sp,8
jr $ra
#——————————————————————————-
# void clrscr()
clrscr:
addi $sp,$sp,-16
sw $ra,0($sp) # save return address
sw $a0,4($sp)
sw $a1,8($sp)
sw $v0,12($sp)
ori $t0,$0,25
ori $a0,$0,10
1: syscall $print_char
addi $t0,$t0,-1
bnez $t0,1b
or $a0,$0,$0
or $a1,$0,$0
syscall $xy
lw $ra,0($sp)
lw $a0,4($sp)
lw $a1,8($sp)
lw $v0,12($sp)
add $sp,$sp,16
jr $ra
#——————————————————————————-
.data
prompt: .asciiz “Please enter the level of difficulty (1-6): ”
exit: .asciiz ” Press Enter to continue, x to exit: ”
n: .word 0
wid: .word 0
hei: .word 0
array: .word 0 # pointer to start address of array of cards
.data
mouse: .struct 0xa0000018
flags: .byte 0
mask: .byte 0
.half 0
.word 0
move: .word 0,0
down: .word 0,0
up: .word 0,0
wheel: .word 0,0
wheeldown: .word 0,0
wheelup: .word 0,0
.code
.globl main
#——————————————————————————-
# intpollMouse()
pollMouse:
addi $sp,$sp,-12
sw $ra,0($sp) # save return address
sw $s0,4($sp)
sw $s1,8($sp)
or $t1,$0,$0
or $t2,$0,$0
1: la $a0,mouse.flags
li $a1,1
syscall $IO_read
beqz $v0,1b
move $t2,$v0
andi $t0,$t2,1
beqz $t0,2f
la $a0,mouse.move
li $a1,4
syscall $IO_read
2: andi $t0,$t2,2
beqz $t0,3f
la $a0,mouse.down
li $a1,4
syscall $IO_read
bnez $t1,3f
ori $t1,$t1,1
3: andi $t0,$t2,4
beqz $t0,4f
la $a0,mouse.up
li $a1,4
syscall $IO_read
beqz $t1,4f
ori $t1,$t1,2
andi $s0,$v0,0xFFFF
srl $s1,$v0,16
4: andi $t0,$t2,8
beqz $t0,5f
la $a0,mouse.wheel
li $a1,4
syscall $IO_read
5: andi $t0,$t2,16
beqz $t0,6f
la $a0,mouse.wheeldown
li $a1,4
syscall $IO_read
6: andi $t0,$t2,32
bnez $t0,7f
la $a0,mouse.wheelup
li $a1,4
syscall $IO_read
7: bne $t1,3,1b
8: move $v0,$s0
move $v1,$s1
lw $ra,0($sp)
lw $s0,4($sp)
lw $s1,8($sp)
add $sp,$sp,12
jr $ra
# card.clic(card * c: a0)
card.clic:
addi $sp,$sp,-20
sw $ra,0($sp) # save return address
sw $s0,4($sp)
sw $s1,8($sp)
sw $s2,12($sp)
sw $s3,16($sp)
lb $t0,card.match($a0)
bnez $t0,6f
lw $s0,state($gp)
lw $s1,card1($gp)
lw $s2,card2($gp)
ori $t0,$0,1
bnez $s0,1f
addi $s0,$s0,1
move $s1,$a0
b 5f
1: bne $s0,1,2f
addi $s0,$s0,1
move $s2,$a0
bne $s1,$s2,5f
or $t0,$0,$0
or $s0,$0,$0
b 5f
2: move $s3,$a0
sb $0,card.faceup($s1)
sb $0,card.faceup($s2)
lw $t1,card.word($s1)
lw $t2,card.word($s2)
bne $t1,$t2,3f
sb $t0,card.match($s1)
sb $t0,card.match($s2)
3: move $a0,$s1
jalcard.draw
move $a0,$s2
jalcard.draw
beq $s3,$s1,4f
beq $s3,$s2,4f
move $a0,$s3
move $s1,$s3
ori $s0,$0,1
ori $t0,$0,1
b 5f
4: or $s0,$0,$0
b 6f
5: sb $t0,card.faceup($a0)
jalcard.draw
6: sw $s0,state($gp)
sw $s1,card1($gp)
sw $s2,card2($gp)
lw $ra,0($sp)
lw $s0,4($sp)
lw $s1,8($sp)
lw $s2,12($sp)
lw $s3,16($sp)
add $sp,$sp,20
jr $ra
#——————————————————————————-
# void main()
main:
ori $t0,$0,1
sw $t0,lfsr($gp)
la $a0,infile # load all words in memory
la $a1,words
jalFileread
1: jalclrscr
la $a0,prompt
syscall $print_string
kloop:
jal random
la $a0,keyboard.flags # hardware address of keyboard flags
addi $a1,$0,1 # 1 byte of data
syscall $IO_read # read flags
blez $v0,kloop # branch if no keyboard flags
andi $t0,$v0,1 # flag bit 0
beqz $t0,kloop
la $a0,keyboard.keypress # hardware address of ascii data
addi $a1,$0,1 # 1 byte of data
syscall $IO_read
addi $v0,$v0,-48
beqz $v0,1b #
sltiu $t0,$v0,7 # check for out-of-range
beqz $t0,1b # try again
jalclrscr # clear the screen
sw $0,state($gp)
sw $0,card1($gp)
sw $0,card2($gp)
ori $t0,$0,2
sllv $s0,$t0,$v0 # calculate 2<<n
la $s1,n
sw $v0,($s1) # save difficulty n
or $a0,$0,$s0 # reserve space for card array
sll $a0,$a0,2 # multiply by 4 to get number in bytes
syscall $malloc
la $t0,array # point to start of array with s5
sw $v0,($t0) # save pointer to allocated array
or $s5,$0,$v0
lw $v0,($s1) # restore difficulty level in v0
li $s1,2 # initial boxes wide
li $s2,1 # initial boxes tall
andi $t0,$v0,1 # odd?
srl $v0,$v0,1 # divided by 2
sllv $s1,$s1,$v0
add $v0,$v0,$t0
sllv $s2,$s2,$v0
la $t0,wid
sw $s1,($t0)
la $t0,hei
sw $s2,($t0)
or $s7,$0,$0
mov $s4,$0 # working counters y
mov $s3,$0 # x
li $a2,3 # width of middle of box
2: li $a3,1 # height of middle of box
sll $a0,$s3,2
add $a0,$a0,$s3 # x = 5 * s3
sll $a1,$s4,1
add $a1,$a1,$s4 # y = 3 * s4
jalcard.new
or $s0,$v0,$0
sw $a0,card.x($s0) # save x and y
sw $a1,card.y($s0)
bnez $s7,3f
jal random # generate a word number
ori $t0,$0,611
divu $v0,$t0
mfhi $s6
3: sw $s6,card.word($s0)
sw $s0,($s5)
addi $s5,$s5,4
xori $s7,$s7,1
addi $s3,$s3,1
bne $s3,$s1,2b
mov $s3,$0
addi $s4,$s4,1
bne $s4,$s2,2b
la $t0,array # shuffle the cards
lw $a0,($t0)
la $t0,n
lw $t1,($t0)
ori $t0,$0,2
sllv $a1,$t0,$t1 # calculate 2<<n
jal Shuffle
or $s0,$a1,$0 # print cards
la $t0,array
lw $s1,($t0) # get array pointer in s1
4: lw $t0,($s1) # get a card pointer
or $a0,$0,$t0
jalcard.draw
addi $s1,$s1,4
addi $s0,$s0,-1
bnez $s0,4b
li $s0,0
li $s1,0
li $s2,0
5: jalpollMouse
li $t0,5
div $t1,$v0,$t0
li $t0,3
div $t2,$v1,$t0
la $t0,wid
lw $t3,($t0)
la $t0,hei
lw $t4,($t0)
bge $t1,$t3,5b
bge $t2,$t4,5b
mul $t0,$t2,$t3
add $t0,$t0,$t1
sll $t0,$t0,2
la $t1,array
lw $a0,($t1) # get array pointer in a0
add $a0,$a0,$t0
lw $a0,($a0)
jalcard.clic
b 5b
or $s0,$a1,$0 # free all allocated space
la $t0,array
lw $s1,($t0) # get array pointer in s1
10: lw $a0,($s1) # get a card pointer
syscall $free
addi $s1,$s1,4
addi $s0,$s0,-1
bnez $s0,10b
la $t0,array
lw $a0,($t0) # get pointer to allocated array
syscall $free # free it
or $a0,$0,$0
ori $a1,$0,24
syscall $xy
la $a0,exit
syscall $print_string
syscall $read_char
bne $v0,’x,1b
syscall $exit