Advertisement
cooprocks123e

Pong - double-buffered (better)

Mar 10th, 2018
96
0
Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
text 29.87 KB | None | 0 0
  1. # TARGET_SYSTEM = 0: DE0
  2. # TARGET_SYSTEM = 1: DE1-SoC
  3. # TARGET_SYSTEM = 2: DE2 / DE2-115
  4. # TARGET_SYSTEM = 3: DE10-Lite
  5.  
  6. .equ TARGET_SYSTEM, 1 # Used to indicate which FPGA the code will be compiled for
  7.  
  8. # -------------------- SCREEN DATA --------------------
  9.  
  10. .if TARGET_SYSTEM == 0
  11. # 128 bytes/row, 1 byte per pixel: DE0
  12. .equ WIDTH, 80
  13. .equ HEIGHT, 60
  14. .equ LOG2_BYTES_PER_ROW, 7
  15. .equ LOG2_BYTES_PER_PIXEL, 0
  16. .elseif TARGET_SYSTEM == 1 || TARGET_SYSTEM == 2
  17. # 320x240, 1024 bytes/row, 2 bytes per pixel: DE1-SoC, DE2, DE2-115
  18. .equ WIDTH, 320
  19. .equ HEIGHT, 240
  20. .equ LOG2_BYTES_PER_ROW, 10
  21. .equ LOG2_BYTES_PER_PIXEL, 1
  22. .elseif TARGET_SYSTEM == 3
  23. # 160x120, 256 bytes/row, 1 byte per pixel: DE10-Lite
  24. .equ WIDTH, 160
  25. .equ HEIGHT, 120
  26. .equ LOG2_BYTES_PER_ROW, 8
  27. .equ LOG2_BYTES_PER_PIXEL, 0
  28. .else
  29. .error "Error: Invalid target system"
  30. .endif
  31.  
  32. .equ BYTES_PER_ROW, (1 << LOG2_BYTES_PER_ROW)
  33. .equ BYTES_PER_PIXEL, (1 << LOG2_BYTES_PER_PIXEL)
  34.  
  35. .if TARGET_SYSTEM == 0 || TARGET_SYSTEM == 3
  36. # 8-bit colours: DE0, DE10-Lite
  37. .equ BG_COL, 0x00
  38. .equ P_COL, 0xFF
  39. .equ B_COL, 0xF0
  40. .equ MID_COL, 0xFF
  41. .equ CHAR_COL, 0xFF
  42. .equ WIN_COL, 0xF0
  43. .elseif TARGET_SYSTEM == 1 || TARGET_SYSTEM == 2
  44. # 16-bit colours: DE1-SoC, DE2, DE2-115
  45. .equ BG_COL, 0x0000
  46. .equ P_COL, 0xFFFF
  47. .equ B_COL, 0xFF00
  48. .equ MID_COL, 0xFFFF
  49. .equ CHAR_COL, 0xFFFF
  50. .equ WIN_COL, 0xFF00
  51. .endif
  52.  
  53. .equ BUFFER_SIZE, HEIGHT * BYTES_PER_ROW
  54.  
  55. .equ CHARBUF, 0x09000000 # Character buffer. Same on all boards.
  56.  
  57. .equ FRAMEBUFFER_A, prog_end
  58. .equ FRAMEBUFFER_B, FRAMEBUFFER_A + BUFFER_SIZE
  59.  
  60. # -------------------- HARDWARE --------------------
  61.  
  62. .if TARGET_SYSTEM == 0 || TARGET_SYSTEM == 2
  63. # DE0, DE2, DE2-115
  64. .equ VGAPIX_CONTROL, 0x10003020
  65. .equ TIMER_BASE_ADDR, 0x10002000
  66. .equ SWITCHES_BASE_ADDR, 0x10000040
  67. .equ BUTTONS_BASE_ADDR, 0x10000050
  68. .elseif TARGET_SYSTEM == 1 || TARGET_SYSTEM == 3
  69. # DE1-SoC, DE10-Lite
  70. .equ VGAPIX_CONTROL, 0xff203020
  71. .equ TIMER_BASE_ADDR, 0xff202000
  72. .equ SWITCHES_BASE_ADDR, 0xff200040
  73. .equ BUTTONS_BASE_ADDR, 0xff200050
  74. .endif
  75.  
  76. .equ TIMER_INTERVAL, 2500000
  77.  
  78. # -------------------- DATA --------------------
  79.  
  80. .equ CHAR_WIDTH, 3 # Character width
  81. .equ CHAR_HEIGHT, 6 # Character height
  82.  
  83. .equ P_WIDTH, 2 # paddle width
  84. .equ P_HEIGHT, 10 # paddle height
  85.  
  86. .equ P1_X, 3 # Left paddle X coordinate
  87. .equ P2_X, WIDTH-3-P_WIDTH # Right paddle X coordinate
  88.  
  89. .equ SCORE_TO_WIN, 9 # Score reqired to win
  90. .equ SCORE_1_X, WIDTH/2-CHAR_WIDTH*3 # Left score X coordinate
  91. .equ SCORE_2_X, WIDTH/2+CHAR_WIDTH*2+1 # Right score X coordinate
  92. .equ SCORE_Y, 4 # Score number lables Y coordinate
  93.  
  94. .equ WIN_TEXT_X, WIDTH/2-CHAR_WIDTH*4-1 # Win text lable X coordinate
  95. .equ WIN_TEXT_Y, HEIGHT/2-CHAR_HEIGHT+1 # Win text lable Y coordinate
  96.  
  97. # Character numbers in the character map
  98.  
  99. .equ SPACE_CHAR,10
  100. .equ P_CHAR, 11
  101. .equ W_CHAR, 12
  102. .equ I_CHAR, 13
  103. .equ N_CHAR, 14
  104. .equ S_CHAR, 15
  105.  
  106. # Register usage:
  107.  
  108. # r18: Ball X coordinate
  109. # r19: Ball Y coordinate
  110. # r20: Ball X direction
  111. # r21: Ball Y direction
  112.  
  113. # r22: Left paddle Y coordinate
  114. # r23: Right paddle Y coordinate
  115.  
  116. # -------------------- MACROS --------------------
  117.  
  118. .macro H_LINE x1, x2, y, col
  119. movi r4, \x1
  120. movi r5, \x2
  121. movi r6, \y
  122. movui r7, \col
  123. call DrawHLine
  124. .endm
  125.  
  126. .macro V_LINE y1, y2, x, col
  127. movi r4, \y1
  128. movi r5, \y2
  129. movi r6, \x
  130. movui r7, \col
  131. call DrawVLine
  132. .endm
  133.  
  134. .macro DV_LINE y1, y2, x, col
  135. movi r4, \y1
  136. movi r5, \y2
  137. movi r6, \x
  138. movui r7, \col
  139. call DrawDVLine
  140. .endm
  141.  
  142. .macro FILL_COLOR col
  143. movui r4, \col
  144. call FillColourFast
  145. .endm
  146.  
  147. .macro DRAW_CHAR col, row, char
  148. movi r4, \col
  149. movi r5, \row
  150. movi r6, \char
  151. call WriteChar
  152. .endm
  153.  
  154. .macro DRAW_BIG_CHAR x, y, char, col
  155. movi r4, \x
  156. movi r5, \y
  157. mov r6, \char
  158. movui r7, \col
  159. call DrawBigNumber
  160. .endm
  161.  
  162. .macro DRAW_BIG_CHAR_CONST x, y, char, col
  163. movi r4, \x
  164. movi r5, \y
  165. movi r6, \char
  166. movui r7, \col
  167. call DrawBigNumber
  168. .endm
  169.  
  170. .macro DRAW_PIXEL x, y, col
  171. mov r4, \x
  172. mov r5, \y
  173. mov r6, \col
  174. call WritePixel
  175. .endm
  176.  
  177. .macro DRAW_PADDLE x, y, col
  178. movi r4, \x
  179. mov r5, \y
  180. movui r6, \col
  181. call DrawPaddle
  182. .endm
  183.  
  184. # -------------------- INTERRUPTS --------------------
  185. .text
  186. .org 0x20
  187.  
  188. # Exception handler - MUST BE AT ADDRESS 0x20
  189. subi sp, sp, 8 # Make room on stack
  190. stw ra, 0(sp) # Save ra
  191. stw r19, 4(sp) # Save r19
  192.  
  193. # Fetch contents of ctl4 to see if it is hardware interrupt.
  194. rdctl et, ipending
  195.  
  196. # If at least one bit is on, it means a hardware device is requesting attention
  197. beq et, r0, END_HANDLER # No bits set - not hardware
  198.  
  199. # Hardware interrupt code. Have to set address back, so that when interrupt handler done, the instruction gets executed.
  200. subi ea, ea, 4
  201.  
  202. andi r19, et, 1 # Check bit 0
  203. beq r19, r0, END_HANDLER # Was not interrupt 0
  204. call TIMER_IRQ
  205.  
  206. # Exit point for the exception handler
  207. END_HANDLER:
  208. ldw r19, 4(sp) # Restore saved register
  209. ldw ra, 0(sp) # Restore saved register
  210. addi sp, sp, 8 # Adjust stack pointer
  211. eret
  212.  
  213. .org 0x100
  214. .extern CONTINUE_FLAG
  215.  
  216. # Device-specific code for interval timer interrupt source
  217. TIMER_IRQ:
  218. subi sp, sp, 12
  219. stw ra, 0(sp)
  220. stw r4, 4(sp)
  221. stw r5, 8(sp)
  222.  
  223. movia r5, TIMER_BASE_ADDR # Interval timer base address
  224. sthio r0, 0(r5) # Clear the interrupt
  225.  
  226. # Set can continue running flag to 1
  227. ldw r4, CONTINUE_FLAG(r0)
  228. movi r4, 1
  229. stw r4, CONTINUE_FLAG(r0)
  230.  
  231. ldw r5, 8(sp)
  232. ldw r4, 4(sp)
  233. ldw ra, 0(sp)
  234. addi sp, sp, 12
  235. ret # Return from the ISR
  236.  
  237. # -------------------- START --------------------
  238.  
  239. .global _start
  240.  
  241. _start:
  242. movia sp, 0x800000 # Initial stack pointer
  243.  
  244. # Initialize framebuffers to empty
  245. movi r4, 0x0000
  246. call FillColourFast
  247. call SwapBuffers
  248. movi r4, 0x0000
  249. call FillColourFast
  250. call SwapBuffers
  251.  
  252. movi r16, WIDTH # Width
  253. movi r17, HEIGHT-1 # Height
  254.  
  255. movia r9, SWITCHES_BASE_ADDR # Switches I/O Address
  256. movia r3, BUTTONS_BASE_ADDR # Buttons I/O Address
  257. movi r15, 255 # Number of NOP delays
  258.  
  259. movi r14, HEIGHT-P_HEIGHT # Midline X coordinate in middle
  260. movi r22, HEIGHT/2-P_HEIGHT/2 # Left paddle Y coordinate in middle
  261. movi r23, HEIGHT/2-P_HEIGHT/2 # Right paddle Y coordinate in middle
  262. movi r18, WIDTH/2 # Ball X coordinate in middle
  263. movi r19, HEIGHT/2 # Ball Y coordinate in middle
  264. movi r20, 1 # Ball X direction
  265. movi r21, 1 # Ball Y direction
  266.  
  267. # Setup interval timer
  268. movia r13, TIMER_BASE_ADDR # Internal timer base address
  269. movia r12, TIMER_INTERVAL # 1/(50 MHz) x (2500000) = 50 msec
  270. sthio r12, 8(r13) # Store the low halfword of counter start value
  271. srli r12, r12, 16
  272. sthio r12, 12(r13) # High halfword of counter start value
  273.  
  274. # Start interval timer, enable its interrupts
  275. movi r15, 0b0111 # START = 1, CONT = 1, ITO = 1
  276. sthio r15, 4(r13)
  277.  
  278. # Enable Nios II processor interrupts
  279. movi r7, 0b1 # Set interrupt mask bits for level 0 (interval timer)
  280. wrctl ienable, r7
  281. movi r7, 1
  282. wrctl status, r7 # Turn on Nios II interrupt processing
  283. #movi r7, 0
  284. #wrctl ipending, r7 # Clear pending interrupts
  285.  
  286. # Set can continue running flag to 0
  287. ldw r4, CONTINUE_FLAG(r0)
  288. movi r4, 0
  289. stw r4, CONTINUE_FLAG(r0)
  290.  
  291. # Set scores to 0
  292. ldw r4, SCORE_P1(r0)
  293. ldw r5, SCORE_P2(r0)
  294. movi r4, 0
  295. movi r5, 0
  296. stw r4, SCORE_P1(r0)
  297. stw r5, SCORE_P2(r0)
  298.  
  299. # We don't need to clear the character buffer because it is defined
  300. # to be initialized to the space character
  301. #call ClearScreen
  302.  
  303. # -------------------- LOOP --------------------
  304.  
  305. Loop:
  306. FILL_COLOR BG_COL # Clear screen
  307.  
  308. # -------------------- TESTING CODE --------------------
  309.  
  310. /*
  311. asdfasdf:
  312. ldw r4, CONTINUE_FLAG(r0)
  313. beq r4, r0, asdfasdf
  314. movi r4, 0
  315. stw r4, CONTINUE_FLAG(r0)
  316. br Loop
  317. */
  318.  
  319. /*
  320. FILL_COLOR B_COL
  321. DRAW_BIG_CHAR_CONST 1, 1, 0, CHAR_COL
  322. DRAW_BIG_CHAR_CONST 1+(CHAR_WIDTH+1)*1, 1, 1, CHAR_COL
  323. DRAW_BIG_CHAR_CONST 1+(CHAR_WIDTH+1)*2, 1, 2, CHAR_COL
  324. DRAW_BIG_CHAR_CONST 1+(CHAR_WIDTH+1)*3, 1, 3, CHAR_COL
  325. DRAW_BIG_CHAR_CONST 1+(CHAR_WIDTH+1)*4, 1, 4, CHAR_COL
  326. DRAW_BIG_CHAR_CONST 1+(CHAR_WIDTH+1)*5, 1, 5, CHAR_COL
  327. DRAW_BIG_CHAR_CONST 1+(CHAR_WIDTH+1)*6, 1, 6, CHAR_COL
  328. DRAW_BIG_CHAR_CONST 1+(CHAR_WIDTH+1)*7, 1, 7, CHAR_COL
  329. DRAW_BIG_CHAR_CONST 1+(CHAR_WIDTH+1)*8, 1, 8, CHAR_COL
  330. DRAW_BIG_CHAR_CONST 1+(CHAR_WIDTH+1)*9, 1, 9, CHAR_COL
  331. DRAW_BIG_CHAR_CONST 1+(CHAR_WIDTH+1)*10, 1, SPACE_CHAR, CHAR_COL
  332. DRAW_BIG_CHAR_CONST 1+(CHAR_WIDTH+1)*11, 1, P_CHAR, CHAR_COL
  333. DRAW_BIG_CHAR_CONST 1+(CHAR_WIDTH+1)*12, 1, W_CHAR, CHAR_COL
  334. DRAW_BIG_CHAR_CONST 1+(CHAR_WIDTH+1)*13, 1, I_CHAR, CHAR_COL
  335. DRAW_BIG_CHAR_CONST 1+(CHAR_WIDTH+1)*14, 1, N_CHAR, CHAR_COL
  336. DRAW_BIG_CHAR_CONST 1+(CHAR_WIDTH+1)*15, 1, S_CHAR, CHAR_COL
  337. br End
  338. */
  339.  
  340. # -------------------- DRAWING --------------------
  341.  
  342. DRAW_PADDLE P1_X, r22, P_COL # Draw left paddle
  343. DRAW_PADDLE P2_X, r23, P_COL # Draw right paddle
  344.  
  345. DV_LINE 0, HEIGHT, WIDTH/2, MID_COL # Draw midline
  346.  
  347. ldw r11, SCORE_P1(r0) # Load left score
  348. ldw r12, SCORE_P2(r0) # Load right score
  349. DRAW_BIG_CHAR SCORE_1_X, SCORE_Y, r11, CHAR_COL # Draw left score
  350. DRAW_BIG_CHAR SCORE_2_X, SCORE_Y, r12, CHAR_COL # Draw right score
  351.  
  352. movui r6, B_COL
  353. DRAW_PIXEL r18, r19, r6 # Ball
  354.  
  355. # -------------------- CHECK WIN --------------------
  356.  
  357. ldw r11, SCORE_P1(r0) # Load left scores
  358. ldw r12, SCORE_P2(r0) # Load right scores
  359.  
  360. movi r10, SCORE_TO_WIN
  361. bge r11, r10, P1_WINS # If left score >= scrore to win, left player wins
  362. bge r12, r10, P2_WINS # If right score >= scrore to win, right player wins
  363. br Check_Input
  364.  
  365. P1_WINS:
  366. DRAW_PADDLE P1_X, r22, WIN_COL # Draw left paddle
  367. DRAW_BIG_CHAR SCORE_1_X, SCORE_Y, r11, WIN_COL # Draw left score
  368. ldw r2, WINNER(r0)
  369. movi r2, 1 # Set winner to 1
  370. stw r2, WINNER(r0)
  371. br Print_Win_Text
  372. P2_WINS:
  373. DRAW_PADDLE P2_X, r23, WIN_COL # Draw right paddle
  374. DRAW_BIG_CHAR SCORE_2_X, SCORE_Y, r12, WIN_COL # Draw right score
  375. ldw r2, WINNER(r0)
  376. movi r2, 2 # Set winner to 2
  377. stw r2, WINNER(r0)
  378. br Print_Win_Text
  379.  
  380. # -------------------- INPUTS --------------------
  381.  
  382. Check_Input:
  383. ldwio r8, 0(r9) # Read switches
  384. andi r10, r8, 256 # Check switch 8 (Left paddle down)
  385. andi r11, r8, 512 # Check switch 9 (Left paddle up)
  386. andi r12, r8, 1 # Check switch 1 (Right paddle down)
  387. andi r13, r8, 2 # Check switch 2 (Right paddle up)
  388.  
  389. # -------------------- PADDLE MOVEMENT --------------------
  390.  
  391. beq r10, r0, Skip_P1_Plus_Y # If left paddle down switch is off, don't move it down
  392. beq r22, r14, Skip_P1_Plus_Y # If left paddle is at bottom, don't move it down
  393. addi r22, r22, 1 # Else, move it down
  394. Skip_P1_Plus_Y:
  395. beq r11, r0, Skip_P1_Minus_Y # If left paddle up switch is off, don't move it up
  396. beq r22, r0, Skip_P1_Minus_Y # If left paddle is at top, don't move it up
  397. subi r22, r22, 1 # Else, move it up
  398. Skip_P1_Minus_Y:
  399. beq r12, r0, Skip_P2_Plus_Y # If right paddle down switch is off, don't move it down
  400. beq r23, r14, Skip_P2_Plus_Y # If right paddle is at bottom, don't move it down
  401. addi r23, r23, 1 # Else, move it down
  402. Skip_P2_Plus_Y:
  403. beq r13, r0, Skip_P2_Minus_Y # If right paddle up switch is off, don't move it up
  404. beq r23, r0, Skip_P2_Minus_Y # If right paddle is at top, don't move it up
  405. subi r23, r23, 1 # Else, move it up
  406. Skip_P2_Minus_Y:
  407.  
  408. # -------------------- BALL MOVEMENT --------------------
  409.  
  410. movi r10, P1_X+P_WIDTH # Left paddle X coordinate
  411. movi r11, P2_X-1 # Right paddle X coordinate
  412.  
  413. X_Calculations:
  414. beq r18, r10, B_Check_P_1_Hit # If Ball X = Left paddle X, check if paddle was hit
  415. beq r18, r11, B_Check_P_2_Hit # If Ball X = Right paddle X, check if paddle was hit
  416. beq r18, r16, B_Hit_Right # If Ball X = Right wall, increase left score, reset ball
  417. beq r18, r0, B_Hit_Left # If Ball X = Left wall, increase right score, reset ball
  418. br Update_B_X
  419. B_Check_P_1_Hit:
  420. blt r19, r22, Update_B_X # If Ball Y higher than left paddle Y, skip
  421. addi r10, r22, P_HEIGHT
  422. bgt r19, r10, Update_B_X # If Ball Y lower than left paddle Y, skip
  423. movi r20, 1 # Set ball X direction to right
  424. br Update_B_X
  425. B_Check_P_2_Hit:
  426. blt r19, r23, Update_B_X # If Ball Y higher than right paddle Y, skip
  427. addi r11, r23, P_HEIGHT
  428. bgt r19, r11, Update_B_X # If Ball Y lower than right paddle Y, skip
  429. movi r20, -1 # Set ball X direction to left
  430. br Update_B_X
  431.  
  432. B_Hit_Right:
  433. V_LINE 0, HEIGHT, WIDTH-1, B_COL # Draw vertical hit indicator line
  434. movi r18, WIDTH/2 # Ball X Pos in middle
  435. movi r19, HEIGHT/2 # Ball Y Pos in middle
  436. movi r20, -1 # Ball X direction set to left
  437. ldw r11, SCORE_P1(r0) # Load score 1 (left paddle)
  438. addi r11, r11, 1 # Increment score 1 (left paddle)
  439. stw r11, SCORE_P1(r0) # Store score 1 (left paddle)
  440. br Update_B_X
  441. B_Hit_Left:
  442. V_LINE 0, HEIGHT, 0, B_COL # Draw vertical hit indicator line
  443. movi r18, WIDTH/2 # Ball X Pos in middle
  444. movi r19, HEIGHT/2 # Ball Y Pos in middle
  445. movi r20, 1 # # Ball X direction set to right
  446. ldw r12, SCORE_P2(r0) # Load score 2 (right paddle)
  447. addi r12, r12, 1 # Increment score 21 (right paddle)
  448. stw r12, SCORE_P2(r0) # Store score 2 (right paddle)
  449. br Update_B_X
  450.  
  451. Update_B_X:
  452. add r18, r18, r20 # Move the ball in the X direction
  453.  
  454. Y_Calculations:
  455. beq r19, r17, B_Set_Y_Dir_Minus # If Ball Y = Bottom wall, bounce
  456. beq r19, r0, B_Set_Y_Dir_Plus # If Ball Y = Top wall, bounce
  457. br Update_B_Y
  458. B_Set_Y_Dir_Minus:
  459. movi r21, -1 # Ball Y direction set to up
  460. br Update_B_Y
  461. B_Set_Y_Dir_Plus:
  462. movi r21, 1 # Ball Y direction set to down
  463.  
  464. Update_B_Y:
  465. add r19, r19, r21 # Move the ball in the Y direction
  466.  
  467. # -------------------- DELAY --------------------
  468.  
  469. # Instead of waiting using the timer interrupt, we're going to swap the buffers
  470. # Part of swapping the buffers requires us to wait until the buffer has actually been swapped
  471. # This synchronizes us so the code runs once per frame
  472. call SwapBuffers
  473. br Loop
  474.  
  475. Wait:
  476. ldw r4, CONTINUE_FLAG(r0) # Load the continue flag from mem.
  477. beq r4, r0, Wait # If flag is not set, loop back and keep waiting
  478. movi r4, 0 # Otherwise, clear the flag
  479. stw r4, CONTINUE_FLAG(r0) # Store the continue flag from mem.
  480. br Loop
  481.  
  482. # -------------------- DISPLAY WIN TEXT --------------------
  483.  
  484. Print_Win_Text:
  485. ldw r2, WINNER(r0) # Load winner from mem.
  486.  
  487. # Draw the "PX Wins" where X is the winner number (1 or 2)
  488. DRAW_BIG_CHAR_CONST WIN_TEXT_X+(CHAR_WIDTH+1)*0, WIN_TEXT_Y, P_CHAR, WIN_COL
  489. DRAW_BIG_CHAR WIN_TEXT_X+(CHAR_WIDTH+1)*1, WIN_TEXT_Y, r2, WIN_COL
  490. DRAW_BIG_CHAR_CONST WIN_TEXT_X+(CHAR_WIDTH+1)*2, WIN_TEXT_Y, SPACE_CHAR, WIN_COL
  491. DRAW_BIG_CHAR_CONST WIN_TEXT_X+(CHAR_WIDTH+1)*3, WIN_TEXT_Y, W_CHAR, WIN_COL
  492. DRAW_BIG_CHAR_CONST WIN_TEXT_X+(CHAR_WIDTH+1)*4, WIN_TEXT_Y, I_CHAR, WIN_COL
  493. DRAW_BIG_CHAR_CONST WIN_TEXT_X+(CHAR_WIDTH+1)*5, WIN_TEXT_Y, N_CHAR, WIN_COL
  494. DRAW_BIG_CHAR_CONST WIN_TEXT_X+(CHAR_WIDTH+1)*6, WIN_TEXT_Y, S_CHAR, WIN_COL
  495.  
  496. Wait_For_Restart_Button:
  497. ldwio r8, 0(r3) # Read buttons
  498. andi r10, r8, 1 # Get button 0 status
  499. bne r10, r0, _start # Branch to start if button is pressed
  500. br Wait_For_Restart_Button # Otherwise, keep waiting for a button press
  501.  
  502. End:
  503. br End
  504.  
  505.  
  506. .data
  507. .global CONTINUE_FLAG
  508. CONTINUE_FLAG: .word 0 # Gets set by the interval timer indicating that the loop can continue
  509. SCORE_P1: .word 0 # Left player score
  510. SCORE_P2: .word 0 # Right player score
  511. WINNER: .word 0 # Temporary variable to record the winning player's number (1 or 2)
  512. CUR_BUFFER: .word 0 # 1 if we're currently writing to framebuffer A, 0 for buffer B
  513.  
  514. # Character map holds the data for the big score characters
  515. # The MSB is column 0 (left) of the char, drawn from bottom to top
  516. # The next byte is column 1 of the char, drawn from bottom to top
  517. # The next byte is column 2 of the char, drawn from bottom to top
  518. # The LSB is column 3 (right) of the char, drawn from bottom to top
  519.  
  520. BIG_CHAR_MAP: .word 0x3E223E00 # 0
  521. .word 0x243E2000 # 1
  522. .word 0x322A2400 # 2
  523. .word 0x222A3E00 # 3
  524. .word 0x0E083E00 # 4
  525. .word 0x2E2A3A00 # 5
  526. .word 0x3E2A3A00 # 6
  527. .word 0x023A0600 # 7
  528. .word 0x3E2A3E00 # 8
  529. .word 0x2E2A3E00 # 9
  530. .word 0x00000000 # [Space]
  531. .word 0x3E0A0E00 # P
  532. .word 0x3E103E00 # W
  533. .word 0x223E2200 # I
  534. .word 0x3C081E00 # N
  535. .word 0x2E2A3A00 # S
  536.  
  537. .text
  538.  
  539. # -------------------- DRAWING --------------------
  540.  
  541. # r4: X
  542. # r5: Y
  543. # r6: Character number in character map
  544. # r7: Colour value
  545. DrawBigNumber:
  546. subi sp, sp, 44
  547. stw r4, 0(sp)
  548. stw r5, 4(sp)
  549. stw r14, 8(sp)
  550. stw r15, 12(sp)
  551. stw r16, 16(sp)
  552. stw r17, 20(sp)
  553. stw r18, 24(sp)
  554. stw r19, 28(sp)
  555. stw r20, 32(sp)
  556. stw r21, 36(sp)
  557. stw ra, 40(sp)
  558.  
  559. mov r14, r4 # r14 <- Start X
  560. movi r18, CHAR_HEIGHT
  561. movi r16, CHAR_WIDTH-1
  562.  
  563. movi r21, BG_COL
  564.  
  565. slli r6, r6, 2 # Multiply number to draw in r6 by 4 to get proper offset
  566.  
  567. movia r19, 0x80000000 # r19 <- Bitmask (1 + 31 zeros)
  568.  
  569. ldw r20, BIG_CHAR_MAP(r6) # Load current char map
  570.  
  571. # Two loops to draw the big char
  572. LoopX:
  573. movi r17, 7 # Reset current Y to 7
  574. ldw r15, 4(sp) # r15 <- Start Y
  575. addi r15, r15, 8 # Add 8 to start Y to begin drawing from bottom
  576. LoopY:
  577. bge r17, r18, Skip_Draw # If current Y counter > Char weight, skip draw
  578. and r5, r19, r20 # Check if current bit is set
  579. beq r5, r0, Draw_BG_Col # If current bit is 0, draw the background colour
  580. DRAW_PIXEL r14, r15, r7 # Draw the pixel in the specified colour
  581. br Skip_Draw
  582. Draw_BG_Col:
  583. DRAW_PIXEL r14, r15, r21 # Draw the pixel in the background colour
  584. Skip_Draw:
  585. srli r19, r19, 1 # Shift bitmask right
  586. subi r15, r15, 1 # Decrement Y coordinate
  587. subi r17, r17, 1 # Decrement Y counter
  588. bge r17, r0, LoopY # Loop if Y counter >= 0
  589. addi r14, r14, 1 # Increment X coordinate
  590. subi r16, r16, 1 # Decrement X counter
  591. bge r16, r0, LoopX # Loop if X counter >= 0
  592.  
  593. ldw ra, 40(sp)
  594. ldw r21, 36(sp)
  595. ldw r20, 32(sp)
  596. ldw r19, 28(sp)
  597. ldw r18, 24(sp)
  598. ldw r17, 20(sp)
  599. ldw r16, 16(sp)
  600. ldw r15, 12(sp)
  601. ldw r14, 8(sp)
  602. ldw r5, 4(sp)
  603. ldw r4, 0(sp)
  604. addi sp, sp, 44
  605. ret
  606.  
  607.  
  608. # r4: X
  609. # r5: Y
  610. # r6: Colour value
  611. DrawPaddle:
  612. subi sp, sp, 40
  613. stw r4, 0(sp)
  614. stw r5, 4(sp)
  615. stw r6, 8(sp)
  616. stw r7, 12(sp)
  617. stw r16, 16(sp)
  618. stw r17, 20(sp)
  619. stw r18, 24(sp)
  620. stw r19, 28(sp)
  621. stw r20, 32(sp)
  622. stw ra, 36(sp)
  623.  
  624. mov r16, r4 # r16 <- Start X
  625. mov r17, r4
  626. addi r17, r17, P_WIDTH # r17 <- End X
  627.  
  628. mov r18, r5 # r18 <- Start Y
  629. mov r19, r5
  630. addi r19, r19, P_HEIGHT # r19 <- End Y
  631.  
  632. mov r20, r6 # r20 <- Colour
  633.  
  634. 1: mov r4, r18 # Line start Y <- start X
  635. mov r5, r19 # Line end Y <- end Y
  636. mov r6, r16 # Line X <- current X
  637. mov r7, r20 # Line colour <- specified colour
  638. call DrawVLine # Draw a single vertical line
  639. addi r16, r16, 1 # Increment current X
  640. blt r16, r17, 1b # Loop if current X < end X
  641.  
  642. ldw ra, 36(sp)
  643. ldw r20, 32(sp)
  644. ldw r19, 28(sp)
  645. ldw r18, 24(sp)
  646. ldw r17, 20(sp)
  647. ldw r16, 16(sp)
  648. ldw r7, 12(sp)
  649. ldw r6, 8(sp)
  650. ldw r5, 4(sp)
  651. ldw r4, 0(sp)
  652. addi sp, sp, 40
  653. ret
  654.  
  655.  
  656. # r4: Start X
  657. # r5: End X
  658. # r6: Y
  659. # r7: Colour value
  660. DrawHLine:
  661. subi sp, sp, 24
  662. stw r4, 0(sp)
  663. stw r5, 4(sp)
  664. stw r6, 8(sp)
  665. stw r16, 12(sp)
  666. stw r17, 16(sp)
  667. stw ra, 20(sp)
  668.  
  669. mov r17, r4 # r17 <- Start X
  670. mov r16, r5 # r16 <- End X
  671. mov r5, r6 # r5 <- Y
  672. mov r6, r7 # r6 <- Colour
  673.  
  674. 1: mov r4, r16 # Pixel X <- current X
  675. call WritePixel # Draw one pixel
  676. subi r16, r16, 1 # Decrement current X
  677. bge r16, r17, 1b # Loop if current X >= start X
  678.  
  679. ldw ra, 20(sp)
  680. ldw r17, 16(sp)
  681. ldw r16, 12(sp)
  682. ldw r6, 8(sp)
  683. ldw r5, 4(sp)
  684. ldw r4, 0(sp)
  685. addi sp, sp, 24
  686. ret
  687.  
  688.  
  689. # r4: Start Y
  690. # r5: End Y
  691. # r6: X
  692. # r7: Colour value
  693. DrawVLine:
  694. subi sp, sp, 24
  695. stw r4, 0(sp)
  696. stw r5, 4(sp)
  697. stw r6, 8(sp)
  698. stw r16, 12(sp)
  699. stw r17, 16(sp)
  700. stw ra, 20(sp)
  701.  
  702. mov r17, r4 # r17 <- Start Y
  703. mov r16, r5 # r16 <- End Y
  704. mov r4, r6 # r4 <- X
  705. mov r6, r7 # r6 <- Colour
  706.  
  707. 1: mov r5, r16 # Pixel Y <- current Y
  708. call WritePixel # Draw one pixel
  709. subi r16, r16, 1 # Decrement current Y
  710. bge r16, r17, 1b # Loop if current Y >= start Y
  711.  
  712. ldw ra, 20(sp)
  713. ldw r17, 16(sp)
  714. ldw r16, 12(sp)
  715. ldw r6, 8(sp)
  716. ldw r5, 4(sp)
  717. ldw r4, 0(sp)
  718. addi sp, sp, 24
  719. ret
  720.  
  721.  
  722. # r4: Start Y
  723. # r5: End Y
  724. # r6: X
  725. # r7: Colour value
  726. DrawDVLine:
  727. subi sp, sp, 28
  728. stw r4, 0(sp)
  729. stw r5, 4(sp)
  730. stw r6, 8(sp)
  731. stw r16, 12(sp)
  732. stw r17, 16(sp)
  733. stw r18, 20(sp)
  734. stw ra, 24(sp)
  735.  
  736. mov r17, r4 # r17 <- Start Y
  737. mov r16, r5 # r16 <- End Y
  738. mov r4, r6 # r4 <- X
  739. mov r6, r7 # r6 <- Colour
  740.  
  741. 1: andi r18, r16, 1 # r18 <- LSB of current Y
  742. bne r18, r0, Skip_Draw_Pixel # If current Y is odd, don't draw the current pixel
  743. mov r5, r16 # Pixel Y <- current Y
  744. call WritePixel # Draw one pixel
  745. Skip_Draw_Pixel:
  746. subi r16, r16, 1 # Decrement current Y
  747. bge r16, r17, 1b # Loop if current Y >= start Y
  748.  
  749. ldw ra, 24(sp)
  750. ldw r18, 20(sp)
  751. ldw r17, 16(sp)
  752. ldw r16, 12(sp)
  753. ldw r6, 8(sp)
  754. ldw r5, 4(sp)
  755. ldw r4, 0(sp)
  756. addi sp, sp, 28
  757. ret
  758.  
  759.  
  760. # r4: Colour value
  761. FillColourFast:
  762. subi sp, sp, 20
  763. stw r8, 0(sp)
  764. stw r9, 4(sp)
  765. stw r10, 8(sp)
  766. stw r2, 12(sp)
  767. stw ra, 16(sp)
  768.  
  769. .if LOG2_BYTES_PER_PIXEL == 0
  770. # One pixel takes up 1 byte
  771. # Copy the colour stored in r4 into r8 4 times
  772. # This way r8 contains 4 colour values to write at once into the vga pixel buffer
  773. andi r8, r4, 0xff # r8 <- LSB of r4 (1 colour value)
  774. slli r9, r8, 8 # r9 <- LSB of r4 shifted 1 byte left
  775. or r8, r8, r9 # r8 <- LSB of r4 in 1st byte + LSB of r4 in 0th byte
  776. slli r9, r8, 16 # r9 <- r8 shifted 2 bytes left
  777. or r8, r9, r8 # r8 <- LSB of r4 in all 4 bytes (4 colour values)
  778. .elseif LOG2_BYTES_PER_PIXEL == 1
  779. # One pixel takes up 2 bytes
  780. # Copy the colour stored in r4 into r8 2 times
  781. # This way r8 contains 2 colour values to write at once into the vga pixel buffer
  782. andi r8, r4, 0xffff # r8 <- Last 2 bytes of r4 (1 colour value)
  783. slli r9, r8, 16 # r9 <- r8 shifted 2 bytes left
  784. or r8, r9, r8 # r8 <- Last 2 bytes of r4 both high and low order (2 colour values)
  785. .elseif LOG2_BYTES_PER_PIXEL == 2
  786. # One pixel takes up 4 bytes
  787. # Don't need to do anything
  788. .else
  789. .error "Error: Unknown pixel size"
  790. .endif
  791.  
  792. movia r9, (BYTES_PER_ROW)*HEIGHT-4 # r9 <- Offset of last pixel in vga pixel buffer
  793. call GetBufferPointer
  794. mov r10, r2 # r10 <- Base address of vga pixel buffer
  795. add r9, r9, r10 # r9 <- Address of last pixel in vga pixel buffer
  796.  
  797. # This is a temporary label!! You can do this!! :)
  798. 1:
  799. stwio r8, 0(r9) # Write 1, 2, or 4 pixels at once to current pixel in vga pixel buffer
  800. subi r9, r9, 4 # Move to previous pixel
  801. nop # Wait for the vga pixel buffer hardware
  802. nop # Keep waiting ...
  803. nop # Keep waiting ...
  804. nop # Keep waiting ...
  805. nop # Keep waiting ...
  806. nop # Keep waiting ...
  807. bge r9, r10, 1b # Loop if current pixel address >= first pixel address
  808.  
  809. ldw r8, 0(sp)
  810. ldw r9, 4(sp)
  811. ldw r10, 8(sp)
  812. ldw r2, 12(sp)
  813. ldw ra, 16(sp)
  814. addi sp, sp, 20
  815. ret
  816.  
  817.  
  818. ClearScreen:
  819. subi sp, sp, 24
  820. stw r4, 0(sp)
  821. stw r5, 4(sp)
  822. stw r6, 8(sp)
  823. stw r16, 12(sp)
  824. stw r17, 16(sp)
  825. stw ra, 20(sp)
  826.  
  827. FILL_COLOR BG_COL # Fill the screen with the background colour
  828.  
  829. # Clear the pixel buffer as well
  830. movi r16, WIDTH-1 # r16 <- End X
  831. 1: movi r17, HEIGHT-1 # r17 <- End Y
  832. 2: mov r4, r16 # Char X <- current X
  833. mov r5, r17 # Char Y <- current Y
  834. mov r6, r0 # Char value <- 0 (blank)
  835. call WriteChar # Draw one char
  836. subi r17, r17, 1 # Decrement current Y
  837. bge r17, r0, 2b # Loop if current Y >= 0
  838. subi r16, r16, 1 # Decrement current X
  839. bge r16, r0, 1b # Loop if current X >= 0
  840.  
  841. ldw ra, 20(sp)
  842. ldw r17, 16(sp)
  843. ldw r16, 12(sp)
  844. ldw r6, 8(sp)
  845. ldw r5, 4(sp)
  846. ldw r4, 0(sp)
  847. addi sp, sp, 24
  848. ret
  849.  
  850.  
  851. # r4: Column (x)
  852. # r5: Row (y)
  853. # r6: Character value
  854. WriteChar:
  855. subi sp, sp, 12
  856. stw r4, 0(sp)
  857. stw r5, 4(sp)
  858. stw r6, 8(sp)
  859.  
  860. slli r5, r5, 7 # r5 <- Calculated memory offset due to Y
  861. add r5, r5, r4 # r5 <- Calculated memory offset for specified X,Y
  862. movia r4, CHARBUF # r4 <- Address of character buffer
  863. add r5, r5, r4 # r5 <- Calculated memory address for specified X,Y
  864. stbio r6, 0(r5) # Write character to character buffer
  865.  
  866. ldw r6, 8(sp)
  867. ldw r5, 4(sp)
  868. ldw r4, 0(sp)
  869. addi sp, sp, 12
  870. ret
  871.  
  872.  
  873. # r4: X
  874. # r5: Y
  875. # r6: Colour value
  876. WritePixel:
  877. subi sp, sp, 20
  878. stw r2, 0(sp)
  879. stw r4, 4(sp)
  880. stw r5, 8(sp)
  881. stw r6, 12(sp)
  882. stw ra, 16(sp)
  883.  
  884. slli r5, r5, LOG2_BYTES_PER_ROW # r5 <- Calculated memory offset due to Y
  885. slli r4, r4, LOG2_BYTES_PER_PIXEL # r4 <- Calculated memory offset due to X
  886. add r5, r5, r4 # r5 <- Calculated memory offset for specified X,Y
  887. call GetBufferPointer # r2 <- Current buffer address
  888. add r5, r5, r2 # r5 <- Calculated memory address for specified X,Y
  889.  
  890. .if LOG2_BYTES_PER_PIXEL == 0
  891. stbio r6, 0(r5) # Write 8-bit pixel to vga pixel buffer
  892. .elseif LOG2_BYTES_PER_PIXEL == 1
  893. sthio r6, 0(r5) # Write 16-bit pixel to vga pixel buffer
  894. .elseif LOG2_BYTES_PER_PIXEL == 2
  895. stwio r6, 0(r5) # Write 32-bit pixel to vga pixel buffer
  896. .else
  897. .error "Error: Unknown pixel size"
  898. .endif
  899.  
  900. ldw ra, 16(sp)
  901. ldw r6, 12(sp)
  902. ldw r5, 8(sp)
  903. ldw r4, 4(sp)
  904. ldw r2, 0(sp)
  905. addi sp, sp, 20
  906. ret
  907.  
  908. # u16 * GetBufferPointer(void)
  909. # Returns a pointer to the current framebuffer
  910. GetBufferPointer:
  911. ldb r2, CUR_BUFFER(r0)
  912. bne r0, r2, 1f
  913. movia r2, FRAMEBUFFER_B
  914. ret
  915. 1:
  916. movia r2, FRAMEBUFFER_A
  917. ret
  918.  
  919. # void SwapBuffers(void)
  920. # Flips the current drawing buffer to screen
  921. SwapBuffers:
  922. subi sp, sp, 16
  923. stw ra, 0(sp)
  924. stw r2, 4(sp)
  925. stw r8, 8(sp)
  926. stw r9, 12(sp)
  927.  
  928. call GetBufferPointer
  929. movia r8, VGAPIX_CONTROL
  930. stwio r2, 4(r8)
  931. stwio r2, 0(r8)
  932.  
  933. # Busy-loop until buffer is done being displayed
  934. 1:
  935. ldwio r9, 12(r8)
  936. andi r9, r9, 1
  937. bne r0, r9, 1b
  938.  
  939. # Swap which buffer is drawn
  940. # CUR_BUFFER = (CUR_BUFFER == 0) ? 1 : 0;
  941. ldb r8, CUR_BUFFER(r0)
  942. cmpeq r8, r0, r8
  943. stb r8, CUR_BUFFER(r0)
  944.  
  945. ldw ra, 0(sp)
  946. ldw r2, 4(sp)
  947. ldw r8, 8(sp)
  948. ldw r9, 12(sp)
  949. addi sp, sp, 16
  950. ret
  951.  
  952. .data
  953. .word 0x11223344
  954. prog_end:
Advertisement
Add Comment
Please, Sign In to add comment
Advertisement