2023-01-10 19:55:27 +00:00
|
|
|
; Mato8
|
|
|
|
; By nortti, 2023
|
|
|
|
; Snake game for CHIP-8
|
|
|
|
; Under Creative Commons Zero 1.0
|
|
|
|
; Assemble with c8asm (https://github.com/wernsey/chip8)
|
|
|
|
|
|
|
|
define frames_wait 4
|
|
|
|
|
|
|
|
define up_key 2
|
|
|
|
define down_key 8
|
|
|
|
define left_key 4
|
|
|
|
define right_key 6
|
|
|
|
|
2023-01-14 19:33:02 +00:00
|
|
|
define direction_up 0
|
|
|
|
define direction_down 6
|
|
|
|
define direction_left 12
|
|
|
|
define direction_right 18
|
|
|
|
|
2023-01-14 20:02:59 +00:00
|
|
|
define game_over_reg v7
|
|
|
|
define fruit_x_reg v8
|
|
|
|
define fruit_y_reg v9
|
|
|
|
define tail_x_reg va
|
|
|
|
define tail_y_reg vb
|
2023-01-14 19:33:02 +00:00
|
|
|
define head_direction_reg vc
|
2023-01-10 19:55:27 +00:00
|
|
|
define head_x_reg vd
|
|
|
|
define head_y_reg ve
|
|
|
|
|
|
|
|
start:
|
|
|
|
cls
|
|
|
|
ld game_over_reg, 0
|
|
|
|
|
|
|
|
rnd head_x_reg, 63
|
|
|
|
rnd head_y_reg, 31
|
|
|
|
|
2023-01-14 20:02:59 +00:00
|
|
|
ld tail_x_reg, head_x_reg
|
|
|
|
ld tail_y_reg, head_y_reg
|
|
|
|
|
2023-01-14 19:33:02 +00:00
|
|
|
ld head_direction_reg, direction_right
|
2023-01-10 19:55:27 +00:00
|
|
|
|
|
|
|
ld i, single_pixel
|
|
|
|
drw head_x_reg, head_y_reg, 1
|
|
|
|
|
|
|
|
call spawn_fruit
|
|
|
|
|
|
|
|
mainloop:
|
|
|
|
ld v0, frames_wait
|
|
|
|
ld dt, v0
|
|
|
|
|
|
|
|
ld v0, up_key
|
|
|
|
sknp v0
|
2023-01-14 19:33:02 +00:00
|
|
|
call turn_up
|
2023-01-10 19:55:27 +00:00
|
|
|
|
|
|
|
ld v0, down_key
|
|
|
|
sknp v0
|
2023-01-14 19:33:02 +00:00
|
|
|
call turn_down
|
2023-01-10 19:55:27 +00:00
|
|
|
|
|
|
|
ld v0, left_key
|
|
|
|
sknp v0
|
2023-01-14 19:33:02 +00:00
|
|
|
call turn_left
|
2023-01-10 19:55:27 +00:00
|
|
|
|
|
|
|
ld v0, right_key
|
|
|
|
sknp v0
|
2023-01-14 19:33:02 +00:00
|
|
|
call turn_right
|
2023-01-10 19:55:27 +00:00
|
|
|
|
|
|
|
call move_snake
|
|
|
|
|
|
|
|
; Wait until the frame timer hits zero
|
|
|
|
mainloop_wait_loop:
|
|
|
|
ld v0, dt
|
|
|
|
se v0, 0
|
|
|
|
jp mainloop_wait_loop
|
|
|
|
|
|
|
|
sne game_over_reg, 0
|
|
|
|
jp mainloop
|
|
|
|
|
|
|
|
game_over:
|
|
|
|
ld v0, 20
|
|
|
|
ld st, v0
|
|
|
|
call wait
|
|
|
|
|
|
|
|
ld v0, 30
|
|
|
|
call wait
|
|
|
|
|
|
|
|
ld v0, 20
|
|
|
|
ld st, v0
|
|
|
|
call wait
|
|
|
|
|
|
|
|
ld v0, 30
|
|
|
|
call wait
|
|
|
|
|
|
|
|
ld v0, 20
|
|
|
|
ld st, v0
|
|
|
|
call wait
|
|
|
|
|
|
|
|
jp start
|
|
|
|
|
|
|
|
wait:
|
|
|
|
ld dt, v0
|
|
|
|
wait_loop:
|
|
|
|
ld v0, dt
|
|
|
|
se v0, 0
|
|
|
|
jp wait_loop
|
|
|
|
ret
|
|
|
|
|
|
|
|
spawn_fruit:
|
|
|
|
rnd fruit_x_reg, 63
|
|
|
|
rnd fruit_y_reg, 31
|
|
|
|
|
|
|
|
ld i, single_pixel
|
|
|
|
drw fruit_x_reg, fruit_y_reg, 1
|
|
|
|
; Did we spawn over the snake?
|
|
|
|
se vf, 0
|
|
|
|
jp spawn_fruit
|
|
|
|
|
|
|
|
ret
|
|
|
|
|
2023-01-14 19:33:02 +00:00
|
|
|
turn_up:
|
|
|
|
; Don't allow 180° turns (which would kill the snake instantly)
|
|
|
|
se head_direction_reg, direction_down
|
|
|
|
ld head_direction_reg, direction_up
|
2023-01-10 19:55:27 +00:00
|
|
|
ret
|
|
|
|
|
2023-01-14 19:33:02 +00:00
|
|
|
turn_down:
|
|
|
|
se head_direction_reg, direction_up
|
|
|
|
ld head_direction_reg, direction_down
|
2023-01-10 19:55:27 +00:00
|
|
|
ret
|
|
|
|
|
2023-01-14 19:33:02 +00:00
|
|
|
turn_left:
|
|
|
|
se head_direction_reg, direction_right
|
|
|
|
ld head_direction_reg, direction_left
|
2023-01-10 19:55:27 +00:00
|
|
|
ret
|
|
|
|
|
2023-01-14 19:33:02 +00:00
|
|
|
turn_right:
|
|
|
|
se head_direction_reg, direction_left
|
|
|
|
ld head_direction_reg, direction_right
|
2023-01-10 19:55:27 +00:00
|
|
|
ret
|
|
|
|
|
|
|
|
move_snake:
|
2023-01-14 20:02:59 +00:00
|
|
|
; Save the direction the snake is moving at head's location
|
|
|
|
ld v0, head_x_reg
|
|
|
|
ld v1, head_y_reg
|
|
|
|
call direction_table_index
|
2023-01-14 19:33:02 +00:00
|
|
|
ld v0, head_direction_reg
|
2023-01-14 20:02:59 +00:00
|
|
|
ld [i], v0
|
2023-01-14 19:33:02 +00:00
|
|
|
|
2023-01-14 20:02:59 +00:00
|
|
|
; Move the snake's head
|
|
|
|
call unpack_direction
|
2023-01-14 19:33:02 +00:00
|
|
|
add head_x_reg, v0
|
|
|
|
ld v0, 63
|
|
|
|
and head_x_reg, v0
|
|
|
|
add head_y_reg, v1
|
|
|
|
ld v0, 31
|
|
|
|
and head_y_reg, v0
|
2023-01-10 19:55:27 +00:00
|
|
|
|
2023-01-14 20:02:59 +00:00
|
|
|
; Draw head location and erase tail location
|
2023-01-10 19:55:27 +00:00
|
|
|
ld i, single_pixel
|
|
|
|
drw head_x_reg, head_y_reg, 1
|
|
|
|
se vf, 0
|
|
|
|
call collision
|
2023-01-14 20:02:59 +00:00
|
|
|
drw tail_x_reg, tail_y_reg, 1
|
|
|
|
|
|
|
|
; Load the direction the snake was moving at tail's location
|
|
|
|
ld v0, tail_x_reg
|
|
|
|
ld v1, tail_y_reg
|
|
|
|
call direction_table_index
|
|
|
|
ld v0, [i]
|
|
|
|
|
|
|
|
; Move the snake's tail
|
|
|
|
call unpack_direction
|
|
|
|
add tail_x_reg, v0
|
|
|
|
ld v0, 63
|
|
|
|
and tail_x_reg, v0
|
|
|
|
add tail_y_reg, v1
|
|
|
|
ld v0, 31
|
|
|
|
and tail_y_reg, v0
|
|
|
|
|
|
|
|
ret
|
2023-01-10 19:55:27 +00:00
|
|
|
|
2023-01-14 20:02:59 +00:00
|
|
|
direction_table_index:
|
|
|
|
; v0 is the X coördinate, from 0 to 63, 00xxxxxx
|
|
|
|
; v1 is the Y coördinate, from 0 to 31, 000yyyyy
|
|
|
|
shl v0, v0
|
|
|
|
shl v0, v0
|
|
|
|
; v0 is the X coördinate shifted left by two, xxxxxx00
|
|
|
|
ld v2, %11100000
|
|
|
|
and v2, v0
|
|
|
|
or v1, v2
|
|
|
|
; v1 is combination of high 3 bits of X coördinate and the Y coördinate, xxxyyyyy
|
|
|
|
ld v2, %00011100
|
|
|
|
and v0, v2
|
|
|
|
; v0 is the low 3 bits of the X coördinate shifted left by two, 000xxx00
|
|
|
|
|
|
|
|
jp v0, direction_table_index_table
|
|
|
|
direction_table_index_table:
|
|
|
|
; 0
|
|
|
|
ld i, #400
|
|
|
|
jp direction_table_index_end
|
|
|
|
|
|
|
|
; 1
|
|
|
|
ld i, #500
|
|
|
|
jp direction_table_index_end
|
|
|
|
|
|
|
|
; 2
|
|
|
|
ld i, #600
|
|
|
|
jp direction_table_index_end
|
|
|
|
|
|
|
|
; 3
|
|
|
|
ld i, #700
|
|
|
|
jp direction_table_index_end
|
|
|
|
|
|
|
|
; 4
|
|
|
|
ld i, #800
|
|
|
|
jp direction_table_index_end
|
|
|
|
|
|
|
|
; 5
|
|
|
|
ld i, #900
|
|
|
|
jp direction_table_index_end
|
|
|
|
|
|
|
|
; 6
|
|
|
|
ld i, #a00
|
|
|
|
jp direction_table_index_end
|
|
|
|
|
|
|
|
; 7
|
|
|
|
ld i, #b00
|
|
|
|
|
|
|
|
direction_table_index_end:
|
|
|
|
add i, v1
|
2023-01-10 19:55:27 +00:00
|
|
|
ret
|
|
|
|
|
2023-01-14 19:33:02 +00:00
|
|
|
unpack_direction:
|
|
|
|
jp v0, unpack_direction_table
|
|
|
|
unpack_direction_table:
|
|
|
|
; Up
|
|
|
|
ld v0, 0
|
|
|
|
ld v1, #ff
|
|
|
|
ret
|
|
|
|
|
|
|
|
; Down
|
|
|
|
ld v0, 0
|
|
|
|
ld v1, 1
|
|
|
|
ret
|
|
|
|
|
|
|
|
; Left
|
|
|
|
ld v0, #ff
|
|
|
|
ld v1, 0
|
|
|
|
ret
|
|
|
|
|
|
|
|
; Right
|
|
|
|
ld v0, 1
|
|
|
|
ld v1, 0
|
|
|
|
ret
|
|
|
|
|
2023-01-10 19:55:27 +00:00
|
|
|
collision:
|
|
|
|
se head_x_reg, fruit_x_reg
|
|
|
|
jp tail_collision
|
|
|
|
se head_y_reg, fruit_y_reg
|
|
|
|
jp tail_collision
|
|
|
|
|
|
|
|
eat_fruit:
|
|
|
|
; TODO: Lenghten snake
|
2023-01-14 19:35:55 +00:00
|
|
|
ld v0, 1
|
|
|
|
ld st, v0
|
|
|
|
|
2023-01-10 19:55:27 +00:00
|
|
|
ld i, single_pixel
|
|
|
|
drw fruit_x_reg, fruit_y_reg, 1
|
|
|
|
jp spawn_fruit
|
|
|
|
|
|
|
|
tail_collision:
|
|
|
|
ld game_over_reg, 1
|
|
|
|
ret
|
|
|
|
|
|
|
|
single_pixel: db #80
|