;  No Copyright
;
;  The person who associated a work with this deed has dedicated the work to the
;  public domain by waiving all of his or her rights to the work worldwide under
;  copyright law, including all related and neighboring rights, to the extent
;  allowed by law.
;
;  You can copy, modify, distribute and perform the work, even for commercial
;  purposes, all without asking permission.
;
;  See https://creativecommons.org/share-your-work/public-domain/cc0/ for more
;  information on the license.


;  This file is part of the Hardware tetris unit, made by
;  Jeroen Domburg <jeroen@spritesmods.com> and Arjen Meek.
;
;  More info on the project:
;  https://www.geekabit.nl/projects/some-gifts-for-me/#hardware-tetris-unit


.device ATTiny2313

;includes
;.include "attiny.inc"

.equ RAMSTART	=	(RAMEND-127)

.def dat	=	R0
.def temp	=	R16 	;The temp register
.def temp2	=	R17 	;Second temp register
.def temp3	=	r18
.def xpos	=	r19
.def ypos	=	r20
.def blokx	=	r21
.def bloky	=	r22
.def bloktr	=	r23 ;bit 543: type, 10: rotation
.def blokdh	=	r24
.def blokdl	=	r25
.def xlo	=	r26
.def fix	=	r27
.def ylo	=	r28
.def temp4	=	r29
.def Zlo	=	r30 ;Block pointer
.def Zhi	=	r31

.def txpos	=	r19
.def szlo	=	r28
.def szhi	=	r29

;De echte code
	.cseg			; switch to Code Segment
	.org	0		
	rjmp start		; reset vector
	nop			; External Int 0 not enabled
	nop			; External Int 1 not enabled
	nop			; Timer 1 Capture Int not enabled
	rjmp down			; Timer 1 Compare match A Int
	nop			; Timer 1 Overflow Int not enabled
	nop			; Timer 0 Overflow Int not enabled
	rjmp recv			; UART ReceiveInt
	nop			; UART Date Reg Empty Int not enabled
	nop			; UART tx'ed Int Not enabled
	reti			; Anacomp interrupt Not enabled

start:
	ldi temp,RAMEND		; top of memory
	out SPL,temp		; init stack pointer

	ldi temp,0b010011000
	out ucr,temp
	ldi temp,13
	out ubrr,temp
	ldi temp,0b0011
	out portd,temp
	ldi temp,0b001
	out tccr0,temp
	ldi temp,0
	out tccr1a,temp
	ldi temp,0b01101 ;/1024
	out tccr1b,temp
	ldi temp,high(10000)
	out ocr1ah,temp
	ldi temp,low(10000)
	out ocr1al,temp
	ldi temp,0b01000000
	out timsk,temp


	ldi temp,27
	rcall send
	ldi temp,'['
	rcall send
	ldi temp,'2'
	rcall send
	ldi temp,'J'
	rcall send


	in temp,udr ;flush
	cli
	rjmp dointro
introret:

	ldi temp,27
	rcall send
	ldi temp,'['
	rcall send
	ldi temp,'2'
	rcall send
	ldi temp,'J'
	rcall send

	ldi blokx,5
	ldi bloky,20
	ldi bloktr,0xc
	ldi fix,0
	rcall tr2z

	ldi ylo,ramstart
	ldi temp,0
wisret:
	st Y+,temp
	cpi ylo,ramstart+(20*2)
	brne wisret
	ldi temp,255
	st Y+,temp
	st Y+,temp

	sei
zzz:
	sei
	rjmp zzz

;Converteert een bloktr waarde naar een adres in z
tr2z:
	ldi zlo,low(blokken*2)
	ldi zhi,high(blokken*2)
	mov temp,bloktr
	lsl temp
	lsl temp
	add zlo,temp
	ldi temp,0
	adc zhi,temp
	ret
	
;Checkt of er een collision is; temp=0 -> niet, temp=1 -> wel
incoll:
	;Onder het veld uit-check
	sbrc bloky,7
	 rjmp coll

	ldi ylo,ramstart
	ldi ypos,4
	ldi temp,20
	sub temp,bloky
	add ylo,temp
	add ylo,temp
	rcall tr2z
nextcheck:
	lpm
	adiw zlo,1

	mov blokdl,dat
	ldi blokdh,0
	mov temp,blokx
	subi temp,-6
cbsh:
	clc
	mov temp2,blokdh
	lsl blokdl
	rol blokdh
	dec temp	
	brne cbsh
	sbrc temp2,7
	 rjmp coll

	mov temp,blokdl
	andi temp,0b00111111
	cpi temp,0
	brne coll
	
	ld temp2,Y+
	ld temp3,Y+
	and temp2,blokdl
	and temp3,blokdh
	or temp2,temp3
	cpi temp2,0
	brne coll

	dec ypos
	brne nextcheck
	
	ldi temp,0
	ret

coll:
	ldi temp,1
	ret


;Snacks up the filled lines
eatfull:
	ldi xlo,ramstart+(2*19)
	ldi ylo,ramstart+(2*19)
eatnext:
	ld temp2,Y+
	ld temp3,Y+
	subi ylo,2
	st X+,temp2
	st X+,temp3
	subi xlo,2

	ori temp2,0b00111111
	and temp2,temp3
	cpi temp2,$ff
	breq overwritethis
	subi xlo,2
overwritethis:
	subi ylo,2

	cpi ylo,ramstart
	brne eatnext

	ret



;Output grid + blocks op seriele dinges
dispgrid:

	;vt100 home
	ldi temp,27
	rcall send
	ldi temp,'['
	rcall send
	ldi temp,'H'
	rcall send


	ldi ylo,ramstart
	ldi ypos,20
	rcall tr2z

nextcol:
	ldi temp,'|'
	rcall send
	ldi xpos,10
	ld temp2,Y+
	ld temp3,Y+

	ldi blokdh,0
	ldi blokdl,0

	;Moeten we het movable blok displayen?
	mov temp,bloky
	sub temp,ypos
	lsr temp
	lsr temp
	cpi temp,0
	brne nextrow
	lpm
	adiw zlo,1
	mov blokdl,dat
	mov temp,blokx
	subi temp,-6
bsh:
;	clc
	lsl blokdl
	rol blokdh
	dec temp	
;	cpi temp,0
	brne bsh		
	or temp2,blokdl
	or temp3,blokdh
	cpi fix,0
	breq nextrow
	subi ylo,2
	st Y+,temp2
	st Y+,temp3

nextrow:
	ldi temp,' '
	sbrc temp3,7
	 ldi temp,'['
	rcall send
	ldi temp,' '
	sbrc temp3,7
	 ldi temp,']'
	rcall send

	clc
	rol temp2
	rol temp3
	dec xpos
	brne nextrow
	ldi temp,'|'
	rcall send
	ldi temp,13
	rcall send
	ldi temp,10
	rcall send
	
	dec ypos
	brne nextcol

	ret

; Send a byte and wait till buffer is empty again (idlewait)
send:
	out udr,temp
wsent:
	sbis usr,5
	 rjmp wsent
	ret

; Receive interrupt
recv:
	push temp
	in temp,sreg
	push temp

	in temp,udr
;	rcall send
	cpi temp,'j'
	brne nietl
	push temp
	inc blokx
	rcall incoll
	cpi temp,0
	breq nietla
	dec blokx
nietla:
	pop temp
nietl:
	cpi temp,'l'
	brne nietr
	push temp
	dec blokx
	rcall incoll
	cpi temp,0
	breq nietra
	inc blokx
nietra:
	pop temp
nietr:
	cpi temp,'k'
	brne nietk
	push temp
donextk:
	dec bloky
	rcall incoll
	cpi temp,0
	breq donextk
	inc bloky
	ldi fix,1
	rcall dispgrid
	rcall eatfull
	ldi fix,0
	rcall nextblock
nietka:
	pop temp
nietk:
	cpi temp,'i'
	brne nieti
	push temp
	mov temp2,bloktr
	inc bloktr
	mov temp,bloktr
	andi temp,3
	cpi temp,0
	brne nadd
	subi bloktr,4
nadd:
	push temp2
	rcall incoll
	pop temp2
	cpi temp,0
	breq nietia
	mov bloktr,temp2
nietia:
	pop temp
nieti:
	rcall dispgrid

	pop temp
	out sreg,temp
	pop temp
	reti

;Picks the next block
nextblock:
	ldi blokx,5
	ldi bloky,20
	in temp,tcnt0
	andi temp,$7f

	ldi bloktr,0b0000
	cpi temp,19
	brlo endblock

	ldi bloktr,0b0100
	cpi temp,38
	brlo endblock

	ldi bloktr,0b1000
	cpi temp,57
	brlo endblock

	ldi bloktr,0b1100
	cpi temp,73
	brlo endblock

	ldi bloktr,0b10000
	cpi temp,92
	brlo endblock

	ldi bloktr,0b10100
	cpi temp,111
	brlo endblock

	ldi bloktr,0b11000
endblock:
	push temp2
	push temp3
	in temp2,ocr1ah
	in temp3,ocr1al
	ldi temp,0xff
	add temp3,temp
	ldi temp,0xff-10
	adc temp2,temp
	out ocr1ah,temp2
	out ocr1al,temp3

	pop temp3
	pop temp2


	rcall incoll
	cpi temp,0
	brne gameover
	ret

gameover:
	ldi zhi,high(gameovert*2)
	ldi zlo,low(gameovert*2)
	ldi temp,0
doprint:
	lpm
	cp dat,temp
	breq quit
	out udr,dat
	rcall wsent	
	adiw zlo,1
	rjmp doprint

quit:
	cli
	sbis usr,7
	 rjmp quit
	in temp,udr
	cpi temp,' '
	brne quit
	rjmp 0

;Timer1 int
down:	
	push temp
	in temp,sreg
	push temp

	dec bloky
	rcall incoll
	cpi temp,0
	breq nietfix
	inc bloky
	ldi fix,1
	rcall dispgrid
	rcall eatfull
	ldi fix,0
	rcall nextblock

nietfix:
	rcall dispgrid
	pop temp
	out sreg,temp
	pop temp

	reti



wait100:
	ldi temp,0
	out tcnt1h,temp
	out tcnt1l,temp
waiting100:
	in temp,tcnt1l
	in temp,tcnt1h
	cpi temp,4
	brlo waiting100
	ret




dointro:

scrollret:
	rcall wait100

	ldi temp,27
	rcall send
	ldi temp,'['
	rcall send
	ldi temp,'H'
	rcall send
	ldi ZLo,low(scroller*2)
	ldi ZHi,high(scroller*2)
	ldi temp,0
	add zlo,txpos
	adc zhi,temp
	ldi temp,30
scrolldisp:
	lpm
	out udr,dat
	rcall wsent
	ldi temp2,1
	add zlo,temp2
	ldi temp2,0
	adc zhi,temp2
	dec temp
	brne scrolldisp
	ldi temp,0
	cp temp,dat
	breq wrap
	inc txpos
	rjmp txend
wrap:
	ldi txpos,0
txend:


	ldi zhi,high(statictxt*2)
	ldi zlo,low(statictxt*2)
	ldi temp,0
doprinta:
	lpm
	cp dat,temp
	breq quits
	out udr,dat
	rcall wsent	
	adiw zlo,1
	rjmp doprinta
quits:
	sbic usr,7
	 rjmp introret

	rjmp scrollret

blokken:
block1:
	.db 0b11,0b11
	.db 0b00,0b00
	.db 0b11,0b11
	.db 0b00,0b00
	.db 0b11,0b11
	.db 0b00,0b00
	.db 0b11,0b11
	.db 0b00,0b00
block2:
	.db 0b110,0b011
	.db 0b000,0b000
	.db 0b010,0b110
	.db 0b100,0b000
	.db 0b110,0b011
	.db 0b000,0b000
	.db 0b010,0b110
	.db 0b100,0b000
block3:
	.db 0b011,0b110
	.db 0b000,0b000
	.db 0b100,0b110
	.db 0b010,0b000
	.db 0b011,0b110
	.db 0b000,0b000
	.db 0b100,0b110
	.db 0b010,0b000
block4:
	.db 0b010,0b111
	.db 0b000,0b000
	.db 0b100,0b110
	.db 0b100,0b000
	.db 0b111,0b010
	.db 0b000,0b000
	.db 0b010,0b110
	.db 0b010,0b000
block5:
	.db 0b0000,0b1111
	.db 0b0000,0b0000
	.db 0b0100,0b0100
	.db 0b0100,0b0100
	.db 0b0000,0b1111
	.db 0b0000,0b0000
	.db 0b0100,0b0100
	.db 0b0100,0b0100


block6:
	.db 0b000,0b111
	.db 0b100,0b000
	.db 0b110,0b010
	.db 0b010,0b000
	.db 0b000,0b001
	.db 0b111,0b000
	.db 0b010,0b010
	.db 0b011,0b000

block7:
	.db 0b000,0b111
	.db 0b001,0b000
	.db 0b010,0b010
	.db 0b110,0b000
	.db 0b000,0b100
	.db 0b111,0b000
	.db 0b011,0b010
	.db 0b010,0b000


gameovert:
	.db 27,'[','H',13,10,13,10,13,10,13,10,13,10,"                        ",13,10,"  --- Game  Over ---    ",13,10,"                        ",13,10,0

scroller:
	.db "        "
	.db "                     Heej Maarten! Gefeliciteerd met je "
	.db "24ste verjaardag! Als aandenken aan deze memorabele "
	.db "gebeurtenis (jahaa) heb je hier een hardwarematige T"
	.db "etris-unit. ArjenM en JeroenD.                      "
	.db "        ",0

statictxt:
	.db 13,10,13,10,13,10,"Press any key to start.",13,10,"j - left",13,10,"k - down",13,10,"l - right",13,10,"i - rotate",0


; end of file
