	DEVICE ZXSPECTRUM48
	
	MACRO PRINT
		IFDEF MGT
			rst $10
			defw $10
		ELSE
			rst $10
		ENDIF
	ENDM
	
	MACRO CALLBAS addr
		IFDEF MGT
			rst $10
			defw addr
		ENDIF		
		IFDEF ESXDOS
			rst $18
			defw addr
		ENDIF		
		IFNDEF ESXDOS
			IFNDEF MGT
				call addr
			ENDIF
		ENDIF
	ENDM

	IFDEF ESXDOS
START:			equ $2000
	ENDIF
	IFDEF MGT
START:			equ $3BD6
	ENDIF
	IFNDEF ESXDOS
		IFNDEF MGT
START:			equ $FF57 - LENGTH
		ENDIF
	ENDIF
	
	DISPLAY "Start: ",/A,START

ROM_CHAN_OPEN:	equ $1601
ROM_STK_STO:	equ $2AB2
ROM_STACK_A:	equ $2D28
ROM_STACK_BC:	equ $2D2B
ROM_FP_TO_BC:	equ $2DA2
ROM_PRINT_FP:	equ $2DE3

VAR_VARS:		equ $5C4B
CHR_RETN:		equ $0D
CHR_INVR:		equ $14
CHR_QUOT:		equ $22
CHR_DOLA:		equ $24
CHR_EQUA:		equ $3D
TOK_TO:			equ $CC
TOK_STEP:		equ $CD

SYS_VARS:		equ $5C4B
SYS_ELINE:		equ $5C59

	org START
	
	IFNDEF ESXDOS
		; Open channel S(creen) for printing
		; (not needed for esxDOS)
		ld a,-2
		CALLBAS ROM_CHAN_OPEN
	ENDIF

	ld hl,(VAR_VARS)
	ld a,(hl)
	cp $80
	jr nz, CHECK_7
	
	ld de,m_intro
	call PRINT_MSG

NEXT_CHARACTER:
	ld a,(hl)
	cp $80					; $80 is the VARS end-marker
	jr z, EXIT
CHECK_7:
	bit 7,a
	jr nz,CHECK_6			; if Bit7 is set, next check Bit6…
	bit 5,a					; if Bit7 is NOT set, ignore Bit6 and check Bit5
	jp z,STRING				; must be 010 String [000 is not used]
	jp NUMBER				; must be 011 Number (short name) [001 is not used]
CHECK_6:
	bit 6,a					; we know Bit7 is set
	jr nz,CHECK_5			; if Bit6 is set, next check Bit5…
	bit 5,a					; 10(?)
	jp nz,LONG_NAME			; 101 Number (long name)
	jr ARRAY				; 100 Number array
CHECK_5:
	bit 5,a					; We now know Bit7 and Bit6 are set,
	jr z,STRINGARRAY		; 110 String array
	jr FORNEXT				; 111 FOR..NEXT control
EXIT:
	call SHOW_TOTAL
	or a ; clear carry = flag to esxDOS no error
	ret

STRINGARRAY:
	ld de,m_string
	jr PRINT_LETTER
ARRAY:
	ld de,m_array
PRINT_LETTER:
	ld a,(hl)
	and %00011111
	add a,$40
	PRINT
	call PRINT_MSG
	ld a,$20
	PRINT

	push hl
	; details
		inc hl
		ld c,(hl)
		inc hl
		ld b,(hl)					; BC = Total length of elements & dims + 1
		inc hl

		ld b,(hl)					; B = Number of dimensions
		inc hl						; HL = pointer -> 1st Dims

PRINT_DIMS:
		push bc
			ld c,(hl)
			inc hl
			ld b,(hl)				; BC = size of dimension
			inc hl
			push hl
				CALLBAS ROM_STACK_BC
				CALLBAS ROM_PRINT_FP
			pop hl
		pop bc
		ld a,b
		dec a
		jr z,NO_DELIMITER
		ld a,"x"
		PRINT
NO_DELIMITER:
		djnz PRINT_DIMS

		ld a,$20
		PRINT
		ld a,CHR_RETN
		PRINT

	pop hl
SKIP_WORD_LENGTH:
	inc hl
	ld e,(hl)
	inc hl
	ld d,(hl)
	ADD hl,de
	inc hl
	jr NEXT_CHARACTER

FORNEXT:
	ld a,CHR_INVR
	PRINT
	ld a,$01			; 01 inverse ON
	PRINT
	ld a,(hl)
	xor $A0				; 10100000	111xxxxx -> 010xxxxx
	PRINT
	ld a,CHR_INVR
	PRINT
	xor a				; 00 inverse OFF
	PRINT
	ld a,$20
	PRINT
	inc hl
	call PRINT_NUMBER
	ld a,TOK_TO	
	PRINT
	call PRINT_NUMBER
	ld a,TOK_STEP
	PRINT
	call PRINT_NUMBER
	ld a,CHR_RETN
	PRINT
	ld de,13-10
	ADD hl,de
	jp NEXT_CHARACTER

STRING:
	ld a,(hl)
	PRINT
	ld a,CHR_DOLA
	PRINT
	ld a,CHR_EQUA
	PRINT
	ld a,CHR_QUOT
	PRINT
	inc hl
	ld c,(hl)
	inc hl
	ld b,(hl)
	inc hl
	ld a,b
	or c
	jr z,STRING_LOOP_DONE
STRING_LOOP:
	ld a,(hl)
	PRINT
	inc hl
	dec bc
	ld a,b
	or c
	jr nz,STRING_LOOP
STRING_LOOP_DONE:
	ld a,CHR_QUOT
	PRINT
	ld a,CHR_RETN
	PRINT
	jp NEXT_CHARACTER

NUMBER:
	ld a,(hl)
	res 5,a
	PRINT
NUMBER_EQ:
	ld a,CHR_EQUA
	PRINT
	inc hl
	call PRINT_NUMBER
	ld a,CHR_RETN
	PRINT
	jp NEXT_CHARACTER

LONG_NAME:
	ld a,(hl)
	xor $E0					; 11100000	101xxxxx -> 010xxxxx
	PRINT
LONG_NAME_LOOP:
	inc hl
	ld a,(hl)
	bit 7,a
	jr nz,LONG_NAME_LAST
	PRINT
	jr LONG_NAME_LOOP
LONG_NAME_LAST:
	res 7,a
	PRINT

	jr NUMBER_EQ
	
PRINT_NUMBER:
	ld a,(hl)
	inc hl
	ld e,(hl)
	inc hl
	ld d,(hl)
	inc hl
	ld c,(hl)
	inc hl
	ld b,(hl)
	inc hl
	
	push hl
	CALLBAS ROM_STK_STO		; FPC stack 5-byte value
	CALLBAS ROM_PRINT_FP
	pop hl
	ret

PRINT_MSG:
	ld a,(de)
	or a
	ret z
	PRINT
	inc de
	jr PRINT_MSG
	
SHOW_TOTAL:
	ld a,CHR_RETN
	PRINT
	scf
	ld hl,(SYS_ELINE)
	ld bc,(SYS_VARS)
	sbc hl,bc
	ld b,h
	ld c,l
	CALLBAS ROM_STACK_BC
	CALLBAS ROM_PRINT_FP
	ld de,m_bytuse
	call PRINT_MSG
	ret
	
m_intro:
	defm "Variables List",$0D
	defm "by Neil R. Canham, 1984",$0D
	defb $0D
	defm "This machine-code program for",$0D
	defm "the 16K or 48K Spectrum lists",$0D
	defm "all defined BASIC variables.",$0D
	defb $0D
	defb 0
m_string:
	defm "$"
m_array:
	defm " array",0
m_bytuse:
	defm " bytes used.",$0D,0
	
	IFDEF MGT
	defs 510-($-START)				; Pad to 510 bytes for MGT format
	ENDIF
	
LENGTH:	equ $-START
	
	DISPLAY "Length: ",/D,LENGTH
	SAVEBIN "VARS",START,LENGTH

	IFNDEF ESXDOS
		IFNDEF MGT
		include	 TapLib.asm
		MakeTape ZXSPECTRUM48, "vars.tap", "VARS", START, LENGTH, START
		ENDIF
	ENDIF