	.CR	SCMP
	.TF	Tetris_v21r.hex,int
;	.TF Tetris_v21r.BIN,bin
	.LF	Tetris_v21r.lst
	
; *****************************************************************************
; MK14 Tetris
; Rev Still in development
; Written by Ian Murray December 2023
; Loads into 0x0400 and 0x0B00
; Executes at 0x0400
; *****************************************************************************
	
;Game Constants
PROM			.EQ 0x0051
MK14_KEYS		.EQ 0x0185		;Address of keyboard and display routine in SCIOSv3
DISP_GR			.EQ 0x0200		;Start of VDU frame store for graphics
CLEAR_SCREEN	.EQ 0x0241		;Start Point for Clear Screan
CHECK_LINES		.EQ 0x0371		;Used to check completed lines
DISP_TEXT		.EQ 0x0350		;Display Text after load
DISP_SCO		.EQ 0x027C		;Display Score
DISP_LEV		.EQ 0x02DE		;Display Level
DISP_LIN		.EQ 0x033E		;Display Lines
DISP_NEXT_BOX	.EQ 0x037C		;Location of Next Box on Screen
DISP_TEST		.EQ 0x03E0		;Display Test
PROG1			.EQ 0x0400		;Start of program memory
PROG2			.EQ 0x0B00		;Extended RAM 256 bytes
PROG3			.EQ 0x0880		;I/O chip RAM 128 bytes

KEYBOARD		.EQ 0x0D00		;Keyboard Pointer

VAR_07E0		.EQ 0x07E0		;GAME OVER text
VAR_07F0		.EQ 0x07F0		;PRESS GO TO START text
VAR_0F00		.EQ 0x0F00		;Variables storage area
VAR_0F60		.EQ 0x0F60		;Object shape
VAR_0F70		.EQ 0x0F70		;Object Bit shape 1st Byte
VAR_0F90		.EQ 0x0F90		;Object Bit shape 2nd Byte
VAR_0FB0		.EQ 0x0FB0		;Chr to be used for Object
VAR_0FB7		.EQ 0x0FB7		;Scores for Single, Double etc
VAR_0FC0		.EQ 0x0FC0		;Random sequence 

;1 = True
;0 = False

	.OR VAR_0F00			;  Variables

True_1		.EQ 0x20		;Set to True 1
False_0		.EQ 0x21		;Set to False 0
OBJ_P		.EQ 0x22		;Used to point to object at 0F60
OBJ_COL		.EQ 0x23
OBJ_ROW		.EQ 0x24
OBJ_H		.EQ 0x25
OBJ_L		.EQ 0x26
OBJ_OH		.EQ 0x27		;Used to store original H location of object
OBJ_OL		.EQ 0x28		;Used to store original H location of object
OBJ_NUM_OLD	.EQ 0x29
OBJ_NUM		.EQ 0x2A
OBJ_NUM_NEXT	.EQ 0x2B
OBJ_BYTE	.EQ 0x2C
NOT_USED	.EQ 0x2D		;Used to confirm move possible
OBJ_1_BYTE	.EQ 0x2E
OBJ_2_BYTE	.EQ 0x2F
OBJ_NUMBER	.EQ 0x30
OBJ_DELETE	.EQ 0x31
OBJ_CHR		.EQ 0x32
OBJ_ORIENT	.EQ 0x33		;0 Up, 1 Right, 2 Down, 3 Left
OBJ_WIDTH	.EQ 0x34
KEYPRESS	.EQ 0x35
KEY_PRESSED	.EQ 0x36
X_MOVE		.EQ 0x37
SCORE_H		.EQ 0x38
SCORE_T		.EQ 0x39
SCORE_U		.EQ 0x3A
SCORE		.EQ 0x3B
SCORE_SUB	.EQ 0x3C
OBJ_NEXT	.EQ 0x3D
LINE_COMP	.EQ 0x3E		;True (1) or False (0) Line Complete
LINE_COMP_H	.EQ 0x3F		;Number of lines complete High Byte
LINE_COMP_L	.EQ 0x40		;Number of lines complete Low Byte
LINE_COMP_SUB		.EQ 0x41
MOVE_COUNT			.EQ 0x42
LINES_DELETED		.EQ 0x43
LINES_DELETED_TEMP	.EQ 0x44
TEMP_1		.EQ 0x45
TEMP_X		.EQ 0x46		; General purpose counter
TEMP_Y		.EQ 0x47
TEMP_Z		.EQ 0x48
DELAY_LEVEL	.EQ 0x49
DELAY_LOOP	.EQ 0x4A
LEVEL		.EQ 0x4B
MOVE_OK		.EQ 0x4C		;Used to confirm move possible
RND			.EQ 0x4D		;Random number to select next object
SPACE_CHR	.EQ 0x4E		;0x20 for next 0x00 for play area
KEY_COUNT	.EQ 0x4F
CHAR		.EQ 0x50
ROW			.EQ 0x51
CNT			.EQ 0x52
PUSHED		.EQ 0x53


	.OR VAR_0F00
	.HS 006D3031787B7800

	.OR VAR_07E0
	.HS 07010D05200F16051220202020202010		;Game Over
	.HS 12051313070F20140F13140112142000		;PRESS GO TO START
	.OR VAR_0F60
	.HS 2E2E2E2E2E2E2E2E2E2E2E2E2E2E2E2E		;Object Shape Store
	
	.OR VAR_0F70
	;   Byte codes for each object shape
	.HS 603010707030F0FF
	.HS 10203030203011FF
	.HS 000000002030F0FF
	.HS 10202010103011FF
		
	.HS 03060701020300FF
	.HS 23131122230311FF
	.HS 36634774070300FF
	.HS 23133231130311FF
		
	.OR VAR_0FB0
	.HS 0224111518191A08					;Chr used for objects
	;.OR VAR_0FB8
	.HS 4000000000010312					;Scores for level 0
	
	.OR VAR_0FC0
	.HS 00010203040506030602000405010501
	.HS 03020400060301060004050200020103
	.HS 05040605010301040006060105040302
	.HS 0000
	
	.OR DISP_GR
	.HS 200D0B31342014051412091320163120	; MK14 TETRIS V1
	.HS 20202020202020202020202020202020	
	.HS 20202020202020202020202020202020	
	.HS 63232323232323232323232323232323	;################
	.HS 23202020202020202020202320202020	;#          #
	.HS 23202020200D0F16052020232013030F	;#    Move  # SCO
	.HS 23202020202020202020202320202020	;#          #
	.HS 2320323D040F170E2020202320202020	;# 2=DOWN   #
	.HS 23202020202020202020202320202020	;#          #
	.HS 2320343D0C0506142020202320202020	;# 4=LEFT   #####
	.HS 23202020202020202020202323232323	;#          #
	.HS 2320363D120907081420202320202020	;# 6=RIGHT  # LEV
	.HS 232020202020202020202023200C0516	;#          #
	.HS 23202020202020202020202320202020	;#          #
	.HS 23202020120F14011405202320202020	;#   ROTATE #
	.HS 23202020202020202020202320202020	;#          #
	.HS 2320033D120907081420202323232323	;# C=RIGHT  #####
	.HS 23202020202020202020202320202020	;#          #
	.HS 2320043D0C05061420202023200C090E	;# D=LEFT   # LIN
	.HS 23202020202020202020202320202020	;#          #
	.HS 23202020202020202020202320202020	;#          #
	.HS 23202020202020202020202320202020	;#          #
	.HS 23202020202020202020202323232323	;#          #####
	.HS 23202020202020202020202320202020	;#          #
	.HS 23202020202020202020202320202020	;#          #
	.HS 23202020202020202020202320202020	;#          #
	.HS 23202020202020202020202320202020	;#          #
	.HS 23232323232323232323232323232323	;################
	.HS 20202020202020202020202020202020
	.HS 20202020202020202020202020202020
	.HS 20202020202020202020202020202020
	.HS 20202020202020202020202020202020

	
	.OR PROG1
	
ENTRY:	
;===================================================================
;P2 is variables pointer 0F20
;===================================================================

	LDI VAR_0F00/256
	XPAH P2
	LDI VAR_0F00\256
	XPAL P2
	
;========================== Wait For GO Pressed =======================
NEW_GAME:

GET_KEY_1:
	CCL
	JS P3,MK14_KEYS
	NOP
	NOP
	XAE
	ST KEYPRESS(2)
	XRI 0x22						;Check for GO Key
	JNZ GET_KEY_1
	
;========================== Clear Screen ==============================
	JS P3,CLEAR_PLAY_AREA
;===================== Initialise variables ===========================
	LDI 0x01
	ST True_1(P2)
	ST MOVE_COUNT(P2)				;Required for new games to start
	LDI 0x00
	ST False_0(P2)
	
	ST KEY_PRESSED(P2)
	ST TEMP_1(P2)
	ST LINE_COMP_H(P2)
	ST LINE_COMP_L(P2)
	ST SCORE_H(P2)
	ST SCORE_T(P2)
	ST SCORE_U(P2)
	ST LEVEL(P2)

	LDI 0x0A
	ST DELAY_LEVEL(P2)				;New Game starting delay_level
	
	LDI VAR_0FC0/256
	XPAH P1
	LDI VAR_0FC0\256
	XPAL P1							;Set P1 to Random Object List
	
	LD RND(P2)
	ANI 0x1F
	ADI 0x07
	ST RND(P2)
	XAE
	LD -128(P1)
	ST OBJ_NUM_NEXT(P2)
	DLD RND(P2)
	XAE
	LD -128(P1)
	ST OBJ_NUMBER(P2)
	
	JS P3,DISPLAY_SCORES
;---------------------------------------------------------------------
NEXT_OBJECT:

	LDI DISP_NEXT_BOX/256
	XPAH P1
	LDI DISP_NEXT_BOX\256
	XPAL P1							;Set P1 to Next Box Location

	JS P3,UPDATE_OBJECT_NEXT
	JS P3,PLACE_OBJECT_NEXT
	
;-------------------------------------------------------------------
	LDI 0x02
	ST OBJ_H(P2)
	LDI 0x45
	ST OBJ_L(P2)					;Set starting postion of new object

	LD DELAY_LEVEL(P2)
	ST DELAY_LOOP(P2)
	
	LDI 0x00
	ST SCORE(P2)
	ST OBJ_ORIENT(P2)
	ST MOVE_COUNT(P2)
	ST LINE_COMP_SUB(P2)
	
	LDI 0x01
	ST SCORE_SUB(P2)
	
	LDI 0x10
	ST X_MOVE(P2)
	
	LD OBJ_NUMBER(P2)
	ST OBJ_NUM(P2)
	
	JS P3,UPDATE_OBJECT
	JS P3,PLACE_OBJECT

;----------------------------------------------------------------------
MOVE_MORE:
	JS P3,DELETE_OBJECT		;Delete and Place object use same function
	JS P3,UPDATE_OBJECT

;----------------------------------------------------------------------
CHECK_OBJECT_CAN_MOVE:
	LD True_1(P2)
	ST MOVE_OK(P2)					;Set Move OK to True 
	
	CCL
	LD OBJ_L(P2)
	ST OBJ_OL(P2)
	ADD X_MOVE(P2)
	ST OBJ_L(P2)
	LD OBJ_H(P2)
	ST OBJ_OH(P2)
	ADI 0x00
	ST OBJ_H(P2)
	
	LD OBJ_H(P2)
	XPAH P1
	LD OBJ_L(P2)  
	XPAL P1							;P1 now points top object location
	
	LDI 0x5F
	ST OBJ_P(P2)					;0x0F60 contains object
	
	LDI 0x04
	ST OBJ_ROW(P2)
	
NEXT_ROW_C:
	LDI 0x04
	ST OBJ_COL(P2)
	
NEXT_COL_C:
	ILD OBJ_P(P2)
	XAE
	LD -128(P2)
	JZ DO_NOT_STORE_C
	LD @1(P1)						; Check Location contains 0x20
	XRI 0x20
	JZ STORED_C
	LD False_0(P2)
	ST MOVE_OK(P2)
	JMP STORED_C
	
DO_NOT_STORE_C:
	LD @1(P1)
	
STORED_C:
	DLD OBJ_COL(P2)
	JNZ NEXT_COL_C
	
	LD @12(P1)
	DLD OBJ_ROW(P2)
	JNZ NEXT_ROW_C
	
	LD MOVE_OK(P2)
	JNZ OBJECT_MOVE_OK
	
	LD OBJ_OH(P2)
	ST OBJ_H(P2)
	LD OBJ_OL(P2)
	ST OBJ_L(P2)
	
	LD X_MOVE(P2)
	XRI 0x10
	JZ OBJECT_MOVE_OK
	LDI 0x10
	ST x_MOVE(P2)
	JMP CHECK_OBJECT_CAN_MOVE
	
;----------------------------------------------------------------------
OBJECT_MOVE_OK:
	JS P3,PLACE_OBJECT
	
	LD MOVE_OK(P2)
	JZ MOVE_NOT_OK				;Move not ok
	
	ILD MOVE_COUNT(P2)
	
	LDI 0x10
	ST X_MOVE(P2)				;Reset Move before checking key press
	
	LD False_0(P2)
	ST KEYPRESS(P2)				;Reset Keypress to False

;---------------------------------------------------------------------
	LD DELAY_LOOP(P2)
	ST TEMP_1(P2)

DELAY_TIMER:
	JS P3,GET_INPUT
	;JS P3,DISPLAY_TEST_INFO				;Only required for testing
	DLY 0x60							;80 for PiView 60 for other
	DLD TEMP_1(P2)
	JNZ DELAY_TIMER
	
;---------------------------------------------------------------------
	CCL							;Add Score to Sub Score
	LD SCORE_SUB(P2)
	DAD SCORE(P2)
	ST SCORE_SUB(P2)

	JS P3,MOVE_MORE				;To far to jump

MOVE_NOT_OK:
	JS P3,CHECK_COMPLETE_LINE
	
	LD LINES_DELETED(P2)
	ST LINES_DELETED_TEMP(P2)
	JZ NO_LINES_TO_DELETE
	
;---------------------------------------------------------------------
DELETE_LINES:
	LDI 0x03					;Set P1 & P3 ready for move
	XPAH P1						;P1 = 0x0390
	LDI 0x90
	XPAL P1
	
	LDI 0x03					;P3 = 0x03A0
	XPAH P3
	LDI 0xA0
	XPAL P3
	
	LDI 0x12					;Only check 18 lines for testing
	ST TEMP_Z(P2)
	
	DLD LINES_DELETED_TEMP(P2)

CHECK_NEXT_ROW:
	LD @0(P3)
	XRI 0xA3
	JZ CHECK_P1_ROW
	LD @-16(P3)
	LD @-16(P1)
	DLD TEMP_Z(P2)
	JNZ CHECK_NEXT_ROW
	JMP NO_LINES_TO_DELETE

CHECK_P1_ROW:
	LD @0(P1)
	XRI 0xA3
	JNZ LOOP_MOVE_ROW
	DLD TEMP_1(P2)
	LD @-16(P1)
	JMP CHECK_P1_ROW

LOOP_MOVE_ROW:
	LDI 0x0B
	ST TEMP_X(P2)
	
LOOP_MOVE:
	LD @1(P1)
	ST @1(P3)
	DLD TEMP_X(P2)
	JNZ LOOP_MOVE

	LD @-27(P3)
	LD @-27(P1)
	XRI 0x63					;Check for top of play area
	JNZ LOOP_MOVE_ROW
	
	LD LINES_DELETED_TEMP(P2)
	JNZ DELETE_LINES			;Check for more lines

;-----------------------------------------------------------------
NO_LINES_TO_DELETE:
	LD OBJ_NUM_NEXT(P2)
	ST OBJ_NUMBER(P2)

;-----------------------------------------------------------------
	LDI VAR_0FC0/256
	XPAH P1
	LDI VAR_0FC0\256
	XPAL P1						;Set P1 to Random Object List
	
	DLD RND(P2)					;RND counts down from 0x31 to zero
	JNZ DONT_RESET_RND
	LDI 0x31
	ST RND(P2)
	
DONT_RESET_RND:
	LD RND(P2)
	XAE
	LD -128(P1)
	ST OBJ_NUM_NEXT(P2)

;-----------------------------------------------------------------
UPDATE_SCORES:
	CCL
	LD SCORE_U(P2)
	DAD SCORE_SUB(P2)
	ST SCORE_U(P2)
	LD SCORE_T(P2)
	DAI 0x00
	ST SCORE_T(P2)
	LD SCORE_H(P2)
	DAI 0x00
	ST SCORE_H(P2)
	
	CCL
	LD LINE_COMP_L(P2)
	DAD LINE_COMP_SUB(P2)
	ST LINE_COMP_L(P2)
	LD LINE_COMP_H(P2)
	DAI 0x00
	ST LINE_COMP_H(P2)
	
	LD LINE_COMP_L(P2)
	ANI 0xF0
	RR
	RR
	RR
	RR
	ST LEVEL(P2)					;Change Delay based on Level
	
	CCL
	LDI 0x0A
	CAD LEVEL(P2)
	ST DELAY_LEVEL(P2)				;DELAY_LEVEL = 10 - LEVEL
	JP STILL_POSITIVE_DELAY
	LDI 0x00
	ST DELAY_LEVEL(P2)
	
STILL_POSITIVE_DELAY:

DISPLAY_SCORES:
	LDI DISP_SCO/256
	XPAH P1
	LDI DISP_SCO\256
	XPAL P1							;Set P1 to Score Location
	
	LD @0x02(P1)
	LD SCORE_H(P2)
	XAE
	JS P3,UPDATE_SCO_LEV_LIN
	
	LD @0x0C(P1)
	
	LD SCORE_T(P2)
	XAE
	JS P3,UPDATE_SCO_LEV_LIN
	
	LD SCORE_U(P2)
	XAE
	JS P3,UPDATE_SCO_LEV_LIN
	
;--------------------------------------------------------------------
	LD @0x5E(P1)					;Set P1 to Level Location
	LD LEVEL(P2)
	XAE
	JS P3,UPDATE_SCO_LEV_LIN

;--------------------------------------------------------------------
	LD @0x5C(P1)					;Set P1 to Line Location

	LD LINE_COMP_H(P2)
	XAE
	JS P3,UPDATE_SCO_LEV_LIN
	LD LINE_COMP_L(P2)
	XAE
	JS P3,UPDATE_SCO_LEV_LIN

;--------------------------------------------------------------------
	LD MOVE_COUNT(P2)
	JZ END
	JS P3,NEXT_OBJECT				;Jump to next object
;--------------------------------------------------------------------
END:
	JS P3,CLEAR_PLAY_AREA
	
	LDI VAR_07E0/256
	XPAH P1
	LDI VAR_07E0\256
	XPAL P1							;P1 points to text
	
	LDI 0x02
	XPAH P3
	LDI 0xC4
	XPAL P3							;P3 points Text Location on screen
	
	LDI 0x06
	ST TEMP_Y(P2)
	
SCREEN_TEXT_MOVE_ROW:
	LDI 0x05
	ST TEMP_X(P2)
	
SCREEN_TEXT_MOVE:
	LD @1(P1)
	ST @1(P3)
	DLD TEMP_X(P2)
	JNZ SCREEN_TEXT_MOVE
	
	LD @27(P3)
	DLD TEMP_Y(P2)
	JNZ SCREEN_TEXT_MOVE_ROW
	
	JS P3,NEW_GAME
;********************************************************************
;*************************** THE END ********************************
;********************************************************************

UPDATE_SCO_LEV_LIN

	XAE
	ST TEMP_1(P2)
	ANI 0xF0
	RR
	RR
	RR
	RR
	ORI 0x30
	ST @1(P1)
	LD TEMP_1(P2)
	ANI 0x0F
	ORI 0x30
	ST @1(P1)

UPDATE_SCO_LEV_LIN_RETURN:
	RET P3

;====================================================================
;====================================================================

CHECK_COMPLETE_LINE:				;CHECK LINES COMPLETED
	LDI 0x00
	ST LINES_DELETED(P2)
	
	LD OBJ_H(P2)
	XPAH P1
	LD OBJ_L(P2)  
	ANI 0xF0
	ORI 0x01
	XPAL P1							;P1 points to start of line

	LDI 0x04
	ST TEMP_Y(P2)

CCL_LOOP1:
	LD True_1(P2)
	ST LINE_COMP(P2)				;Set Line Complete to True(1)
	
	LDI 0x0A
	ST TEMP_X(P2)
	LD @0(P1)
	XRI 0x23						;Check for bottom line #
	JNZ CCL_LOOP2
	LD False_0(P2)					;Set Line Complete to False(0)
	ST LINE_COMP(P2)				;if character 20(space) found
	
CCL_LOOP2:
	LD @1(P1)
	XRI 0x20
	JNZ CCL_NEXT
	LD False_0(P2)					;Set Line Complete to False(0)
	ST LINE_COMP(P2)				;if character 20(space) found
	
CCL_NEXT
	DLD TEMP_X(P2)
	JNZ CCL_LOOP2					;Check rest of line
	
	LD LINE_COMP(P2)
	JZ CCL_NEXT_LINE
	ILD LINE_COMP_SUB(P2)

	LD @-11(P1)						;Move to start of line
	
	LDI 0xA3
	ST @1(P1)						;Mark Line for deletion
	ILD LINES_DELETED(P2)


DELETE_LINE:
	LD @10(P1)

CCL_NEXT_LINE:
	
	LD @6(P1)
	DLD TEMP_Y(P2)
	JNZ CCL_LOOP1					;Check next line
	
	LD LINES_DELETED(P2)
	JZ CHECK_COMPLETE_LINE_RETURN
	
	LD LEVEL(P2)
	ST TEMP_X(P2)
	ILD TEMP_X(P2)

LOOP_FOR_EACH_LEVEL:
	LDI VAR_0FB7/256
	XPAH P1
	LDI VAR_0FB7\256
	XPAL P1
	
	CCL
	LD LINES_DELETED(P2)
	ADI 0x04
	ST TEMP_1(P2)
	
	LD LINES_DELETED(P2)
	XAE
	
	CCL
	LD SCORE_U(P2)
	DAD -128(P1)
	ST SCORE_U(P2)
	LD TEMP_1(P2)
	XAE
	LD SCORE_T(P2)
	DAD -128(P1)
	ST SCORE_T(P2)
	LD SCORE_H(P2)
	DAI 0x00
	ST SCORE_H(P2)
	
	DLD TEMP_X(P2)
	JNZ LOOP_FOR_EACH_LEVEL

CHECK_COMPLETE_LINE_RETURN:
	RET P3
;====================================================================
;====================================================================
UPDATE_OBJECT_NEXT:
	LD True_1(P2)
	ST OBJ_NEXT(P2)
	LD OBJ_NUM_NEXT(P2)
	ST OBJ_NUM(P2)
	LDI 0x20
	ST SPACE_CHR(P2)
	JP UPDATE_OBJECT_NEXT_2
;====================================================================
UPDATE_OBJECT_OLD:
	LD OBJ_NUM_OLD(P2)
	ST OBJ_NUM(P2)

UPDATE_OBJECT:
	LD False_0(P2)
	ST OBJ_NEXT(P2)
	ST SPACE_CHR(P2)
	
UPDATE_OBJECT_NEXT_2:
	LDI VAR_0FB0/256
	XPAH P1
	LDI VAR_0FB0\256
	XPAL P1
	
	LD OBJ_NUM(P2)
	ANI 0x07
	XAE
	LD -128(P1)
	ST OBJ_CHR(P2)

	LDI VAR_0F70\256
	XPAL P1

	LD OBJ_NUM(P2)				;Get 2 Bytes that make up object
	XAE
	LD -128(P1)
	ST OBJ_1_BYTE(P2)
	CCL
	LD OBJ_NUM(P2)
	ADI 0x20					;Location of Second Byte of object
	XAE
	LD -128(P1)
	ST	OBJ_2_BYTE(P2)
	
;----------------------------------------------------------------
	OR OBJ_1_BYTE(P2)
	ST TEMP_1(P2)
	ANI 0x0F
	ST OBJ_BYTE(P2)
	LD TEMP_1(P2)
	ANI 0xF0
	RR
	RR
	RR
	RR
	OR OBJ_BYTE(P2)
	ST OBJ_BYTE(P2)
	LDI 0x00
	ST OBJ_WIDTH(P2)
	
NEXT_OBJECT_BIT:
	LD OBJ_BYTE(P2)
	ANI 0x01
	JZ CHECK_OBJECT_WIDTH
	LD OBJ_BYTE(P2)
	RR
	ST OBJ_BYTE(P2)
	ILD OBJ_WIDTH(P2)
	JMP NEXT_OBJECT_BIT

;----------------------------------------------------------------
CHECK_OBJECT_WIDTH:

	CCL
	LD OBJ_L(P2)
	ANI 0x0F
	ADD OBJ_WIDTH(P2)
	ST TEMP_1(P2)

	LD OBJ_NEXT(P2)
	JNZ GET_OBJECT

CHECK_0C
	LD TEMP_1(P2)
	XRI 0x0C
	JNZ CHECK_0D
	JMP UPDATE_OBJECT_OLD
		
CHECK_0D
	LD TEMP_1(P2)
	XRI 0x0D
	JNZ CHECK_0E
	JMP UPDATE_OBJECT_OLD

CHECK_0E
	LD TEMP_1(P2)
	XRI 0x0E
	JNZ GET_OBJECT
	JMP UPDATE_OBJECT_OLD

GET_OBJECT:
	LDI 0x02
	ST	TEMP_X(P2)

	LDI VAR_0F60\256			;P1 = Object Shape Location
	XPAL P1
	
LOOP0:
	LDI 0x08
	ST	TEMP_Y(P2)
	
LOOP1:
	LD OBJ_1_BYTE(P2)
	ANI 0x01
	JZ CHR_STORED

	LD OBJ_CHR(P2)
	JMP STORE_CHARACTER

CHR_STORED:
	LD SPACE_CHR(P2)

STORE_CHARACTER:
	ST @1(P1)
	LD OBJ_1_BYTE(P2)
	RR
	ST OBJ_1_BYTE(P2)
	DLD TEMP_Y(P2)
	JNZ LOOP1
	
	LD OBJ_2_BYTE(P2)
	ST OBJ_1_BYTE(P2)
	DLD TEMP_X(P2)
	JNZ LOOP0
	
	LD False_0(P2)
	ST OBJ_NEXT(P2)

UPDATE_OBJECT_RETURN:
	RET P3
	
;=====================================================================
;=====================================================================
CLEAR_PLAY_AREA:

	LDI CLEAR_SCREEN/256
	XPAH P1
	LDI CLEAR_SCREEN\256
	XPAL P1
	
	LDI 0x17
	ST	TEMP_Y(P2)

CLS_LOOP1:
	LDI 0x0A
	ST	TEMP_X(P2)
	
CLS_LOOP2:
	LDI 0x20
	ST @1(P1)
	DLD TEMP_X(P2)
	JNZ CLS_LOOP2
	LD @6(P1)
	DLD TEMP_Y(P2)
	JNZ CLS_LOOP1
	
CLEAR_PLAY_AREA_RETURN:	
	RET P3
	
;=====================================================================
;=====================================================================
	.OR PROG2
GET_INPUT:

KYBD:
	LDI 0x00
	ST CHAR(P2)
	
	LDI KEYBOARD/256
	XPAH P1

OFF:
	LDI 0xFF
	ST ROW(P2)
	LDI 10							;Set row counter
	ST CNT(P2)
	LDI 0
	ST PUSHED(P2)					;Zero keyboard input
	XPAL P1							;Update row address
LOOPB:
	ILD ROW(P2)						;Update row address
	XAE
	LDI 0x00
	ST -128(P1)
	LD -128(P1)						;Get segmant
	XRI 0xFF						;Check if pushed
	JZ BACK							;Jump if not pushed
	ORE
	ST PUSHED(P2)
BACK:
	DLD CNT(P2)						;Check if done
	JNZ LOOPB						;No if jump
	LD PUSHED(P2)					;No set character
	ST CHAR(P2)
	
	LD PUSHED(P2)
	JNZ CHECK_KEY_PRESSED
	LD False_0(P2)
	ST KEY_PRESSED(P2)
	RET P3
	
CHECK_KEY_PRESSED:
	LD KEY_PRESSED(P2)
	JZ TEST_2
	RET P3

TEST_2:					;Move Down
	LD True_1(P2)
	ST KEY_PRESSED(P2)

	LD PUSHED(P2)
	XRI 0x82
	JNZ TEST_4
	ILD KEYPRESS(P2)
	LDI 0x01
	ST TEMP_1(P2)
	ST DELAY_LOOP(P2)
	ST SCORE(P2)

TEST_4:					;Move Left
	LD PUSHED(P2)
	XRI 0x84
	JNZ TEST_6
	ILD KEYPRESS(P2)
	LD OBJ_L(P2)
	ANI 0x0F
	XRI 0x01
	JZ TEST_6			;Check if at edge of screen

	LDI 0x0F
	ST X_MOVE(P2)

TEST_6:					;Move Right
	LD PUSHED(P2)
	XRI 0x86
	JNZ TEST_C
	CCL
	LD OBJ_L(P2)
	ANI 0x0F
	ADD OBJ_WIDTH(P2)
	XRI 0x0B
	JZ TEST_C						;Check for right hand edge
	ILD KEYPRESS(P2)
	LDI 0x11
	ST X_MOVE(P2)
	
TEST_C:
	LD PUSHED(P2)
	XRI 0x12
	JNZ TEST_D
	ILD KEYPRESS(P2)
	LD OBJ_NUM(P2)					;Rotate object clockwise
	ST OBJ_NUM_OLD(P2)
	CCL
	ADI 0x08
	ANI 0x1F
	ST OBJ_NUM(P2)
	
TEST_D:
	LD PUSHED(P2)
	XRI 0x13
	JNZ NO_MORE_KEYS_TO_CHECK
	ILD KEYPRESS(P2)
	LD OBJ_NUM(P2)					;Rotate object anti clockwise
	ST OBJ_NUM_OLD(P2)
	CCL
	ADI 0x18
	ANI 0x1F
	ST OBJ_NUM(P2)
	
NO_MORE_KEYS_TO_CHECK:
	DLD RND(P2)						;RND counts down from 0x31 to zero
	JNZ GET_INPUT_RETURN
	LDI 0x31
	ST RND(P2)

GET_INPUT_RETURN:

	RET P3
;======================================================================
;======================================================================
PLACE_OBJECT_NEXT:
	LDI 0x03
	ST OBJ_H(P2)
	LDI 0x7C
	ST OBJ_L(P2)			;Next object postion
	JP PLACE_OBJECT
;----------------------------------------------------------------------

DELETE_OBJECT:
	LD True_1(P2)
	ST OBJ_DELETE(P2)				; Set Object Delete to True
;----------------------------------------------------------------------
PLACE_OBJECT:
	LD OBJ_H(P2)
	XPAH P1
	LD OBJ_L(P2)  
	XPAL P1							; P1 now points top object location
	
	LDI 0x5F
	ST OBJ_P(P2)					;0x0F60 contains object
	
	LDI 0x04
	ST OBJ_ROW(P2)
	
NEXT_ROW:
	LDI 0x04
	ST OBJ_COL(P2)
	
NEXT_COL:
	LD OBJ_DELETE(P2)
	JNZ DELETE_OBJECT_BYTE

	ILD OBJ_P(P2)
	XAE
	LD -128(P2)
	JZ DO_NOT_STORE
	ST @1(P1)						; Place Object
	JP STORED
	
DELETE_OBJECT_BYTE:
	ILD OBJ_P(P2)
	XAE
	LD -128(P2)
	JZ DO_NOT_STORE
	LDI 0x20
	ST @1(P1)						; Place Space Chracter
	JP STORED
	
NEXT_OBJECT_BYTE:
	ILD OBJ_P(P2)
	XAE
	LD -128(P2)
	ST @1(P1)						; Place Space Chracter
	JP STORED
	
DO_NOT_STORE:
	LD @1(P1)
	
STORED:
	
	DLD OBJ_COL(P2)
	JNZ NEXT_COL
	
	LD @12(P1)
	DLD OBJ_ROW(P2)
	JNZ NEXT_ROW
	
	LDI 0x00
	ST OBJ_DELETE(P2)		; Reset Object Delete to False

PLACE_OBJECT_RETURN:
	RET P3
	
;======================================================================
;======================================================================
	.OR PROG3
DISPLAY_TEST_INFO:

	LDI DISP_TEST/256
	XPAH P1
	LDI DISP_TEST\256
	XPAL P1
	
	LD KEYPRESS(P2)
	ST @1(P1)
	LD @2(P1)
	
	LD OBJ_WIDTH(P2)
	ORI 0x30
	ST @1(P1)
	LD @1(P1)
	
	CCL
	LD OBJ_L(P2)
	ANI 0x0F
	ADD OBJ_WIDTH(P2)
	ORI 0x30
	ST @1(P1)
	LD @1(P1)
	
	LD DELAY_LEVEL(P2)
	ORI 0x30
	ST @1(P1)
	LD @1(P1)
	
	LD CHAR(P2)
	;ORI 0x30
	ST @1(P1)
	LD @1(P1)
	
	
DISPLAY_TEST_INFO_RETURN:
	RET P3
;======================================================================

;======================================================================
	.OR DISP_TEXT
	.HS 23202020101205131320202320202020
	.HS 23202020202020202020202323232323
	.HS 23202020070F20140F20202320202020
	.HS 23202020202020202020202320202020
	.HS 23202020131401121420202320202020



EXEC_ADR:	
	.NO 0xFFFE
	.DB ENTRY/256
	.DB ENTRY\256
