# coordinates are given in col major format # (col,row) = (x,y) = (a0,a1) .equ BG_COLOR, 0x00 #black .equ VG_ADDR, 0x11100000 .equ VG_COLOR, 0x11140000 .equ LEDS_ADDR, 0x11080000 .global srand_function .global rand_function .global main .type main, @function #Registers used: #x18 address for VGA #x19 address for VGA #s7 address for array (left arrows) #s8 address for array (down arrows) #s9 address for array (up arrows) #s10 address for array (right arrows) #a0,a1 arguments for draw dot (x/y coordinates respectively) #a5,a6,a7, used to link result of rand_function to a specific draw arrow routine #x3,x4,x8,s11 counter that allows a max of 3 arrows of one type on screen # main: li a0, 0 #load from switches (will implement later) for seeded randomness call srand_function #----------Initialize Registers----------------------------------------------------------- li x18, VG_ADDR li x19, VG_COLOR ##address of the arrays used to hold the y-coordinates of the moving arrows # s7 = left arrow's y-coordinates,etc. la s7, LEFT_COLUMN la s8, DOWN_COLUMN la s9, UP_COLUMN la s10, RIGHT_COLUMN #Assuming that a0 is fresh from the rand_function if a0 is equal to # 0 == draw a left arrow # 1 == draw a down arrow # 2 == draw an up arrow # 3 == draw a right arrow li a5,1 #draw down arrow li a6,2 #draw up arrow li a7,3 #max number of arrows in one column (AKA length of array)# ALSO!, matching for down arrow #counter that counts the number of arrows in one column li x3,0 #counter for number of down arrow li x4,0 #up counter li x8,0 #left counter li s11,0 #right counter call draw_background # draw using default color li t5,10 # counter to delay arrow creation loop: ADDI t5,t5,-1 #decrement counter used to delay arrow creation BEQ t5,x0,spawn_arrows #IF timer == 0, then its time to draw an arrow! move_arrows: #prevents MOVE from being called if there are 0 arrows <--(My attempt and removing the under/overflow issue with the counters) BEQZ x8,1f call Move_Left_Arrows 1: BEQZ s11,1f call Move_Right_Arrows 1: BEQZ x3,1f call Move_Down_Arrows 1: BEQZ x4,1f call Move_Up_Arrows 1: call draw_stationary_arrow #prevents stationary arrows from being deleted call BUFFER j loop spawn_arrows: li t5,10 #restore timer countdown to allow another arrow to spawn after t=10 li a0, 4 #max range in the rand_function #FIRST# store all argument registers to retain original value #so rand_function does NOT override them all ##TODO: (overkill# seek to reduce later once bug is fixed) addi sp,sp,-4 sw a5, 0(sp) addi sp,sp,-4 sw a6, 0(sp) addi sp,sp,-4 sw a7, 0(sp) addi sp,sp,-4 sw x3, 0(sp) addi sp,sp,-4 sw x4, 0(sp) addi sp,sp,-4 sw s11, 0(sp) #---------CALL RAND---------- #a0 = result of rand_function call rand_function li t0, LEDS_ADDR sw a0,0(t0) #-------Pop and restore all original values------ LW s11, 0(sp) addi sp,sp,4 LW x4, 0(sp) addi sp,sp,4 LW x3, 0(sp) addi sp,sp,4 LW a7, 0(sp) addi sp,sp,4 LW a6, 0(sp) addi sp,sp,4 LW a5, 0(sp) addi sp,sp,4 #------------------Utilize our a0 result from rand----------- li a1,60 #start at bottom of the screen BEQ a0, a5, DRAW_DOWN #if a0 == 1, draw a down arrow..etc. BEQ a0, a6, DRAW_UP BEQ a0, x0, DRAW_LEFT BEQ a0, a7, DRAW_RIGHT #safety net that shouldn't need to be used: in case a0 != 0,1,2,3 j move_arrows DRAW_DOWN: BEQ x3,a7, move_arrows #if x4 == 3, then we do not want to draw more arrows call draw_down_arrow #draws the arrow call populate_DOWN_COLUMN #helper function that does the book keeping for the array j move_arrows #move the arrows DRAW_UP: BEQ x4,a7, move_arrows call draw_up_arrow call populate_UP_COLUMN j move_arrows DRAW_LEFT: BEQ x8,a7, move_arrows call draw_left_arrow call populate_LEFT_COLUMN j move_arrows DRAW_RIGHT: BEQ s11,a7, move_arrows call draw_right_arrow call populate_RIGHT_COLUMN j move_arrows #------------------------------------------------------------- #--------Left arrows subroutine------------------------------- #------------------------------------------------------------- #uses t3,a0,a2 registers. # t0,t1,a0 (called in draw dot/horizontal that MODIFIES the registers) draw_left_arrow: #draws an arrow at the y-coordinate ADDI x8,x8, 1 #increment counter (# of left arrows on the screen) #Save Return address addi sp,sp,-4 sw ra, 0(sp) mv t3,a1 #temporary store y-coordinate li a0, 6 # start X coordinate li a2, 14 # ending x coordinate call draw_horizontal_line li a0, 4 # X coordinate call draw_dot # draw red square ADDI a1,a1,-2 li a0, 6 # X coordinate call draw_dot # draw red square mv a1,t3 ADDI a1,a1,2 li a0, 6 # X coordinate call draw_dot # draw red square mv a1,t3 #restore original y-value LW ra,0(sp) ADDI sp,sp,4 RET #uses t3,a0,a2 registers. # t0,t1,a0 (called in draw dot/horizontal that MODIFIES the registers) Delete_Left_Arrows: #the same as draw left arrows but in BG color #---THIS IS WHERE THE OVER/UNDERFLOW IS OCCURRING! ADDI x8,x8, -1 #decrement counter to indicate there is 1 less arrow on the screen #----------------------------------------- li a3,BG_COLOR #Save Return address addi sp,sp,-4 sw ra, 0(sp) mv t3,a1 #temporary store y-coordinate li a0, 6 # start X coordinate li a2, 14 # ending x coordinate call draw_horizontal_line li a0, 4 # X coordinate call draw_dot # draw red square ADDI a1,a1,-2 li a0, 6 # X coordinate call draw_dot # draw red square mv a1,t3 ADDI a1,a1,2 call draw_dot # draw red square mv a1,t3 LW ra,0(sp) ADDI sp,sp,4 RET #USES a1 register #OVERRIDES a0,a3 registers #calls draw dot/line, so a2,t0,t1 are modified too Move_Left_Arrows: #Save Return address addi sp,sp,-4 sw ra, 0(sp) #move first arrow lw a1,0(s7) #get y-coordinate of the first arrow # IF the coordinate is < 0, then we do not want to delete the arrow (it is off of the screen) #so branch out for the next arrow in the array BLT a1, x0, 1f CALL Delete_Left_Arrows #ELSE! delete the current arrow ADDI a1,a1,-1 #updates Y-coordinate to move it up #IF the coordinate after the updated Y-coordinate is < 0, then we do not want to draw #the arrow since it is off the screen #(We still want to store it back into the array, or else we will execute the ADDI above many times) BLT a1,x0,2f li a3, 0x1C #green CALL draw_left_arrow #draws the arrow at the new location 2: sw a1,0(s7) #store the updated y coor into the array 1: #do the same with moving the second arrow lw a1,4(s7) #get y-coor of 2nd arrow BLT a1, x0, 1f CALL Delete_Left_Arrows ADDI a1,a1,-1 BLT a1,x0,2f li a3, 0x1F #neon blue CALL draw_left_arrow 2: sw a1,4(s7) #store new y-coor into the array 1: #move third arrow lw a1,8(s7) BLT a1, x0, 1f CALL Delete_Left_Arrows ADDI a1,a1,-1 BLT a1,x0,2f li a3, 0xE3 #purple CALL draw_left_arrow 2: sw a1,8(s7) 1: #Restore Return address LW ra,0(sp) ADDI sp,sp,4 RET #BOOK-KEEPING of our arrays that hold the Y-coordinate of arrows #We shift the contents of the array over to make space for the new y-coordinate (to prevent any data from being overwritten) #Called RIGHT BEFORE drawing a BRAND NEW arrow (not when drawing an arrow for moving it) #Uses t6,a4,t2,a1 registers #modified t0,t1,a2,a0 registers (if delete arrows is called) populate_LEFT_COLUMN: addi sp,sp,-4 sw ra, 0(sp) mv t4,a1 #save current a1 (the new arrow y-coor) lw t6, 0(s7) #load our cuurent coordinates lw a4, 4(s7) lw t2, 8(s7) # IF t2 <= 0, then we delete it because array[8] data is being shifted off BLT t2, x0, 1f mv a1,t2 #modify a1 with t2, to delete the arrow that is being shifted off call Delete_Left_Arrows 1: sw a4, 8(s7) #shift the data over to the next index in the array sw t6, 4(s7) mv a1,t4 #restore a1 original value because it was modified by t2 sw a1, 0(s7) #store the ycoordinate into the array lw ra,0(sp) #setup return ADDI sp,sp,4 RET #------------------------------------------------------------------------ #------DRAW RIGHT ARROWS (same as left arrows, but different registers)--------- draw_right_arrow: #Save Return address addi sp,sp,-4 sw ra, 0(sp) #---Start Code mv t3,a1 # store original a1 into a temporary reg li a0, 65 # x coordinate li a2, 74 # ending x coordinate call draw_horizontal_line #call draw line with current a1 li a0, 74 # X coordinate (hard coded for right arrows) ADDI a1, a1, -2 # Y coordinate call draw_dot # draw red square mv a1,t3 ADDI a1,a1,2 #Y coordiante call draw_dot # draw red square @ same X coordinate as before li a0, 76 # X coordinate mv a1,t3 # restore original Y coordinate call draw_dot # draw red square ADDI s11,s11,1 #INCREMENT counter (# of right arrows) #--Restore Return address LW ra,0(sp) ADDI sp,sp,4 RET Delete_Right_Arrows: #The same as Draw Right Arrows BUT with the background color! li a3, BG_COLOR #Save Return address addi sp,sp,-4 sw ra, 0(sp) ADDI s11,s11,-1 #DECREMENT counter (# of right arrows on the screen) when deleting #---Start Code mv t3,a1 # store a1 into a temporary reg li a0, 65 # x coordinate li a2, 74 # ending x coordinate call draw_horizontal_line #call draw line with current a1 li a0, 74 # X coordinate (hard coded for right arrows) ADDI a1, a1, -2 # Y coordinate call draw_dot # draw red square mv a1,t3 ADDI a1,a1,2 #Y coordiante call draw_dot # draw red square li a0, 76 # X coordinate mv a1,t3 # restore original Y coordinate call draw_dot # draw red square #--Restore Return address LW ra,0(sp) ADDI sp,sp,4 RET Move_Right_Arrows: #a1 -= 1 #Save Return address addi sp,sp,-4 sw ra, 0(sp) #move first arrow lw a1, 0(s10) BLT a1, x0, 1f CALL Delete_Right_Arrows ADDI a1, a1, -1 #updates Y-coordinate to one above #If the coordinate after the updated Y-coordinate is < 0, then we do not want to draw #the arrow since it is off the screen #(We still want to store it back into the array) BLT a1, x0, 2f li a3, 0x1C CALL draw_right_arrow 2: sw a1, 0(s10) 1: #move second arrow lw a1,4(s10) BLT a1, x0, 1f CALL Delete_Right_Arrows ADDI a1,a1,-1 BLT a1,x0,2f li a3, 0x1F #neon blue CALL draw_right_arrow 2: sw a1, 4(s10) 1: #move third arrow lw a1,8(s10) BLT a1, x0, 1f CALL Delete_Right_Arrows ADDI a1,a1,-1 BLT a1,x0,2f li a3, 0xE3 #purple CALL draw_right_arrow 2: sw a1,8(s10) 1: #Restore Return address LW ra,0(sp) ADDI sp,sp,4 RET populate_RIGHT_COLUMN: addi sp,sp,-4 sw ra, 0(sp) mv t4,a1 #save current a1 (the new arrow y-coor) lw t6, 0(s10) lw a4, 4(s10) lw t2, 8(s10) # iffy t2 <= 0, then we delete it because s7[8] data is being shifted off BLT t2, x0, 1f mv a1,t2 #modify a1 with t2, to delete the arrow that is being shifted off call Delete_Right_Arrows 1: sw a4, 8(s10) sw t6, 4(s10) mv a1,t4 #restore a1 original value (the new arrow y-coor) sw a1, 0(s10) #store lw ra,0(sp) #setup return ADDI sp,sp,4 RET #------------------------------- #-----Draw UP Arrows------------ #------------------------------- draw_up_arrow: #Save Return address addi sp,sp,-4 sw ra, 0(sp) ADDI x4,x4,1 #---Start Code mv t3, a1 ADDI a2,a1,8 li a0, 50 # x coordinate call draw_vertical_line #----top dot---- mv a1,t3 li a0, 50 # X coordinate addi a1, a1, -2 call draw_dot # draw red square #----left dot---- li a0, 52 # X coordinate mv a1, t3 call draw_dot # draw red square #----right dot---- li a0, 48 # X coordinate call draw_dot # draw red square #Restore Return address LW ra,0(sp) ADDI sp,sp,4 RET Delete_Up_Arrows: li a3, BG_COLOR #Save Return address addi sp,sp,-4 sw ra, 0(sp) #---Start Code mv t3, a1 ADDI a2,a1,8 li a0, 50 # x coordinate call draw_vertical_line #----top dot---- mv a1,t3 li a0, 50 # X coordinate addi a1, a1, -2 call draw_dot # draw red square #----left dot---- li a0, 52 # X coordinate mv a1, t3 call draw_dot # draw red square #----right dot---- li a0, 48 # X coordinate call draw_dot # draw red square mv a1,t3 ADDI x4,x4,-1 #Restore Return address LW ra,0(sp) ADDI sp,sp,4 RET Move_Up_Arrows: #Save Return address addi sp,sp,-4 sw ra, 0(sp) #get y-coordinate of the first arrow lw a1,0(s9) # IF the coordinate is < 0, then we do not want to delete the arrow (it is out of the screen) #so branch out for the next arrow in the array BLT a1, x0, 1f CALL Delete_Up_Arrows ADDI a1,a1,-1 #updates Y-coordinate to one above #If the coordinate after the updated Y-coordinate is < 0, then we do not want to draw #the arrow since it is off the screen #(We still want to store it back into the array) BLT a1,x0,2f li a3, 0x1C #green CALL draw_up_arrow 2: sw a1,0(s9) #store updated y-coordinate back into the array 1: #move second arrow lw a1,4(s9) #get second arrow's y-coordinate BLT a1, x0, 1f CALL Delete_Up_Arrows #delete the current arrow before the y-coor is updated ADDI a1,a1,-1 #make arrow move up BLT a1,x0,2f li a3, 0x1F #neon blue CALL draw_up_arrow 2: sw a1,4(s9) 1: #move third arrow lw a1,8(s9) #get third arrow's y-coor BLT a1, x0, 1f CALL Delete_Up_Arrows ADDI a1,a1,-1 BLT a1,x0,2f li a3, 0xE3 #purple CALL draw_up_arrow 2: sw a1,8(s9) 1: #Restore Return address LW ra,0(sp) ADDI sp,sp,4 RET populate_UP_COLUMN: addi sp,sp,-4 sw ra, 0(sp) mv t4,a1 #save current a1 (the new arrow y-coor) lw t6, 0(s9) lw a4, 4(s9) lw t2, 8(s9) # iffy t2 <= 0, then we delete it because s7[8] data is being shifted off BLT t2, x0, 1f mv a1,t2 #modify a1 with t2, to delete the arrow that is being shifted off call Delete_Up_Arrows 1: sw a4, 8(s9) sw t6, 4(s9) mv a1,t4 #restore a1 original value (the new arrow y-coor) sw a1, 0(s9) #store lw ra,0(sp) #setup return ADDI sp,sp,4 RET #-------------------------------------- #-----Draw DOWN Arrows----------------- #-------------------------------------- draw_down_arrow: ADDI x3,x3,1 #Save Return address addi sp,sp,-4 sw ra, 0(sp) #---Start Code mv t3,a1 # store a1 into a temporary reg ADDI a2,a1,7 li a0, 30 # x coordinate call draw_vertical_line #call draw line with current a1 li a0, 32 # X coordinate (hard coded for down arrows) mv a1,a2 call draw_dot # draw red square li a0, 28 # X coordinate call draw_dot # draw red square li a0, 30 # X coordinate ADDI a1,a1,2 call draw_dot # draw red square #--Restore Return address LW ra,0(sp) ADDI sp,sp,4 mv a1,t3 RET Delete_Down_Arrows: #this is essentially a draw down arrow but w/ blue color li a3, BG_COLOR #Save Return address addi sp,sp,-4 sw ra, 0(sp) ADDI x3,x3,-1 #---Start Code mv t3,a1 # store a1 into a temporary reg ADDI a2,a1,7 li a0, 30 # x coordinate call draw_vertical_line #call draw line with current a1 li a0, 32 # X coordinate (hard coded for down arrows) mv a1,a2 call draw_dot # draw red square li a0, 28 # X coordinate call draw_dot # draw red square li a0, 30 # X coordinate ADDI a1,a1,2 call draw_dot # draw red square mv a1,t3 #--Restore Return address LW ra,0(sp) ADDI sp,sp,4 RET Move_Down_Arrows: #Save Return address addi sp,sp,-4 sw ra, 0(sp) #move first arrow lw a1,0(s8) # iffy the coordinate is < 0, then we do not want to delete the arrow (it is out of the screen) #so branch out for the next arrow in the array BLT a1, x0, 1f CALL Delete_Down_Arrows ADDI a1,a1,-1 #updates Y-coordinate to one above #If the coordinate after the updated Y-coordinate is < 0, then we do not want to draw #the arrow since it is off the screen #(We still want to store it back into the array) BLT a1,x0,2f li a3, 0x1C #green CALL draw_down_arrow 2: sw a1,0(s8) 1: #move second arrow lw a1,4(s8) BLT a1, x0, 1f CALL Delete_Down_Arrows ADDI a1,a1,-1 BLT a1,x0,2f li a3, 0x1F #neon blue CALL draw_down_arrow 2: sw a1,4(s8) 1: #move third arrow lw a1,8(s8) BLT a1, x0, 1f CALL Delete_Down_Arrows ADDI a1,a1,-1 BLT a1,x0,2f li a3, 0xE3 #purple CALL draw_down_arrow 2: sw a1,8(s8) 1: #Restore Return address LW ra,0(sp) ADDI sp,sp,4 RET populate_DOWN_COLUMN: addi sp,sp,-4 sw ra, 0(sp) mv t4,a1 #save current a1 (the new arrow y-coor) lw t6, 0(s8) lw a4, 4(s8) lw t2, 8(s8) # iffy t2 <= 0, then we delete it because s7[8] data is being shifted off BLT t2, x0, 1f mv a1,t2 #modify a1 with t2, to delete the arrow that is being shifted off call Delete_Down_Arrows 1: sw a4, 8(s8) sw t6, 4(s8) mv a1,t4 #restore a1 original value (the new arrow y-coor) sw a1, 0(s8) #store lw ra,0(sp) #setup return ADDI sp,sp,4 RET #---------------------------------------------------------------------------- #-----------------------Drawing Stationary Arrows---------------------------- #---------------------------------------------------------------------------- draw_stationary_arrow: #ORDER from left to right of the screen: left, down, up, right #Save Return address addi sp,sp,-4 sw ra, 0(sp) li a3, 0xFF #white #-----------LEFT Arrow-------------- li a1, 5 # Y coordinate li a0, 6 # start X coordinate li a2, 14 # ending x coordinate call draw_horizontal_line li a1, 5 # Y coordinate li a0, 4 # X coordinate call draw_dot # draw red square li a1, 3 # Y coordinate li a0, 6 # X coordinate call draw_dot # draw red square li a1, 7 # Y coordinate li a0, 6 # X coordinate call draw_dot # draw red square #-----------RIGHT Arrow-------------- li a0, 65 # x coordinate li a1, 5 # start y coordinate li a2, 74 # ending x coordinate call draw_horizontal_line li a0, 74 # X coordinate li a1, 3 # Y coordinate call draw_dot # draw red square li a0, 74 # X coordinate li a1, 7 # Y coordinate call draw_dot # draw red square li a0, 76 # X coordinate li a1, 5 # Y coordinate call draw_dot # draw red square #-----------DOWN Arrow-------------- li a0, 30 # x coordinate li a1, 3 # start y coordinate li a2, 10 # ending y coordinate call draw_vertical_line li a0, 32 # X coordinate li a1, 10 # Y coordinate call draw_dot # draw red square li a0, 28 # X coordinate li a1, 10 # Y coordinate call draw_dot # draw red square li a0, 30 # X coordinate li a1, 12 # Y coordinate call draw_dot # draw red square #-----------UP Arrow-------------- li a0, 50 # x coordinate li a1, 5 # start y coordinate li a2, 12 # ending y coordinate call draw_vertical_line li a0, 50 # X coordinate li a1, 3 # Y coordinate call draw_dot # draw red square li a0, 52 # X coordinate li a1, 5 # Y coordinate call draw_dot # draw red square li a0, 48 # X coordinate li a1, 5 # Y coordinate call draw_dot # draw red square #Restore Return address LW ra,0(sp) ADDI sp,sp,4 RET #-------------------------------------------------------------------- BUFFER: #slows the ascent of the moving arrows li t0, 1000000 goback: addi t0,t0,-1 BNEZ t0, goback RET #-------------------------------------------------------------------- #---------------DRAW DOT/LINE FUNCTIONS (from Piazza)---------------- #-------------------------------------------------------------------- # draws a horizontal line from (a0,a1) to (a2,a1) using color in a3 draw_horizontal_line: addi sp,sp,-4 sw ra, 0(sp) addi a2,a2,1 #go from a0 to a2 inclusive draw_horiz1: call draw_dot addi a0,a0,1 bne a0,a2, draw_horiz1 lw ra, 0(sp) addi sp,sp,4 ret #--------------------------------------------------------------------- # draws a vertical line from (a0,a1) to (a0,a2) using color in a3 draw_vertical_line: addi sp,sp,-4 sw ra, 0(sp) addi a2,a2,1 draw_vert1: call draw_dot addi a1,a1,1 bne a1,a2,draw_vert1 lw ra, 0(sp) addi sp,sp,4 ret #-------------------------------------------------------------------------------------- # Fills the 60x80 grid with one color using successive calls to draw_horizontal_line draw_background: addi sp,sp,-4 sw ra, 0(sp) li a3, BG_COLOR #use default color li a1, 0 #a1= row_counter li t4, 60 #max rows start: li a0, 0 li a2, 79 #total number of columns call draw_horizontal_line addi a1,a1, 1 bne t4,a1, start #branch to draw more rows lw ra, 0(sp) addi sp,sp,4 ret #------------------------------------------------------------------------ # draws a dot on the display at the given coordinates: # (X,Y) = (a0,a1) with a color stored in a3 # (col, row) = (a0,a1) draw_dot: andi t0,a0,0x7F # select bottom 7 bits (col) andi t1,a1,0x3F # select bottom 6 bits (row) slli t1,t1,7 # {a1[5:0],a0[6:0]} or t0,t1,t0 # 13-bit address sw t0, 0(x18) # write 13 address bits to register sw a3, 0(x19) # write color data to frame buffer ret #-----Initialize Arrays (holds the y-coordinates of each arrow typing)---- .data LEFT_COLUMN: .word -1,-1,-1 DOWN_COLUMN: .word -1,-1,-1 UP_COLUMN: .word -1,-1,-1 RIGHT_COLUMN: .word -1,-1,-1