.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: call show_restart call wait call restart_game beq v0,zero, wait_restart 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:show_restart show_restart: stw ra, 0(sp) addi sp, sp, -4 call write_r call write_e call write_s call write_t call write_a call write_r call write_t addi t0, zero, 12 loop: call move_snake addi t0, t0 ,-1 bne t0, zero, loop #get origin return address ldw ra, 0(sp) addi sp, sp, 4 ret write_r: stw ra, 0(sp) addi sp, sp, -4 addi a0, zero, 11 call create_line_4 call move_snake call wait #create point at y = 2 addi a1, zero, 2 call create_snake call move_snake call wait #skip line call move_snake call wait #get origin return address ldw ra, 0(sp) addi sp, sp, 4 ret write_e: stw ra, 0(sp) addi sp, sp, -4 call create_line_4 call move_snake call wait call create_line_2 #create point at y = 5 addi a1, zero, 5 call create_snake call move_snake call wait #skip line call move_snake call wait #get origin return address ldw ra, 0(sp) addi sp, sp, 4 ret write_s: stw ra, 0(sp) addi sp, sp, -4 call create_line_2 #create point at y = 5 addi a1, zero, 5 call create_snake call move_snake call wait #create point at y = 2 addi a1, zero, 2 call create_snake #create point at y = 4 addi a1, zero, 4 call create_snake #create point at y = 5 addi a1, zero, 5 call create_snake call move_snake call wait #skip line call move_snake call wait #get origin return address ldw ra, 0(sp) addi sp, sp, 4 ret write_t: stw ra, 0(sp) addi sp, sp, -4 call create_line_4 call move_snake call wait #create point at y = 3 addi a1, zero, 3 call create_snake call move_snake call wait #skip line call move_snake call wait #get origin return address ldw ra, 0(sp) addi sp, sp, 4 ret write_a: stw ra, 0(sp) addi sp, sp, -4 call create_line_3 call move_snake call wait #create point at y = 2 addi a1, zero, 2 call create_snake call move_snake call wait call create_line_3 call move_snake call wait #skip line call move_snake call wait #get origin return address ldw ra, 0(sp) addi sp, sp, 4 ret ;END:show_restart #============================= ;BEGIN:create_pattern: #helps the show_restart procedure by creating a line pattern create_line_4: stw ra, 0(sp) addi sp, sp, -4 addi a0, zero, 11 call create_line_2 addi a1, zero, 4 call create_snake addi a1, zero, 5 call create_snake #get origin return address ldw ra, 0(sp) addi sp, sp, 4 ret create_line_3: stw ra, 0(sp) addi sp, sp, -4 addi a0, zero, 11 addi a1, zero, 3 call create_snake addi a1, zero, 4 call create_snake addi a1, zero, 5 call create_snake #get origin return address ldw ra, 0(sp) addi sp, sp, 4 ret create_line_2: stw ra, 0(sp) addi sp, sp, -4 addi a0, zero, 11 addi a1, zero, 2 call create_snake addi a1, zero, 3 call create_snake #get origin return address ldw ra, 0(sp) addi sp, sp, 4 ret ;END:create_pattern: #============================= ;BEGIN:create_snake create_snake: #a0 = Head_x_coord, a1 = head_y_coord slli t0, a0, 3 add t0, t0, a1 #t0 = 8x + y (GSA elem) slli t0, t0, 2 #GSA elem address addi t1, zero, 1 #direction = left stw t1, GSA(t0) ret ;END:create_snake #============================= ; 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: