.Z80
;	841002 ULF NORDQUIST

CPM		EQU	0
BDOS		EQU	0005H

DIRCIO		EQU	06H		;DIRECT CONSOLE I/O
LF		EQU	10
CR		EQU	13
ESC		EQU	1BH
CURPOS		EQU	3DH		;CURSOR POSITIONING COMMAND
IVMIN		EQU	0		;INIT MIN VERT COUNT
IVMAX		EQU	23		;INIT MAX VERT COUNT
IHMIN		EQU	0		;INIT MIN HORIZ COUNT
IHMAX		EQU	78		;INIT MAX HORIZ COUNT
ICHAR		EQU	21H		;INIT CHARACTER

SPIRAL: 	LD	(SPSAVE),SP
		LD	SP,STACK	;INIT SP
		LD	A,ESC
		CALL	CRT
		LD	A,4CH
		CALL	CRT		;CLEAR AND HOME
SPIRAL13:	LD	A,ICHAR
		LD	(CHAR),A        ;INIT CHARACTER
SPIRAL11:	LD	A,IHMIN
		LD	(HPOS),A        ;INIT CURSOR HORIZ
		LD	(HMIN),A        ;INIT MIN HORIZ
		LD	A,IHMAX
		LD	(HMAX),A        ;INIT MAX HORIZ
		LD	A,IVMIN
		LD	(VPOS),A        ;INIT CURSOR VERT
		LD	(VMIN),A        ;INIT MIN VERT
		LD	A,IVMAX
		LD	(VMAX),A        ;INIT MAX VERT
		CALL	CURSOR		;POS CURSOR
		LD	A,(CHAR)
		CALL	CRT		;SEND CHAR

;	GO RIGHT TO HMAX

SPIRAL8:	LD	A,(VMIN)
		LD	B,A
		LD	A,(VMAX)
		CP	B
		JR	Z,SPIRAL2	;IF VMAX=VMIN, CONT
		INC	B		;INC VMIN
		LD	A,B
		LD	(VMIN),A        ;UPDATE VMIN
SPIRAL2:	LD	A,(HMAX)
		LD	B,A
		LD	A,(HPOS)
		CP	B
		JR	Z,SPIRAL1	;IF AT HMAX=HPOS CONT AT NXT
		INC	A
		LD	(HPOS),A        ;UPDATE HPOS
		CALL	CURSOR		;POS CURSOR
		LD	A,(CHAR)
		CALL	CRT		;SEND CHAR
		JR	SPIRAL2

;	GO DOWN TO VMAX

SPIRAL1:	LD	A,(HMIN)
		CP	B
		JR	Z,SPIRAL4	;IF HMAX=HMIN CONT
		DEC	B		;DEC HMAX
		LD	A,B
		LD	(HMAX),A        ;UPDATE HMAX
SPIRAL4:	LD	A,(VMAX)
		LD	B,A
		LD	A,(VPOS)
		CP	B
		JR	Z,SPIRAL3	;IF VPOS=VMAX CONT AT NXT
		INC	A
		LD	(VPOS),A        ;UPDATE VPOS
		CALL	CURSOR		;POS CURSOR
		LD	A,(CHAR)
		CALL	CRT		;SEND CHAR
		JR	SPIRAL4

;	GO LEFT TO HMIN

SPIRAL3:	LD	A,(VMIN)
		CP	B
		JR	Z,SPIRAL5	;IF VMAX=VMIN
		DEC	B		;DEC VMAX
		LD	A,B
		LD	(VMAX),A        ;UPDATE VMAX
SPIRAL5:	LD	A,(HMIN)
		LD	B,A
		LD	A,(HPOS)
		CP	B
		JR	Z,SPIRAL6	;IF HPOS=HMIN
		DEC	A
		LD	(HPOS),A        ;UPDATE VPOS
		CALL	CURSOR		;POS CURSOR
		LD	A,(CHAR)
		CALL	CRT		;SEND CHAR
		JR	SPIRAL5

;	GO UP TO VMIN

SPIRAL6:	LD	A,(HMAX)
		CP	B
		JR	Z,SPIRAL7	;IF HMAX=HMIN
		INC	B		;INC HMIN
		LD	A,B
		LD	(HMIN),A        ;UPDATE VMAX
SPIRAL7:	LD	A,(VMIN)
		LD	B,A
		LD	A,(VPOS)
		CP	B
		JP	Z,SPIRAL9	;IF VPOS=VMIN
		DEC	A
		LD	(VPOS),A        ;UPDATE VPOS
		CALL	CURSOR		;POS CURSOR
		LD	A,(CHAR)
		CALL	CRT		;SEND CHAR
		JR	SPIRAL7

;	CHECK IF SCREEN IS FILLED

SPIRAL9:	LD	A,(VMAX)
		CP	B
		JR	NZ,SPIRAL10	;IF VMIN<>VMAX
SPIRAL12:	LD	A,(CHAR)
		CP	7FH
		JP	Z,SPIRAL13	;START OVER
		INC	A
		LD	(CHAR),A        ;UPDATE CHAR
		JP	SPIRAL11	;START NEW SPIRAL
SPIRAL10:	LD	A,(HMIN)
		LD	B,A
		LD	A,(HMAX)
		CP	B
		JP	NZ,SPIRAL8	;CONT SPIRAL
		JR	SPIRAL12

;	SUBROUTINE --- CURSOR ---
;	POSITIONS CURSOR AT CURRENT VPOS AND HPOS
;	ENTRY : HPOS & VPOS UPDATED
;	CHANGES : -

CURSOR: 	PUSH	AF
		PUSH	BC
		PUSH	DE
		PUSH	HL
		LD	A,ESC
		CALL	CRT		;OUTPUT ESCAPE
		LD	A,CURPOS
		CALL	CRT		;OUTPUT CUR POS CMD
		LD	A,(VPOS)
		ADD	A,20H		;OFFSET
		CALL	CRT		;SEND LINE NO
		LD	A,(HPOS)
		ADD	A,20H
		CALL	CRT		;SEND COL NO
		LD	E,0FFH		;FLAG FOR INPUT
		LD	C,DIRCIO
		CALL	BDOS		;GET CHR FROM CONSOLE
		OR	A
		JR	Z,CURSOR1	;IF NO DATA
		LD	A,23
		LD	(VPOS),A
		XOR	A
		LD	(HPOS),A
		CALL	CURSOR		;LOWER LEFT CORNER
		LD	A,CR
		CALL	CRT
		LD	A,LF
		CALL	CRT		;NEW LINE
		LD	SP,(SPSAVE)
		RET			;EXIT TO CPM
CURSOR1:	POP	HL
		POP	DE
		POP	BC
		POP	AF
		RET

;	SUBROUTINE --- CRT ---
;	ENTRY : A=DATA TO SEND TO CONSOLE
;	CHANGES : -

CRT:		PUSH	AF
		PUSH	BC
		PUSH	DE
		PUSH	HL
		LD	E,A		;DATA TO SEND
		LD	C,DIRCIO
		CALL	BDOS
		POP	HL
		POP	DE
		POP	BC
		POP	AF
		RET

;	STORAGE

VPOS		EQU	0A000H		;CURRENT VERT POS
HPOS		EQU	0A001H		;CURRENT HOR POS
VMAX		EQU	0A002H		;CURRENT VERT MAX
HMAX		EQU	0A003H		;CURRENT HOR MAX
VMIN		EQU	0A004H		;CURRENT VERT MIN
HMIN		EQU	0A005H		;CURRENT HOR MIN
CHAR		EQU	0A006H		;CURRENT CHARACTER
SPSAVE		EQU	0A007H		;SAVE ENTRY SP

STACK		EQU	0A100H		;TOP OF STACK

		END

