752 lines
14 KiB
NASM
Raw Permalink Normal View History

2022-04-07 18:43:21 +02:00
.equ HEAD_X, 0x1000 ; snake head's position on x-axis
.equ HEAD_Y, 0x1004 ; snake head's position on y-axis
.equ TAIL_X, 0x1008 ; snake tail's position on x-axis
.equ TAIL_Y, 0x100C ; snake tail's position on y-axis
.equ SCORE, 0x1010 ; score address
.equ GSA, 0x1014 ; game state array
.equ STACK, 0x2000 ; stack position
.equ LEDS, 0x2000 ; LED addresses
.equ SEVEN_SEGS, 0x1198 ; 7-segment display addresses
.equ RANDOM_NUM, 0x2010 ; Random number generator address
.equ BUTTONS, 0x2030 ; Button addresses
#=============================
addi sp, zero, STACK
call wait_restart
main_init:
call wait
main:
call get_input #check for input
call hit_test #check for collision
add a0, zero, zero
add t0, v0, zero
addi t1, zero, 1
bne v0, t1, main_no_food #if (collision != 1) -> skip
#check for food and update score
call create_food #create food
ldw t2, SCORE(zero) #save current score
addi t3, zero, 99
addi a0, zero, 1
beq t2, t3, main_no_food
addi t2, t2, 1 #increment score
stw t2, SCORE(zero) #store new score
main_no_food:
addi t1, zero, 2 #t2 = 2 (collision detect value)
bne v0, t1, main_no_hit #if (v0 != 2) -> skip next instruction
call wait_restart #else terminate game
main_no_hit:
call move_snake #update snake's position
call clear_leds
call draw_array #draw the array
call display_score
call wait #wait
call restart_game #restart game
bne v0 , zero, main_init
br main #loop main
#=============================
; BEGIN:wait_restart
wait_restart:
addi sp, sp, -4
stw zero, 0 (sp)
wait_restart_loop:
call move_text
ldw a0, 0 (sp)
call add_text
addi a0, a0, 1
addi t1, zero, 40
blt a0, t1, wait_restart_no_reset
add a0, zero, zero
wait_restart_no_reset:
stw a0, 0 (sp)
call clear_leds
call draw_array
call wait
call restart_game
beq v0,zero, wait_restart_loop
addi sp, sp, 4
call main_init
;END:wait_restart
#=============================
; BEGIN:wait
wait:
addi t0, zero, 1
# slli t0, t0, 21
addi t1, zero, 0
wait_rec:
addi t1, t1, 1
blt t1, t0, wait_rec
ret
;END:wait
#=============================
; BEGIN:add_text
add_text: # a0 = letter part to draw
add t1, zero,zero
beq t1, a0, add_text_s_0
addi t1, t1, 1
beq t1, a0, add_text_s_1
addi t1, t1, 1
beq t1, a0, add_text_s_2
addi t1, t1, 1
beq t1, a0, add_text_s_3
addi t1, t1, 1
beq t1, a0, add_text_s_4
addi t1, t1, 1
beq t1, a0, add_text_space
addi t1, t1, 1
beq t1, a0, add_text_n_0
addi t1, t1, 1
beq t1, a0, add_text_n_1
addi t1, t1, 1
beq t1, a0, add_text_n_2
addi t1, t1, 1
beq t1, a0, add_text_n_3
addi t1, t1, 1
beq t1, a0, add_text_n_4
addi t1, t1, 1
beq t1, a0, add_text_space
addi t1, t1, 1
beq t1, a0, add_text_a_0
addi t1, t1, 1
beq t1, a0, add_text_a_1
addi t1, t1, 1
beq t1, a0, add_text_a_2
addi t1, t1, 1
beq t1, a0, add_text_a_3
addi t1, t1, 1
beq t1, a0, add_text_a_4
addi t1, t1, 1
beq t1, a0, add_text_space
addi t1, t1, 1
beq t1, a0, add_text_k_0
addi t1, t1, 1
beq t1, a0, add_text_k_1
addi t1, t1, 1
beq t1, a0, add_text_k_2
addi t1, t1, 1
beq t1, a0, add_text_k_3
addi t1, t1, 1
beq t1, a0, add_text_k_4
addi t1, t1, 1
beq t1, a0, add_text_space
addi t1, t1, 1
beq t1, a0, add_text_e_0
addi t1, t1, 1
beq t1, a0, add_text_e_1
addi t1, t1, 1
beq t1, a0, add_text_e_2
addi t1, t1, 1
beq t1, a0, add_text_e_3
addi t1, t1, 1
beq t1, a0, add_text_e_4
addi t1, t1, 1
beq t1, a0, add_text_space
ret
add_text_space:
addi t0, zero, 0b00000000
br add_text_save
add_text_s_0:
addi t0, zero, 0b00111010
br add_text_save
add_text_s_1:
add_text_s_2:
add_text_s_3:
addi t0, zero, 0b00101010
br add_text_save
add_text_s_4:
addi t0, zero, 0b00101110
br add_text_save
add_text_n_0:
add_text_n_4:
addi t0, zero, 0b00111110
br add_text_save
add_text_n_1:
addi t0, zero, 0b00010000
br add_text_save
add_text_n_2:
addi t0, zero, 0b00001000
br add_text_save
add_text_n_3:
addi t0, zero, 0b00000100
br add_text_save
add_text_a_0:
add_text_a_4:
addi t0, zero, 0b00111110
br add_text_save
add_text_a_1:
add_text_a_2:
add_text_a_3:
addi t0, zero, 0b00100100
br add_text_save
add_text_k_0:
addi t0, zero, 0b00111110
br add_text_save
add_text_k_1:
addi t0, zero, 0b00001000
br add_text_save
add_text_k_2:
addi t0, zero, 0b00001000
br add_text_save
add_text_k_3:
addi t0, zero, 0b00010100
br add_text_save
add_text_k_4:
addi t0, zero, 0b00100010
br add_text_save
add_text_e_0:
addi t0, zero, 0b00111110
br add_text_save
add_text_e_1:
add_text_e_2:
add_text_e_3:
addi t0, zero, 0b00101010
br add_text_save
add_text_e_4:
addi t0, zero, 0b00100010
br add_text_save
add_text_save:
addi t4, zero, 1
addi t3, zero, 95
slli t3, t3, 2
addi t6, zero, 7
add_text_save_loop:
and t5, t4, t0
stw t5, GSA (t3)
srli t0, t0, 1
addi t3, t3, -4
addi t6, t6, -1
bne t6, zero, add_text_save_loop
ret
;END:add_text
#=============================
; BEGIN:move_text
move_text:
addi t0, zero, GSA
add t1, zero, zero #y
add t2, zero, zero #x
addi t4, zero , 8 #8
addi t5, zero , 11 #12
move_text_i:
ldw t3, 0 (t0) #GSAi_val
ldw t6, 32 (t0) #GSAi+1_val
bne t6,zero, set_to_1 #Do Draw
set_to_zero:
stw zero, 0 (t0)
br text_incr_y
set_to_1:
stw t6, 0 (t0)
text_incr_y:
addi t1, t1, 1
addi t0, t0, 4
blt t1, t4, move_text_i;
addi t2, t2, 1
add t1, zero, zero
blt t2, t5, move_text_i;
ret
; END:move_text
#=============================
; BEGIN:clear_leds
clear_leds:
stw zero, LEDS (zero) #LED0 = 0
stw zero, LEDS+4 (zero) #LED1 = 1
stw zero, LEDS+8 (zero) #LED2 = 2
ret
; END:clear_leds
#=============================
; BEGIN: set_pixel
set_pixel:
#a0 = x, a1 = y
add t1, zero, zero #comparator 1
add t2, zero, zero #comparator 2
add t3, zero, zero #final leds layout
cmpgeui t1, a0, 4 # t1 = x >= 4 ? 1 : 0
beq t1, zero, lzero # if (a0 < 4) -> lzero
cmpgeui t2, a0, 8 # t2 = x >= 8 ? 1 : 0
beq t2, zero, lone # elsif (x < 8) -> lone
bne t2, zero, ltwo #else -> ltwo
lzero:
add t6, zero, zero #t6 = 0
br pixelize # -> pixelize
lone:
addi t6, zero, 4 #t6 = 4
br pixelize # -> pixelize
ltwo:
addi t6, zero, 8 #t6 = 8
br pixelize # -> pixelize
pixelize:
ldw t5, LEDS(t6) #t5 = mem[t6 + LEDS]
sub t4, a0, t6 #t4 = x - t6
slli t4, t4, 3 #t4 << 3
add t4, t4, a1 #t4 += y
addi t3, zero, 1 #t3 = 1
sll t3, t3, t4 #t3 << t4
or t3, t3, t5 #t3 |= t5
stw t3, LEDS(t6) #mem[LEDS + t6] = t3
ret #return
; END: set_pixel
#=============================
; BEGIN:get_input
get_input:
addi t1, zero, 1 #mask
ldw t2, BUTTONS+4(zero) #edgecapture states
stw zero, BUTTONS+4(zero)
ldw t3, HEAD_X(zero) #head x coord
ldw t4, HEAD_Y(zero) #head y coord
slli t3, t3, 3 #head_x << 3
add t4, t3, t4 #t4 = 8x + y (GSA element address)
slli t4, t4, 2
ldw t7, GSA(t4) #t7 = GSAheadval
and t5, t1, t2 #t5 = edgecapture & 1
addi t3, zero, 4 #t3 = 4 (impossible value)
beq t7, t3, 4 #if t7 == t3 -> skip next instruction
bne t5, zero, left #if(edgecapture & 1 !=0) -> left
slli t1, t1, 1 #t1 << 1
and t5, t1, t2 #t5 = edgecapture & 10
addi t3, zero, 3 #t3 = 3 (impossible value)
beq t7, t3, 4 #if t7 == t3 -> skip next instruction
bne t5, zero, up #if(edgecapture & 10 !=0) -> up
slli t1, t1, 1 #t1 << 1
and t5, t1, t2 #t5 = edgecapture & 100
addi t3, zero, 2 #t3 = 2 (imopossible val)
beq t7, t3, 4 #if t7 == t3 -> skip next instruction
bne t5, zero, down #if(edgecapture & 100 !=0) -> down
slli t1, t1, 1 #t1 << 1
and t5, t1, t2 #t5 = edgecapture & 1000
addi t3, zero, 1 #t3 = 1 (impossible value)
beq t7, t3, 4 #if t7 == t3 -->skip next instruction
bne t5, zero, right #if(edgecapture & 1000 !=0) -> right
ret
left:
addi t6, zero, 1 #t6 = 1
stw t6, GSA(t4) #mem[GSA + t4] = 1
ret
up:
addi t6, zero, 2 #t6 = 1
stw t6, GSA(t4) #mem[GSA + t4] = 2
ret
down:
addi t6, zero, 3 #t6 = 3
stw t6, GSA(t4) #mem[GSA + t4] = 3
ret
right:
addi t6, zero, 4 #t6 = 4
stw t6, GSA(t4) #mem[GSA + t4] = 4
ret
; END:get_input
#=============================
; BEGIN:move_snake
move_snake:
#a0 = foodEaten ? 1 : 0
ldw t0, HEAD_X(zero) #t0: head x coord
ldw t1, HEAD_Y(zero) #t1: head y coord
slli t2, t0, 3 #x = 8x
add t2, t2, t1 #t2 = 8x + y (Head GSA element address)
slli t2, t2, 2
ldw t5, GSA(t2) #t2: Head direction vector
head:
addi t6, zero, 1 #t6: current direction
bne t5, t6, not_left #if(HeadVect == 1) -> go_left
addi t0, t0, -1
br check_head
not_left:
addi t6, zero, 2
bne t5, t6, not_up #if(HeadVect == 2) -> go_up
addi t1, t1, -1
br check_head
not_up:
addi t6, zero, 3
bne t5, t6, not_down #if(HeadVect == 3) -> go_down
addi t1, t1, 1
br check_head
not_down:
addi t6, zero, 4
bne t5, t6, not_right #if(HeadVect == 4) -> go_right
addi t0, t0, 1
br check_head
not_right: # NO movements to make !
ret
check_head:
slli t2, t0, 3
add t2, t2, t1
slli t2, t2, 2
stw t5, GSA(t2)
stw t0, HEAD_X(zero)
stw t1, HEAD_Y(zero)
beq a0, zero, no_fud
br fud
no_fud:
ldw t3, TAIL_X(zero) #t3: tail x coord
ldw t4, TAIL_Y(zero) #t4: tail y coord
slli t2, t3, 3 #x = 8x
add t2, t2, t4 #t5 = 8x + y (Tail GSA element address)
slli t2, t2, 2
ldw t5, GSA(t2) #t5: Tail direction vector
addi t6, zero, 1 #t6: current direction
bne t5, t6, tail_not_left #if(TailVect != 1) -> go_left
addi t3, t3, -1
br pre_fud
tail_not_left:
addi t6, zero, 2
bne t5, t6, tail_not_up #if(TailVect == 2) -> go_up
addi t4, t4, -1
br pre_fud
tail_not_up:
addi t6, zero, 3
bne t5, t6, tail_not_down #if(TailVect == 3) -> go_down
addi t4, t4, 1
br pre_fud
tail_not_down:
addi t6, zero, 4
bne t5, t6, pre_fud #if(TailVect == 4) -> go_right
addi t3, t3, 1
br pre_fud
pre_fud:
stw zero, GSA(t2)
stw t3, TAIL_X(zero)
stw t4, TAIL_Y(zero)
fud:
ret
; END:move_snake
#=============================
; BEGIN:draw_array
draw_array:
addi sp, sp, -4
stw ra, 0 (sp)
addi t0, zero, GSA
add t1, zero, zero #y
add t2, zero, zero #x
addi t4, zero , 8 #8
addi t5, zero , 12 #12
draw_array_i:
ldw t3, 0 (t0) #GSAi_val
beq t3,zero, incr_y #Do not Draw
add a0, t2, zero
add a1, t1, zero
# PREPARE FUNCTION CALL
addi sp, sp, -12
stw t0, 0 (sp)
stw t1, 4 (sp)
stw t2, 8 (sp)
call set_pixel # SET PIXEL
ldw t0, 0 (sp)
ldw t1, 4 (sp)
ldw t2, 8 (sp)
addi sp, sp, 12
# UNDO FUNCTION CALL
addi t4, zero , 8 #8
addi t5, zero , 12 #12
incr_y:
addi t1, t1, 1
addi t0, t0, 4
blt t1, t4, draw_array_i;
addi t2, t2, 1
add t1, zero, zero
blt t2, t5, draw_array_i;
ldw ra, 0 (sp)
addi sp, sp, 4
ret
; END:draw_array
#=============================
; BEGIN:create_food
create_food:
addi t1, zero, 255 # mask lowest byte
addi t2, zero, 384 # max val mem
addi t4, zero, 5 #value of food in GSA
random_food:
ldw t0, RANDOM_NUM (zero) # read random
and t0,t0,t1 # lowest byte of random
slli t0, t0, 2
bge t0, t2, random_food
ldw t3, GSA (t0)
bne t3, zero, random_food #checks if cell is empty
stw t4, GSA (t0) #add food
ret
; END:create_food
#=============================
; BEGIN:hit_test
hit_test:
#Collide with food
ldw t0, HEAD_X(zero) #head_x_coord
ldw t1, HEAD_Y(zero) #head_y_coord
slli t2, t0, 3 #t2 = 8x
add t2, t2, t1 #t2 = 8x + y (GSA elem address)
slli t2, t2, 2
ldw t3, GSA(t2) #value of the GSA elem at head coord
addi t7, zero, 1 #t6: current direction
bne t3, t7, check_not_left #if(TailVect != 1) -> go_left
addi t0, t0, -1
br check_cell
check_not_left:
addi t7, zero, 2
bne t3, t7, check_not_up #if(TailVect != 2) -> go_up
addi t1, t1, -1
br check_cell
check_not_up:
addi t7, zero, 3
bne t3, t7, check_not_down #if(TailVect != 3) -> go_down
addi t1, t1, 1
br check_cell
check_not_down:
addi t7, zero, 4
bne t3, t7, check_cell #if(TailVect != 4) -> exit
addi t0, t0, 1
check_cell:
addi t6, zero, 11
bltu t6, t0, hit_edge
addi t6, zero, 7
bltu t6, t1, hit_edge
slli t2, t0, 3 #t2 = 8x
add t2, t2, t1 #t2 = 8x + y (GSA elem address)
slli t2, t2, 2
ldw t3, GSA(t2) #value of the GSA elem after head coord
beq t3, zero, no_hit
addi t4, zero, 5 #food value
beq t3, t4, hit_food
bltu t3, t4, hit_edge
hit_edge:
addi v0, zero, 2
ret
hit_food:
addi v0, zero, 1 #food is eaten since headGSAval = 5
ret #else return v0
no_hit:
add v0, zero, zero #v0 = 0
ret #return v0
; END:hit_test
#=============================
; BEGIN:display_score
display_score:
ldw t1, SCORE (zero) #Value of score
add t2, zero, zero # 10 units
addi t3, zero, 10 #min to substract
bin_to_dec:
blt t1, t3, draw_score # t1 < 10 -> go draw
sub t1, t1, t3 # t1 = t1 - 10;
addi t2, t2, 1 # t2 = t2 + 1 ;
br bin_to_dec
draw_score:
ldw t6, font_data (zero)
stw t6, SEVEN_SEGS+0 (zero)
stw t6, SEVEN_SEGS+4 (zero)
slli t2, t2, 2
ldw t6, font_data (t2)
stw t6, SEVEN_SEGS+8 (zero)
slli t1, t1, 2
ldw t6, font_data (t1)
stw t6, SEVEN_SEGS+12 (zero)
ret
; END:display_score
#=============================
; BEGIN:restart_game
restart_game:
ldw t5, BUTTONS+4(zero) #EDGE
addi t7, zero, 0b010000
and t6, t5, t7 #010000 & t1
beq t6, zero, exit_no_restart
stw zero, BUTTONS+4(zero)
#reset_mem:
stw zero, HEAD_Y (zero)
stw zero, HEAD_X (zero)
stw zero, TAIL_Y (zero)
stw zero, TAIL_X (zero)
stw zero, SCORE (zero)
add t2, zero, zero
addi t3, zero, 384
reset_gsa:
stw zero, GSA(t2)
addi t2, t2, 4
blt t2, t3, reset_gsa
#init_gsa:
addi t4 , zero, 4
stw t4, GSA (zero)
addi sp, sp, -4
stw ra, 0 (sp)
call clear_leds
call create_food
call draw_array
call display_score
ldw ra, 0 (sp)
addi sp, sp, 4
addi v0, zero, 1
br exit_restart_func
exit_no_restart:
addi v0, zero, 0
exit_restart_func:
ret
; END:restart_game
#=============================
font_data:
.word 0xFC ; 0
.word 0x60 ; 1
.word 0xDA ; 2
.word 0xF2 ; 3
.word 0x66 ; 4
.word 0xB6 ; 5
.word 0xBE ; 6
.word 0xE0 ; 7
.word 0xFE ; 8
.word 0xF6 ; 9
end: