This was written 100% by hand without any assistance from our silicon based overlords.
Initialisation
.syntax unified
.global main
.type main, %function
main:
initialise:
@ Set all pins on microbit to output
bl initialise_output_pins
@ start animation on death and startup
game_start:
@ print heart on
ldr r1, =heart_on
ldr r0, [r1]
ldr r1, =game_state
str r0, [r1]
mov r0, 0xfff
pi_1:
cmp r0, 0
beq exit_pi_1
bl print_game
sub r0, 1
b pi_1
exit_pi_1:
@ print heart off
ldr r1, =heart_off
ldr r0, [r1]
ldr r1, =game_state
str r0, [r1]
mov r0, 0xfff
pi_2:
cmp r0, 0
beq exit_pi_2
bl print_game
sub r0, 1
b pi_2
exit_pi_2:
@ set the game state to intended initial gamestate
ldr r1, =reset_game_state
ldr r0, [r1]
ldr r2, =game_state
str r0, [r2]
mov r4, 4 @ Direction for ball between 0 and 5 inclusive
mov r5, 6 @ Position for ball between 0 and 24 inclusive
mov r6, 2 @ Direction for paddle between 0 and 1 inclusive
mov r7, 1 @ Position for paddle between 0 and 4 inclusive
@ note: that the position of the paddle is of the left pixel
@ so the other part of the paddle will always be one
@ to the right.
push {r4-r7} @ Store values
Game loop
play_game:
mov r0, 0x2000 @ good pause amount
pause_g: @pause and print the game
cmp r0, 0
beq exit_g
bl print_game
sub r0, 1
b pause_g
exit_g:
bl step_game @ step the entire game
@ checks if game hase been lost, if it has restart
cmp r5, 4
ble game_start
@ else:
b play_game
Update the game state
step_game:
@ steps the entire game to its next logical state
pop {r4-r7} @ get position and direction values
push {lr}
step_ball:
@ Move ball according to the direction register
.type move_ball, %function
@ args:
@ r4: direction of ball
@ r5: position of ball
@ r6: direction of paddle
@ r7: position of paddle
move_ball:
bl check_game
cmp r4, 0
beq move_up_left
cmp r4, 1
beq move_up
cmp r4, 2
beq move_up_right
cmp r4, 3
beq move_down_left
cmp r4, 4
beq move_down
cmp r4, 5
beq move_down_right
move_up_left:
mov r3, 6
b change_gamestate_b
move_up:
mov r3, 5
b change_gamestate_b
move_up_right:
mov r3, 4
b change_gamestate_b
move_down_left:
mov r3, -4
b change_gamestate_b
move_down:
mov r3, -5
b change_gamestate_b
move_down_right:
mov r3, -6
b change_gamestate_b
.type change_gamestate_b, %function
@ args:
@ r3: how much to change ball position by
change_gamestate_b:
ldr r1, =game_state
ldr r2, [r1]
push {r1}
@ make a variable to remove position of last ball
mov r0, 0b1
mov r1, 24
sub r1, r5
lsl r0, r1
eor r2, r0 @ remove last position of ball in game state
add r5, r3 @ changes the position of the ball
@ add new position of ball to game state
mov r0, 0b1
mov r1, 24
sub r1, r5
lsl r0, r1
orr r2, r0
pop {r1}
str r2, [r1] @ store the game back into memory
Update the paddle
step_paddle:
@ If paddle can move:
@ move paddle
@ Else:
@ step timer
cmp r6, 0
beq move_left_p
cmp r6, 1
beq move_right_p
cmp r6, 2
beq no_move_p
move_left_p:
ldr r1, =game_state
ldr r2, [r1]
push {r1}
@ makes a copy of r7 to alter
mov r3, r7
sub r3, 1
@ removes the right side of the paddle from game state
mov r0, 0b1
mov r1, 24
sub r1, r3
lsl r0, r1
eor r2, r0
@ adds pixel to the left
sub r1, 2
mov r0, 0b1
lsl r0, r1
orr r2, r0
add r7, 1 @ changes location of the paddle
pop {r1}
str r2, [r1]
pop {lr}
push {r4-r7}
bx lr
move_right_p:
ldr r1, =game_state
ldr r2, [r1]
push {r1}
@ makes a copy of r7 to alter
mov r3, r7
@ removes the left side of the paddle from game state
mov r0, 0b1
mov r1, 24
sub r1, r3
lsl r0, r1
eor r2, r0
@ adds pixel to the right
add r1, 2
mov r0, 0b1
lsl r0, r1
orr r2, r0
sub r7, 1 @ changes location of the paddle
pop {r1}
str r2, [r1] @ store result back
pop {lr}
push {r4 - r7}
bx lr
no_move_p:
pop {lr}
push {r4-r7}
bx lr
Handle the ball rebounding off wall/paddle
Rebounding off the walls
check_game:
@ checks if ball is on bound or paddle and changes direction accordingly
.type check_ball, %function
@ args:
@ r5: position of ball
@ returns:
@ r4: adjested direction
check_ball:
@ Checks if the ball is on any bound
@ Checks if ball is in top corner
cmp r5, 20
beq corner_rebound
cmp r5, 24
beq corner_rebound
@ Checks if ball on roof
cmp r5, 20
bgt roof_rebound
push {lr}
@ Checks if ball is on right wall
cmp r5, 5
beq right_wall_rebound
cmp r5, 10
beq right_wall_rebound
cmp r5, 15
beq right_wall_rebound
@ Checks if ball is on left wall
cmp r5, 9
beq left_wall_rebound
cmp r5, 14
beq left_wall_rebound
cmp r5, 19
beq left_wall_rebound
@ if not on the edge, check if ball is on paddle
b check_paddle
corner_rebound:
push {lr}
bl random_number @ Generate random number
pop {lr}
@ See if random number is odd
mov r1, 0b1
tst r0, r1
bne set_down
b set_opp
set_down:
@ set direction of ball to down
mov r4, 0x4
b check_paddle_pos @ returns to step ball
set_opp:
@ if direction up right, set direction down left
cmp r4, 2
beq set_down_left
@ else set the direction to down right
mov r4, 5
b check_paddle_pos @ returns to step ball
set_down_left:
mov r4, 3
b check_paddle_pos @ returns to step ball
roof_rebound:
add r4, 3 @ changes direction of ball to the downwards (in same direction)
b check_paddle_pos @ returns to step ball
left_wall_rebound:
@ makes sure when rebounding off wall it flips with direction
pop {lr} @ needs to pop this as was not used (so later on can recall to main thred)
cmp r4, 3
blt lw_rebound_up @ sees if the ball is going up or down
@ if it is going down, set to down rebound
cmp r4, 4
beq check_paddle_pos @ if ball going down directly, don't rebound
mov r4, 5
b check_paddle_pos
@ else set to up rebound
lw_rebound_up:
cmp r4, 1
beq check_paddle_pos @ if ball going up directly, don't rebound
mov r4, 2
b check_paddle_pos
right_wall_rebound:
@ makes sure when rebounding off wall it flips with direction
pop {lr} @ needs to pop this as was not used (so later on can recall to main thred)
cmp r4, 3
blt rw_rebound_up @ sees if the ball is going up or down
@ if it is going down, set to down rebound
cmp r4, 4
beq check_paddle_pos @ if ball going down directly, don't rebound
mov r4, 3
b check_paddle_pos
@ else set to up rebound
rw_rebound_up:
cmp r4, 1
beq check_paddle_pos @ if ball going up directly, don't rebound
mov r4, 0
b check_paddle_pos
Rebounding off the paddle
check_paddle:
@ Checks if the ball is on the paddle
@ If it is:
@ go direction according to which pixel the ball hits on the paddle and if the paddle is moving
mov r1, r7 @ coppies pos of paddle to scratch register
add r1, 4 @ changing value of r1 to compair it to pssilble row
cmp r1, r5 @ checks if ball is on paddle, left side
IT eq
bleq paddle_rebound
add r1, 1
cmp r1, r5 @ checks if ball is on paddle, right side
IT eq
bleq paddle_rebound
bl check_paddle_pos
pop {lr} @ return to step ball
bx lr
paddle_rebound:
@ ball rebound from paddle
@ changes direction of ball to something random
push {lr}
bl random_number @ Generate random number
pop {lr}
@ See if random number is odd
mov r1, 0b1
tst r0, r1
bne set_up_p @ change the direction of the ball to directly up
b set_away_p @ set the direction of the ball to logically opposite
set_up_p:
mov r4, 1
bx lr
set_away_p:
@ checks if ball is heading down
cmp r4, 4
beq mix_dir @ if it is make sure it doesn't head straight up
sub r4, 3 @ else make it go opposite direction
bx lr
mix_dir:
@ set ball going left
mov r4, 0
bx lr
Paddle AI
check_paddle_pos:
push {lr}
bl ai_dir
@ checks if paddle will try and go into the right wall
cmp r7, 1
IT eq
bleq check_paddle_dir_right
@ checks if paddle will try and go into the left wall
cmp r7, 4
IT eq
bleq check_paddle_dir_left
pop {lr}
bx lr
check_paddle_dir_right:
cmp r6, 1
IT ne
bxne lr @ return if it is not
@ else set direction to left
mov r6, 0
bx lr
check_paddle_dir_left:
cmp r6, 0
IT ne
bxne lr @ returns if not trying to go into wall
@ else set direction to right
mov r6, 1
bx lr
ai_dir:
@ change direction based on random number gen
push {lr}
bl random_number
pop {lr}
mov r1, 0b1
tst r0, r1
bne change_paddle_left
mov r6, 1 @ change paddle direction right (ev)
bx lr
change_paddle_left:
mov r6, 0 @ change paddle direction left
bx lr
Random Number Generator
.type random_number, %function
@ returns:
@ r0: randomly generated number
random_number:
ldr r1, =0x4000D000 @ Base address to RNG
mov r0, 0b1
str r0, [r1] @ starts random number genorator
mov r0, 0xffff
pause_r:
cmp r0, 0
beq exit_r
sub r0, 1
b pause_r
exit_r:
@ stops rRNG
mov r0, 0b1
str r0, [r1, 0x4]
ldr r0, [r1, 0x508] @ stores result of RNG to output
bx lr
Static Variables
.data
game_state:
.word 0b1100001000000000000000000
reset_game_state:
.word 0b1100001000000000000000000
heart_on:
.word 0b0010001110111111111101010
heart_off:
.word 0b0010001010100011010101010

