###########################################
#
#  F8Z: a chip8/Octo tech demo
#
#  A/D move gomez left and right.
#  Q/E rotate the world around him.
#  Runs best at 100 cycles/frame.
#
###########################################

: letter-F 0x07 0x19 0x61 0x81 0x87 0x99 0x81 0x81 0x87 0x9E 0x98 0x90 0x90 0xF0 0xE0
: letter-8 0x0E 0x33 0x41 0x89 0x99 0x93 0x81 0xC1 0x89 0x99 0x91 0x83 0xCE 0x78 0x60 
: letter-Z 0x07 0x19 0x61 0x81 0x91 0xE1 0x43 0x86 0x89 0x81 0x81 0x87 0x9E 0xF8 0x60 

: cloud1 0x07 0x0F 0x7F 0xFF
: cloud2 0xC0 0xE0 0xFE 0xFF
: cloud3 0x30 0x7E 0xFF 

: pillar # (padded to 16 bytes/side)
	0x06 0x1B 0x65 0x8F 0xD5 0xBD 0xFB 0x7E 0x83 0xBB 0xBB 0xBB 0x83 0x7F 0xFD 0x00
	0x78 0xD6 0xFE 0xFD 0xBF 0xFF 0xFE 0xFF 0x83 0xAB 0xAB 0xBB 0x82 0xFF 0xBF 0x00
	0x60 0xB8 0xFE 0xFB 0x7B 0x7F 0xFF 0xDF 0x83 0xBA 0xA3 0xBB 0x83 0x7F 0xFD 0x00
	0x16 0xD9 0xA6 0xBB 0xFB 0xFF 0xDF 0xFE 0x82 0xBB 0xAB 0xAB 0x83 0x7F 0xF9 0x00

: floors # (padded to 8 bytes/tile)
	0xFE 0xFE 0xFE 0xE0 0xEF 0xEF 0xEF 0x00
	0xEF 0xEF 0xEF 0xE0 0xFE 0xFE 0xFE 0x00
	0xEF 0xEF 0xEF 0xE0 0xEE 0xEE 0xEE 0x00
	0xFE 0xFE 0xFE 0xE0 0xEE 0xEE 0xEE 0x00

: gomez # (padded to 16 bytes/frame)
	0x00 0x00 0x60 0xE0 0x7E 0xFF 0xBD 0xF7 0x7E 0x18 0x3C 0x5E 0x3C 0x3C 0x24 0x00 # facing right
	0x00 0x60 0x60 0xFE 0xFF 0xBD 0xF7 0x7E 0x18 0x3C 0x5E 0x3C 0x3C 0x48 0x00 0x00
	0x00 0x60 0x60 0xFE 0xFF 0xBD 0xF7 0x7E 0x18 0x7E 0x1C 0x3C 0x3C 0x24 0x00 0x00
	0x00 0x00 0x60 0xFE 0xFF 0xFF 0xBD 0x76 0x18 0x3C 0x5E 0x3C 0x3C 0x12 0x00 0x00
	0x00 0x00 0x06 0x07 0x7E 0xFF 0xBD 0xEF 0x7E 0x18 0x3C 0x7A 0x3C 0x3C 0x24 0x00 # facing left
	0x00 0x06 0x06 0x7F 0xFF 0xBD 0xEF 0x7E 0x18 0x3C 0x7A 0x3C 0x3C 0x12 0x00 0x00
	0x00 0x06 0x06 0x7F 0xFF 0xBD 0xEF 0x7E 0x18 0x7E 0x38 0x3C 0x3C 0x24 0x00 0x00
	0x00 0x00 0x06 0x7F 0xFF 0xFF 0xBD 0x6E 0x18 0x3C 0x7A 0x3C 0x3C 0x48 0x00 0x00

: pillar-pos
	46 10 16 46

: cloud-delta
	254 255 254 255 2 1 2 1

: sync
	v2 := 4
	delay := v2
	loop
		v2 := delay
		if v2 != 0 then
	again
;

: draw-objects
	v0 := 2
	v1 := vd
	v1 += 8
	v2 := 1
	i := gomez
	i += vc # animation frame
	i += v8 # direction facing
	sprite va vb 15

	# clouds
	i := cloud1
	sprite vd v0 4
	i := cloud2
	sprite v1 v0 4
	i := cloud3
	sprite ve v2 3

	# pillar
	i := pillar-pos # get x coord
	i += v5
	load v0
	v1 :=  9
	i := pillar
	v2 <<= v5 # add (rotation * 16)
	v2 <<= v2
	v2 <<= v2
	v2 <<= v2
	i += v2
	sprite v0 v1 15
;

: draw-background
	v0 := 0
	v1 := 25
	loop
		i  := floors
		v2 := random 0b11000
		i  += v2
		sprite v0 v1 7
		v0 += 8
		if v0 != 64 then
	again
;

###########################################
#
#  Wipe Effects
#
###########################################

: wipe-common
	v1 := 16
	buzzer := v1

	v1 := 0b11 # wrap rotation modulo 4
	v5 &= v1

	i := gomez
	loop
		i += v1

		v1 := 1
		sprite v0 v1 15
		v1 := 16
		sprite v0 v1 15

		sync

		v1 := 1
		sprite v0 v1 15
		v1 := 16
		sprite v0 v1 15
		v2 := v0

		v0 += v3
		v1 := 0b111111
		v2 := v0
		v2 &= v1
		if v2 != 0 then
	again
	clear
	draw-background
;

: wipe-left
	# rotate player's position
	v0 := va
	va := v7
	v7 := 64
	v7 -= v0

	v5 += -1
	v0 := 64
	v3 := -16
	jump wipe-common

: wipe-right
	# rotate player's position
	v0 := va
	va := v7
	v7 := 64
	v7 += v0

	v5 += 1
	v0 := 0
	v3 := 16
	jump wipe-common

###########################################
#
#  Movement and Animation
#
###########################################

: walk
	v9 += -1                 # count down anim timer
	vc += 16                 # advance frame
	v0 := 0b0110000
	vc &= v0
	if v8 == 0 then va +=  1 # move
	if v8 != 0 then va += -1
;

: face-left   v8 := 64 ;
: move-left   if v8 == 0 then jump face-left   v9 := 4 ;
: face-right  v8 :=  0 ;
: move-right  if v8 == 64 then jump face-right v9 := 4 ;

: move-player
	if v9 != 0 then jump walk
	v0 := 7
	if v0 key then jump move-left
	v0 := 9
	if v0 key then jump move-right
	v0 := 4
	if v0 key then jump wipe-left
	v0 := 6
	if v0 key then jump wipe-right
;

###########################################
#
#  Main Loop
#
###########################################

: main
	# title screen
	v0 := 15
	v1 := 13
	i := letter-F
	sprite v0 v1 15
	v0 += 12
	v1 += -5
	i := letter-8
	sprite v0 v1 15
	v0 += 12
	v1 += -5
	i := letter-Z
	sprite v0 v1 15
	v0 := 16
	loop
		sync
		v0 += -1
		if v0 != 0 then
	again
	clear

	# v0-v3 are used extensively as temporaries
	# v4 is still free

	v5 :=  0 # rotation index
	v6 :=  0 # real x
	v7 :=  0 # real y
	v8 :=  0 # 0 - right, 64 - left
	v9 :=  0 # moving?
	va := 10 # player x position
	vb := 10 # player y position
	vc :=  0 # player anim frame
	vd := 10 # big cloud x
	ve := 40 # small cloud x

	draw-background
	draw-objects
	loop
		draw-objects
		move-player

		i := cloud-delta
		i += v5
		i += v5
		load v1
		vd += v0
		ve += v1

		draw-objects
		sync
	again
