

;	Some macros used by the math routines
;	-------------------------------------

cmp.w:		.macro	field1, [#] field2
		lda	%1+1
		.ifm	2 immediate
		cmp	%2 / 256
		.else
		cmp	%2 + 1
		.endif
		bne	~a
		lda	%1
		.ifm	2 immediate
		cmp	%2 & $ff
		.else
		cmp	%2
		.endif
~a:
		.endm


sub.w:		.macro	field_1, [#] field_2, [field_3]
		sec
		.ifm	2 immediate
		  lda	%1
		  sbc	%2 & $ff
		  pha
		  lda	%1+1
		  sbc	%2 / 256
		.else
		  lda	%1
		  sbc	%2
		  pha
		  lda	%1+1
		  sbc	%2+1
		.endif
		.ifm	3 exists
		  sta	%3+1
		  pla
		  sta	%3
		.else
		  sta	%1+1
		  pla
		  sta	%1
		.endif
		.endm


;======================================================================
;		Low level fetch and get instructions
;======================================================================

__rts:		rts


	.IF_REFERENCED _saveax
_saveax:	sta _save_a	;save A,X into temp area
		stx _save_x
		rts
_getax: 	lda _save_a
		ldx _save_x
		rts
	.ENDIF


	.IF_REFERENCED _saveop1
_saveop1:	sta _oper1		;save operator
		stx _oper1+1
		rts
	.ENDIF

	.IF_REFERENCED _saveop2
_saveop2:	sta _oper2
		stx _oper2+1
		rts
	.ENDIF


	.IF_REFERENCED _loadiptr
_loadiptr:	sta _iptr		;load IPTR with value in A,X
		stx _iptr+1
		rts
	.ENDIF


	.IF_REFERENCED _loadiofst
_loadiofst: sta _iofst
		stx _iofst+1
		rts
	.ENDIF


	.IF_REFERENCED _gchar
_gchar: 	sta _iptr		;fetch char at @ in A,X
		stx _iptr+1
		ldy #0
		lda (_iptr),y
		ldx #0
		rts
	.ENDIF


	.IF_REFERENCED _gint
_gint:		sta _iptr		;fetch int at @ in A,X
		stx _iptr+1
		ldy #1
		lda (_iptr),y
		tax
		dey
		lda (_iptr),y
		rts
	.ENDIF


	.IF_REFERENCED _gochar
_gochar:	clc		;fetch char at @ in A,X with
		adc _iofst		; offset of IOFST
		sta _iptr
		txa
		adc _iofst+1
		sta _iptr+1
		ldy #0
		lda (_iptr),y
		ldx #0
		rts
	.ENDIF


	.IF_REFERENCED _goint
_goint: 	asl _iofst			;double the offset
		rol _iofst+1
		clc
		adc _iofst
		sta _iptr
		txa
		adc _iofst+1
		sta _iptr+1
		ldy #1
		lda (_iptr),y
		tax
		dey
		lda (_iptr),y
		rts
	.ENDIF


	.IF_REFERENCED _pchar
_pchar: 	ldy #0
		sta (_iptr),y
		rts
	.ENDIF


	.IF_REFERENCED _pint
_pint:		ldy #0
		sta (_iptr),y
		iny
		txa
		sta (_iptr),y
		rts
	.ENDIF


	.IF_REFERENCED _pochar
_pochar:	pha
		jsr _calcofst
		ldy #0
		pla
		sta (_iptr),y
		rts
	.ENDIF


	.IF_REFERENCED _point
_point: 	asl _iofst			;double the offset
		rol _iofst+1
		sta .tempa
		stx .tempx
		jsr _calcofst
		ldy #0
		lda .tempa
		sta (_iptr),y
		iny
		lda .tempx
		sta (_iptr),y
		rts
.tempa: 	dc.b	0
.tempx: 	dc.b	0
	.ENDIF


	.IF_REFERENCED _calcofst
_calcofst:	lda _iptr
		clc
		adc _iofst
		sta _iptr
		lda _iptr+1
		adc _iofst+1
		sta _iptr+1
		rts
	.ENDIF



;	Compare (16-bit) value at _comp1 to value in A,X
;
;	Returns:	 BEQ  ->  operands are equal
;			 BMI  ->  _oper1 < _oper2
;			 BNE  ->  _oper1 > _oper2
;	---------------------------------------------------

	.IF_REFERENCED _compare
_compare:	cpx	_comp1+1
		bne	.noteq
		cmp	_comp1
		bne	.noteq
.equal: 	rts
.noteq: 	bcs	.less1
.great1:	lda #1
		rts
.less1: 	lda #$ff
		rts
	.ENDIF



_getdev:	asl		;multiply device in A * 16
		asl
		asl
		asl
		tax
_rts:		rts




;======================================================================
;		High level Input and Output functions
;======================================================================

	.IF_REFERENCED printf
printf: 	lda #0		;printf to device 0
		jmp _printf
	.ENDIF

	.IF_REFERENCED fprintf
fprintf:	lda _parm1		;printf to a specified device
		pha		;save device
		ldy #0
.move:		lda _parm2,y	;move parms down
		sta _parm1,y
		iny
		cpy #18
		bcc .move
		pla
		jmp _printf
	.ENDIF


	.IF_REFERENCED _printf
_printf:	sta .device	;the actual printf routine
		lda _parm1
		sta _pfptr
		lda _parm1+1
		sta _pfptr+1
		ldy #0		;make our own private copy of
.gstack:	lda _parm2,y	; the stack parameters
		sta .stack,y
		iny
		cpy #18
		bcc .gstack

		ldy #0
		sty .stkidx
		lda (_pfptr),y	;length of mask
		sta .strlth
		iny
		sty .stridx

.loop:		ldy .stridx
		cpy .strlth
		bcc .notdone
		beq .notdone
		lda #1
		ldx #0
		rts
.notdone:	lda (_pfptr),y		;next byte of string
		cmp #'%'			;special lead-in?
		beq .special
.thischar:	sta _parm1
		ldx .device
		jsr __putchar
		bmi .error
.nextbyte:	inc .stridx
		jmp .loop
.error: 	lda #0
		ldx #0
		rts
.special:	iny
		sty .stridx
		lda (_pfptr),y
		cmp #'s'			;string?
		beq .string
		cmp #'d'
		beq .decimal
		cmp #'e'
		beq .eol
		cmp #'c'			;string?
		beq .char
		cmp #'h'			;hex?
		beq .hex
		cmp #'f'			;floating point?
		bne .notfl
		jmp .float
.notfl: 	jmp .thischar
.eol:		lda #$9b
		ldx .device
		jsr __putchar
		bmi .error
		jmp .nextbyte
.string:	lda .stkidx
		asl
		tay
		lda .stack,y
		sta _parm1
		lda .stack+1,y
		sta _parm1+1
		ldx .device
		lda _parm1
		ldy _parm1+1
		jsr __putstr
		bmi .strerr
		inc .stkidx
		jmp .nextbyte
.strerr:	jmp .error
.decimal:	lda .stkidx
		asl
		tay
		lda .stack,y
		sta _parm1
		lda .stack+1,y
		sta _parm1+1
		ldx .device
		lda _parm1
		ldy _parm1+1
		jsr __putnum
		bmi .strerr
		inc .stkidx
		jmp .nextbyte
.char:		lda .stkidx
		asl
		tay
		lda .stack,y
		ldx .device
		jsr __putchar
		bmi .strerr
		inc .stkidx
		jmp .nextbyte
.hex:		lda .stkidx
		asl
		tay
		lda .stack,y
		sta _parm1
		lda .stack+1,y
		sta _parm1+1
		ldx .device
		lda _parm1
		ldy _parm1+1
		jsr __puthex
		bmi .strerr
		inc .stkidx
		jmp .nextbyte
.float: 	lda .stkidx
		asl
		tay
		lda .stack,y
		sta _parm1
		lda .stack+1,y
		sta _parm1+1
		ldx .device
		lda _parm1
		ldy _parm1+1
		jsr __putfloat
		bmi .strerr
		inc .stkidx
		jmp .nextbyte
.device:	ds.b	1
.strlth:	ds.b	1
.stridx:	ds.b	1
.stkidx:	ds.b	1
.stack: 	ds.b	20
	.ENDIF




	.IF_REFERENCED write_ram
write_ram:	lda	88
		sta	_ptr
		lda	89
		sta	_ptr+1
		ldy	_parm2		;ypos in parm2
		beq	.done
		cpy	#25		;must be 1-24..
		bcc	.ckidx
		jmp	.done
.calc:		lda	_ptr
		clc
		adc	#40
		sta	_ptr
		lda	_ptr+1
		adc	#0
		sta	_ptr+1
.ckidx: 	dey
		bne	.calc
.done:		dec	_parm1
		lda	_ptr
		clc
		adc	_parm1
		sta	_ptr
		lda	_ptr+1
		adc	#0
		sta	_ptr+1

		lda	_parm3
		sta	_sptr
		lda	_parm3+1
		sta	_sptr+1
		ldy #0
		lda (_sptr),y		;get length byte
		sta _freslo		;use freslo as length byte
		iny			;move to first byte of string
		sty _freshi		;use freshi as length pointer
.loop:		ldy _freshi
		cpy _freslo		;done yet?
		bcc .notdone
		beq .notdone
		rts
.notdone:	lda (_sptr),y		;get byte
		jsr	.xlate		;translate it
		ldy	#0
		sta	(_ptr),y
		inc	_ptr
		bne	.novf1
		inc	_ptr+1
.novf1: 	inc _freshi
		bne .loop
.exit:		rts
.temp:		ds.b	1
.xlate: 	sta	.temp
		and	#$7f
		cmp	#32
		bcc	.add64
		cmp	#96
		bcc	.sub32
		jmp	.asis
.add64: 	clc
		adc	#64
		jmp	.asis
.sub32: 	sec
		sbc	#32
.asis:		bit	.temp
		bpl	.xxlate
		ora	#$80
.xxlate:	rts
	.ENDIF




	.IF_REFERENCED pute
pute:		ldx #0
		lda #$9b
		sta _parm1
		jmp put
	.ENDIF


	.IF_REFERENCED put
put:		lda _parm1
		ldx #0
		jsr __putchar
		bpl .ok
.err:		lda #0
		beq .exit
.ok:		lda #1
.exit:		ldx #0
		rts
	.ENDIF


	.IF_REFERENCED putd
putd:		ldx _parm1
		lda _parm2
		jsr __putchar
		bpl .ok
.err:		lda #0
		beq .exit
.ok:		lda #1
.exit:		ldx #0
		rts
	.ENDIF


	.IF_REFERENCED getd
getd:		ldx _parm1
		jsr __getchar
		ldx #0
		rts
	.ENDIF


	.IF_REFERENCED open
open:		jsr close		;close the device
		lda _parm2
		sta _sptr
		lda _parm2+1
		sta _sptr+1
		jsr _toascii
		lda _parm1
		jsr _getdev	 ;dev = dev * 16
		lda #3
		sta _iccom,x
		lda #_asciistr&$ff
		sta _icbal,x
		lda #_asciistr/256
		sta _icbah,x
		lda #80
		sta _icbll,x
		lda #0
		sta _icblh,x
		lda _parm3
		sta _icax1,x
		lda _parm4
		sta _icax2,x
		jsr _CIO
		bpl .ok
.err:		lda #0
		beq .exit
.ok:		lda #1
.exit:		ldx #0
		rts
	.ENDIF




	.IF_REFERENCED blockread
blockread:	lda _parm3
		ora _parm3+1
		bne .ok
		ldy #0
		jmp .error
.ok:		lda _parm1
		jsr _getdev	 ;dev = dev * 16
		lda #7
		sta _iccom,x
		lda _parm2
		sta _icbal,x
		lda _parm2+1
		sta _icbah,x
		lda _parm3
		sta _icbll,x
		lda _parm3+1
		sta _icblh,x
		jsr _CIO
		bmi .error
.noerror:	lda _icbll,x
		pha
		lda _icblh,x	 ;get lth actually read in
		tax
		pla
		rts
.error: 	cpy #136		;EOF is ok..
		beq .noerror
		lda #0
		ldx #0
		rts
	.ENDIF



	.IF_REFERENCED blockwrite
blockwrite: lda _parm3
		ora _parm3+1
		bne .ok
		jmp .error
.ok:		lda _parm1
		jsr _getdev	 ;dev = dev * 16
		lda #11
		sta _iccom,x
		lda _parm2
		sta _icbal,x
		lda _parm2+1
		sta _icbah,x
		lda _parm3
		sta _icbll,x
		lda _parm3+1
		sta _icblh,x
		jsr _CIO
		bmi .error
.noerror:	lda _icbll,x
		pha
		lda _icblh,x	 ;get lth actually read in
		tax
		pla
		rts
.error: 	lda #0
		ldx #0
		rts
	.ENDIF


	.IF_REFERENCED point
point:		lda _parm1
		jsr _getdev
		lda #37
		sta _iccom,x
		lda _parm2
		sta $34c,x
		lda _parm3
		sta $34d,x
		lda _parm4
		sta $34e,x
		jsr _CIO
		bpl .ok
.err:		lda #0
		beq .exit
.ok:		lda #1
.exit:		ldx #0
		rts
	.ENDIF



	.IF_REFERENCED close
close:		lda _parm1
		jsr _getdev
		lda #12
		sta _iccom,x
		jsr _CIO
		bpl .ok
.err:		lda #0
		beq .exit
.ok:		lda #1
.exit:		ldx #0
		rts
	.ENDIF



	.IF_REFERENCED inputs
inputs: 	lda _parm1			; inputs (string)
		ldx _parm1+1
		sta _parm2
		stx _parm2+1
		lda #0
		sta _parm1
		sta _parm1+1
		jmp inputsd
	.ENDIF


	.IF_REFERENCED inputsd
inputsd:	lda _parm1
		jsr _getdev	 ;dev = dev * 16
		lda #5
		sta _iccom,x
		lda _parm2
		clc
		adc #1
		sta _icbal,x
		lda _parm2+1
		adc #0
		sta _icbah,x
		lda #100
		sta _icbll,x
		lda #0
		sta _icblh,x
		jsr _CIO
		bmi .error
.noerror:	lda _icbll,x	 ;get lth actually read in
		sec
		sbc #1		; minus 1
		ldy #0
		sta (_parm2),y	 ; and place it in length byte
		lda #1
		ldx #0
		rts
.error: 	lda #0
		ldx #0
		rts
	.ENDIF




	.IF_REFERENCED fdelete
fdelete:	lda #33
		ldx #0
		ldy #0
		jmp __xio
	.ENDIF

	.IF_REFERENCED frename
frename:	lda #32
		ldx #0
		ldy #0
		jmp __xio
	.ENDIF


	.IF_REFERENCED flock
flock:		lda #34
		ldx #0
		ldy #0
		jmp __xio
	.ENDIF

	.IF_REFERENCED fprotect
fprotect:	lda #35
		ldx #0
		ldy #0
		jmp __xio
	.ENDIF

	.IF_REFERENCED funprotect
funprotect: lda #36
		ldx #0
		ldy #0
		jmp __xio
	.ENDIF

	.IF_REFERENCED funlock
funlock:	lda #46
		ldx #0
		ldy #0
		jmp __xio
	.ENDIF

	.IF_REFERENCED fcredir
fcredir:	lda #42
		ldx #0
		ldy #0
		jmp __xio
	.ENDIF

	.IF_REFERENCED fdeldir
fdeldir:	lda #43
		ldx #0
		ldy #0
		jmp __xio
	.ENDIF

	.IF_REFERENCED fcwd
fcwd:		lda #44
		ldx #0
		ldy #0
		jmp __xio
	.ENDIF

	.IF_REFERENCED fainit
fainit: 	lda #254
		ldx #0
		ldy #0
		jmp __xio
	.ENDIF




;======================================================================
;		Low level Input and Output functions
;======================================================================


	.IF_REFERENCED __xio
__xio:		sta .cmd		;cmd -> A, ax1 -> X, ax2 -> Y
		stx .ax1
		sty .ax2
		jsr freeiocb
		cmp #0
		bne .gotone
		jmp .err
.gotone:	sta .device
		lda _parm1
		sta _sptr
		lda _parm1+1
		sta _sptr+1
		jsr _toascii
		lda .device
		jsr _getdev	 ;dev = dev * 16
		lda .cmd
		sta _iccom,x
		lda #_asciistr&$ff
		sta _icbal,x
		lda #_asciistr/256
		sta _icbah,x
		lda #128
		sta _icbll,x
		lda #0
		sta _icblh,x
		lda .ax1
		sta _icax1,x
		lda .ax2
		sta _icax2,x
		jsr _CIO
		tya
		ldx #0
		rts
.err:		lda #0
		ldx #0
		rts
.device:	ds.b	1
.cmd:		ds.b	1
.ax1:		ds.b	1
.ax2:		ds.b	1
	.ENDIF


	.IF_REFERENCED freeiocb

freeiocb:	ldx #$10		;find a free IOCB; return in A
		ldy #1
.loop:		lda _ichid,x
		cmp #$ff		;free?
		beq .gotone
		txa
		clc
		adc #$10
		tax
		iny
		cpy #8
		bcc .loop
.none:		lda #0		;none free!
		ldx #0
		rts
.gotone:	tya
		ldx #0
		rts
	.ENDIF

	.IF_REFERENCED __putstr
__putstr:	stx .device		; device -> X, string -> A,Y
		sta _sptr
		sty _sptr+1
		ldy #0
		lda (_sptr),y		;get length byte
		sta _freslo		;use freslo as length byte
		iny			;move to first byte of string
		sty _freshi		;use freshi as length pointer
.loop:		ldy _freshi
		cpy _freslo		;done yet?
		bcc .notdone
		beq .notdone
		rts
.notdone:	lda (_sptr),y		;get byte
		ldx .device		;get device
		jsr __putchar
		bmi .exit		;exit with MINUS if error
		inc _freshi
		bne .loop
.exit:		rts
.device:	ds.b	1
	.ENDIF


	.IF_REFERENCED __putnum
__putnum:	stx .device		; device -> X, number -> A,Y
		sta _fr0
		sty _fr0+1
		jsr _ifp			;float it
		jsr _fasc			;to ascii
		ldy #0
.loop:		lda (_inbuff),y
		sta .saveb
		and #$7f			;last byte is negative
		ldx .device
		sty .tempy
		jsr __putchar
		bmi .exit		;exit with MINUS on error
		ldy .tempy
		iny
		lda .saveb
		bpl .loop
		lda #0		;clear MINUS flag
.exit:		rts
.tempy: 	ds.b	1
.device:	ds.b	1
.saveb: 	ds.b	1
	.ENDIF

	.IF_REFERENCED __putfloat
__putfloat: stx .device 		; device -> X, fp @ -> A,Y
		tax
		jsr _fld0r			;load into fr0
		jsr _fasc			;to ascii
		ldy #0
.loop:		lda (_inbuff),y
		sta .saveb
		and #$7f			;last byte is negative
		ldx .device
		sty .tempy
		jsr __putchar
		bmi .exit		;exit with MINUS on error
		ldy .tempy
		iny
		lda .saveb
		bpl .loop
		lda #0		;clear MINUS flag
.exit:		rts
.tempy: 	ds.b	1
.device:	ds.b	1
.saveb: 	ds.b	1
	.ENDIF


	.IF_REFERENCED __puthex
__puthex:	stx .device		; device -> X, number -> A,Y
		sta .lo
		sty .hi
		lda .hi
		lsr
		lsr
		lsr
		lsr
		jsr .out
		lda .hi
		and #$0f
		jsr .out
		lda .lo
		lsr
		lsr
		lsr
		lsr
		jsr .out
		lda .lo
		and #$0f
		jsr .out
		lda #0		;clear MINUS flag
		rts

.out:		tay
		lda .digits,y
		ldx .device
		jsr __putchar
		bmi .error
		rts
.error: 	sty .tempy
		pla
		pla
		ldy .tempy
		rts

.tempy: 	ds.b	1
.device:	ds.b	1
.lo:		ds.b	1
.hi:		ds.b	1
.digits:	dc.b	"0123456789ABCDEF"
	.ENDIF



	.IF_REFERENCED __putchar
__putchar:	pha		  ; char -> A,	device -> X
		txa
		asl
		asl
		asl
		asl
		tax
		lda #11
		sta _iccom,x
		lda #0
		sta _icbll,x
		sta _icblh,x
		pla
		jmp _CIO
	.ENDIF


	.IF_REFERENCED __getchar
__getchar:	txa		  ; device -> X
		asl
		asl
		asl
		asl
		tax
		lda #7
		sta _iccom,x
		lda #0
		sta _icbll,x
		sta _icblh,x
		jmp _CIO
	.ENDIF



;======================================================================
;		Miscellaneous functions and procs
;======================================================================


;	call an assembler routine
;	-------------------------

	.IF_REFERENCED call

call:		sta .go+1
		stx .go+2
.go:		jmp $ffff

	.ENDIF



	.IF_REFERENCED keypressed
keypressed: lda 764
		cmp #$ff
		beq .no
.yes:		lda #1
		bne .exit
.no:		lda #0
.exit:		ldx #0
		rts
	.ENDIF


;	   strcpy (dest, source)
;	   ---------------------

	.IF_REFERENCED scopy
scopy:		jmp strcpy
	.ENDIF


	.IF_REFERENCED strcpy

strcpy: 	jsr _loadstr
		ldy #0
		lda (_dptr),y		;get lth byte
		tay			;go backwards
.loop:		lda (_dptr),y
		sta (_sptr),y
		cpy #0
		beq .done
		dey
		jmp .loop
.done:		rts
	.ENDIF


;	   strcmp  (string1, string2)
;	   strcmpi (string1, string2)
;	   -------------------------

	.IF_REFERENCED strcmp

strcmp: 	lda  #$80
		jmp  _cmpstr
	.ENDIF


	.IF_REFERENCED strcmpi
strcmpi:	lda  #0
		jmp _cmpstr
	.ENDIF


	.IF_REFERENCED _cmpstr

_cmpstr:	sta .dofold
		jsr _loadstr
		ldy #0		;zero index
		lda (_sptr),y	;get length byte
		sta .lth
.loop:		lda (_sptr),y	;get next byte
		bit .dofold
		bmi .nofold1
		jsr upcase
.nofold1:	sta .temp
		lda (_dptr),y	;they match?
		bit .dofold
		bmi .nofold2
		jsr upcase
.nofold2:	cmp .temp
		bne .noteq		;nope..
		cpy .lth		;end of string?
		beq .end		;yes -- they match
		iny
		bne .loop
.noteq: 	lda #1		;set BNE
		bne .exit
.end:		lda #0		;set BEQ
.exit:		ldx #0
		rts
.lth:		ds.b	1
.temp:		ds.b	1
.dofold:	ds.b	1
	.ENDIF


;	   strcat  (dest, source)
;	   ----------------------

	.IF_REFERENCED strcat

strcat: 	jsr _loadstr
		ldy #0
		lda (_dptr),y		;get source lth
		sta .srclth
		beq .end			;null string..exit
		lda (_sptr),y		;get dest lth
		sta .desty
		inc .srcy
		inc .desty
		ldy #1			;always start at 1 on
		sty .srcy			; the source string
.loop:		ldy .srcy
		lda (_dptr),y		;get byte from source
		ldy .desty
		sta (_sptr),y		;store into dest
		lda .srcy
		cmp .srclth		;end of string?
		beq .end			;yes
		inc .srcy
		inc .desty			;up indexes
		bne .loop			;and keep going
.end:		ldy #0
		lda (_sptr),y		;up the length byte
		clc			; of the dest string
		adc .srclth
		sta (_sptr),y
		rts
.srcy:		dc.b	1
.desty: 	dc.b	1
.srclth:	dc.b	1
	.ENDIF



;	x = valb (string)
;	x = valc (string)
;	~~~~~~~~~~~~~~~~~

	.IF_REFERENCED valb

valb:		jmp valc
	.ENDIF

	.IF_REFERENCED valc

valc:		lda _parm1
		sta _sptr
		lda _parm1+1
		sta _sptr+1
		jsr _toascii		;convert to asciiz string
		lda #_asciistr&$ff
		sta _inbuff
		lda #_asciistr/256
		sta _inbuff+1
		lda #0
		sta _cix
		jsr _afp			 ;ascii --> floating pt.
		bcs .default
		jsr _fpi			 ;floating --> integer
		bcs .default
		lda _fr0
		ldx _fr0+1
		rts
.default:	lda #0
		tax
		rts
	.ENDIF



;	call an action-type routine
;	---------------------------

	.IF_REFERENCED action

action: 	sta .go+1
		stx .go+2
.go:		jsr $ffff
		lda _freslo
		ldx _freshi
		rts
	.ENDIF



	.IF_REFERENCED _add

_add:		sta _oper2
		stx _oper2+1
		lda _oper1
		clc
		adc _oper2
		sta _oper1
		lda _oper1+1
		adc _oper2+1
		tax
		lda _oper1
		rts
	.ENDIF


	.IF_REFERENCED _subtract

_subtract:	sta _oper2
		stx _oper2+1
		lda _oper1
		sec
		sbc _oper2
		sta _oper1
		lda _oper1+1
		sbc _oper2+1
		tax
		lda _oper1
		rts
	.ENDIF


	.IF_REFERENCED _multiply

_multiply:	sta _oper2
		stx _oper2+1
		lda #0
		sta	_fr0
		sta	_fr0+1
.loop:		lda	_oper2
		ora	_oper2+1
		beq	.done
		lda	_fr0
		clc
		adc	_oper1
		sta	_fr0
		lda	_fr0+1
		adc	_oper1+1
		sta	_fr0+1
		dec	_oper2
		lda	_oper2
		cmp	#$ff
		bne	.loop
		dec	_oper2+1
		jmp	.loop
.done:		lda	_fr0
		ldx	_fr0+1
		rts
	.ENDIF



	.IF_REFERENCED _divide

_divide:	sta _oper2
		stx _oper2+1
		ora _oper2+1		;must catch divide by zero!
		beq .moddone
		lda #0
		sta .result
		sta .result+1
.modloop:	lda _oper2+1		;while (oper2 <= oper1)
		cmp _oper1+1		;	oper1 -= oper2
		bcc .modok
		beq .cklow
		bcs .moddone
.cklow: 	lda _oper2
		cmp _oper1
		beq .modok
		bcs .moddone
.modok: 	lda _oper1
		sec
		sbc _oper2
		sta _oper1
		lda _oper1+1
		sbc _oper2+1
		sta _oper1+1
		inc .result
		bne .novf1
		inc .result+1
.novf1:		jmp .modloop
.moddone:	lda .result
		ldx .result+1
		rts
.result:	ds.b	2
	.ENDIF




;	.IF_REFERENCED _divide
;
;_divide:	sta _oper2
;		stx _oper2+1
;		lda _oper2
;		sta _fr0
;		lda _oper2+1
;		sta _fr0+1
;		jsr _ifp
;		jsr _fmove
;		lda _oper1
;		sta _fr0
;		lda _oper1+1
;		sta _fr0+1
;		jsr _ifp
;		jsr _fdiv
;		bcs	.error
;		jsr _fpi
;		bcs	.error
;		lda _fr0
;		ldx _fr0+1
;		rts
;.error:	lda	#0
;		tax
;		rts
;	.ENDIF


	.IF_REFERENCED _and

_and:		sta _oper2
		stx _oper2+1
		lda _oper1
		and _oper2
		sta _oper1
		lda _oper1+1
		and _oper2+1
		tax
		lda _oper1
		rts
	.ENDIF



	.IF_REFERENCED _or

_or:		sta _oper2
		stx _oper2+1
		lda _oper1
		ora _oper2
		sta _oper1
		lda _oper1+1
		ora _oper2+1
		tax
		lda _oper1
		rts
	.ENDIF


	.IF_REFERENCED _xor

_xor:		sta _oper2
		stx _oper2+1
		lda _oper1
		eor _oper2
		sta _oper1
		lda _oper1+1
		eor _oper2+1
		tax
		lda _oper1
		rts
	.ENDIF



	.IF_REFERENCED _mod

_mod:		sta _oper2
		stx _oper2+1
.modloop:	lda _oper2+1		;while (oper2 <= oper1)
		cmp _oper1+1		;	oper1 -= oper2
		bcc .modok
		beq .cklow
		bcs .moddone
.cklow: 	lda _oper2
		cmp _oper1
		beq .modok
		bcs .moddone
.modok: 	lda _oper1
		sec
		sbc _oper2
		sta _oper1
		lda _oper1+1
		sbc _oper2+1
		sta _oper1+1
		jmp .modloop
.moddone:	lda _oper1
		ldx _oper1+1
		rts
	.ENDIF



	.IF_REFERENCED _lshift

_lshift:	tay
		cpy #0
		beq .exit
.cont:		asl _oper1
		rol _oper1+1
		dey
		bne .cont
.exit:		lda _oper1
		ldx _oper1+1
		rts
	.ENDIF


	.IF_REFERENCED _rshift

_rshift:	tay
		cpy #0
		beq .exit
.cont:		lsr _oper1+1
		ror _oper1
		dey
		bne .cont
.exit:		lda _oper1
		ldx _oper1+1
		rts
	.ENDIF


	.IF_REFERENCED isdigit

isdigit:	cmp #'0'
		bcc .no
		cmp #'9'+1
		bcs .no
		lda #1
		bne .exit
.no:		lda #0
.exit:		ldx #0
		rts
	.ENDIF


	.IF_REFERENCED isalpha

isalpha:	jsr upcase
		cmp #'A'
		bcc .no
		cmp #'Z'+1
		bcs .no
		lda #1
		bne .exit
.no:		lda #0
.exit:		ldx #0
		rts
	.ENDIF


	.IF_REFERENCED islower

islower:	cmp #'a'
		bcc .no
		cmp #'z'+1
		bcs .no
		lda #1
		bne .exit
.no:		lda #0
.exit:		ldx #0
		rts
	.ENDIF





	.IF_REFERENCED zero

zero:		lda #0
		sta _parm3			;parms 1/2 already there
		jmp setblock
	.ENDIF



	.IF_REFERENCED setblock

setblock:	lda _parm1			; setblock (dest,size,val)
		clc
		adc _parm2
		sta _parm2
		lda _parm1+1
		adc _parm2+1
		sta _parm2+1
		ldy #0
		lda _parm3
.move:		sta (_parm1),y
		inc _parm1
		bne .ov1
		inc _parm1+1
.ov1:		ldx _parm1+1
		cpx _parm2+1
		bcc	.move
		ldx _parm1
		cpx _parm2
		bcc .move
		rts
	.ENDIF


	.IF_REFERENCED moveblock

moveblock:	lda _parm2		 ; MoveBlock (char *dest,*src; card size)
		clc
		adc _parm3
		sta _parm3
		lda _parm2+1
		adc _parm3+1
		sta _parm3+1
		ldy #0
.move:		lda (_parm2),y
		sta (_parm1),y
		inc _parm2
		bne .ov1
		inc _parm2+1
.ov1:		inc _parm1
		bne .ov2
		inc _parm1+1
.ov2:		lda _parm2+1
		cmp _parm3+1
		bne .move
		lda _parm2
		cmp _parm3
		bcc .move
		rts
	.ENDIF



	.IF_REFERENCED pos


pos:		ldy #0
		lda (_parm1),y
		sta .s_lth
		lda (_parm2),y
		sta .d_lth
		lda _parm1
		sta .comp+1
		lda _parm1+1
		sta .comp+2
		lda _parm2
		sta .get+1
		lda _parm2+1
		sta .get+2
		lda #1
		sta .loc
		ldy #0
		ldx #0
		jsr .up_str
		jsr .up_sub
.comp:		lda $ffff,y
		jsr upcase
		sta .temp
.get:		lda $ffff,x
		jsr upcase
		cmp .temp
		beq .match
.nomatch:	ldx #1
		inc .loc
		jsr .up_str
		jmp .comp
.match: 	jsr .up_sub
		jsr .up_str
		jmp .comp
.up_str:	iny
		cpy .s_lth
		bcc .xup
		beq .xup
		pla
		pla
		lda #0
		ldx #0
.xup:		rts
.up_sub:	inx
		cpx .d_lth
		bcc .xsub
		beq .xsub
		pla
		pla
		lda .loc
		ldx #0
.xsub:		rts
.temp:		dc.b	0
.loc:		dc.b	0
.s_lth: 	dc.b	0
.d_lth: 	dc.b	0
	.ENDIF



	.IF_REFERENCED isupper

isupper:	cmp #'A'
		bcc .no
		cmp #'Z'+1
		bcs .no
		lda #1
		bne .exit
.no:		lda #0
.exit:		ldx #0
		rts
	.ENDIF


	.IF_REFERENCED eof

eof:		jsr _getdev		;dev = dev * 16
		lda _icstat,x
		cmp #136
		beq .goteof
.noteof:	lda #0
		beq .exit
.goteof:	lda #1
.exit:		ldx #0
		rts
	.ENDIF


	.IF_REFERENCED halt

halt:		lda #1
		sta .idx
.closem:	lda .idx
		sta _parm1
		jsr close
		inc .idx
		lda .idx
		cmp #8
		bcc .closem
		ldx #$ff
		txs
		jmp ($0a)
.idx:		ds.b	1

	.ENDIF

	.IF_REFERENCED toupper

toupper:	jmp upcase
	.ENDIF


	.IF_REFERENCED upcase

upcase: 	cmp #'a'
		bcc .xupcase
		cmp #'z'+1
		beq .xupcase
		bcs .xupcase
		sec
		sbc #32
.xupcase:	rts
	.ENDIF


	.IF_REFERENCED tolower

tolower:	jmp locase
	.ENDIF


	.IF_REFERENCED locase

locase: 	cmp #'A'
		bcc .xlocase
		cmp #'Z'+1
		beq .xlocase
		bcs .xlocase
		clc
		adc #32
.xlocase:	rts
	.ENDIF




	.IF_REFERENCED _loadstr
_loadstr:	lda _parm1
		sta _sptr
		lda _parm1+1
		sta _sptr+1
		lda _parm2
		sta _dptr
		lda _parm2+1
		sta _dptr+1
		rts
	.ENDIF


	.IF_REFERENCED strc
strc:		jmp __itostr
	.ENDIF

	.IF_REFERENCED strb
strb:		jmp __itostr
	.ENDIF

	.IF_REFERENCED __itostr
__itostr:	lda _parm1
		sta _fr0
		lda _parm1+1
		sta _fr0+1
		jsr _ifp			;float it
		jsr _fasc			;to ascii
		ldy #0
.loop:		lda (_inbuff),y 	;get a byte
		php
		and #$7f			;last byte is negative
		iny
		sta (_parm2),y		;put it in string
		plp
		bpl .loop
		tya
		ldy #0
		sta (_parm2),y		;set length byte
		rts
	.ENDIF



;======================================================================
;		Floating-point support routines
;======================================================================

;	int_val = ftoi(fp_number)

	.IF_REFERENCED ftoi
ftoi:		ldx _parm1			;fp --> integer
		ldy _parm1+1
		jsr _fld0r			;load to fr0
		jsr _fpi			;to integer
		bcs .zero			;error!
		lda _fr0
		ldx _fr0+1
		rts
.zero:		lda #0
		tax
		rts
	.ENDIF


;	ftostr (fp_number, string)

	.IF_REFERENCED ftostr
ftostr: 	ldx _parm1
		ldy _parm1+1 
		jsr _fld0r
		jsr _fasc			;to ascii
		ldy #0
.loop:		lda (_inbuff),y 	;get a byte
		php
		and #$7f			;last byte is negative
		iny
		sta (_parm2),y		;put it in string
		plp
		bpl .loop
		tya
		ldy #0
		sta (_parm2),y		;set length byte
		rts
	.ENDIF



;	strtof (string, fp_number)

	.IF_REFERENCED strtof

strtof: 	lda _parm1
		sta _sptr
		lda _parm1+1
		sta _sptr+1
		jsr _toascii		;convert to asciiz string
		lda #_asciistr&$ff
		sta _inbuff
		lda #_asciistr/256
		sta _inbuff+1
		lda #0
		sta _cix
		jsr _afp			;ascii --> floating pt.
		bcs .default
		ldx _parm2
		ldy _parm2+1
		jsr _fst0r			;store it
		rts
.default:	ldy #0			;error occurred, so
		tya			; just zero it out
.deflp: 	sta (_parm2),y
		iny
		cpy #6
		bne .deflp
		rts
	.ENDIF


;	itof (int_number, fp_number)

	.IF_REFERENCED itof
itof:		lda _parm1			;int --> fp
		sta _fr0
		lda _parm1+1
		sta _fr0+1
		jsr _ifp
		ldx _parm2
		ldy _parm2+1
		jsr _fst0r			;store it
		rts
	.ENDIF


;	fadd (target_fp, fp1, fp2)

	.IF_REFERENCED fadd
fadd:		jsr __setfr01		;set up registers
		jsr _fadd
		ldx _parm1
		ldy _parm1+1
		jsr _fst0r			;store it
		rts
	.ENDIF

	.IF_REFERENCED fsub
fsub:		jsr __setfr01		;set up registers
		jsr _fsub
		ldx _parm1
		ldy _parm1+1
		jsr _fst0r			;store it
		rts
	.ENDIF


;	fdiv (target_fp, fp1, fp2)

	.IF_REFERENCED fdiv
fdiv:		jsr __setfr01		;set up registers
		jsr _fdiv
		ldx _parm1
		ldy _parm1+1
		jsr _fst0r			;store it
		rts
	.ENDIF

;	fmult (target_fp, fp1, fp2)

	.IF_REFERENCED fmult
fmult:		jsr __setfr01		;set up registers
		jsr _fmult
		ldx _parm1
		ldy _parm1+1
		jsr _fst0r			;store it
		rts
	.ENDIF

;	fsub (target_fp, fp1, fp2)

;	fmove (target_fp, source_fp)

	.IF_REFERENCED fmove
fmove:		ldy #0
.loop:		lda (_parm2),y		;just move 6 bytes
		sta (_parm1),y
		iny
		cpy #6
		bne .loop
		rts
	.ENDIF

;	fzero (fp_number);

	.IF_REFERENCED fzero
fzero:		ldy #0
		tya
.loop:		sta (_parm1),y
		iny
		cpy #6
		bne .loop
		rts
	.ENDIF


;	result = fcompare (fp1, fp2);
;
;	returns: 0 = match, 1 = fp1 > fp2, 2 = fp2 > fp1

	.IF_REFERENCED fcompare
fcompare:	ldy #0
		lda (_parm1),y
		and #$80
		sta .exp1
		lda (_parm2),y
		and #$80
		sta .exp2
		lda .exp1
		cmp .exp2
		beq .samesign		;signs match
		bcc .ex1gr			;fp1 is greater
		jmp .ex2gr			;fp2 is greater
.ex1gr: 	lda #1
		jmp .exit
.ex2gr: 	lda #2
		jmp .exit
.samesign:	lda (_parm1),y
		and #$7f
		sta .exp3
		lda (_parm2),y
		and #$7f
		sta .exp4
		lda .exp3
		cmp .exp4
		beq .sameexp		;exponents match
		bcc .fp2gr			;fp2 is greater
		jmp .fp1gr			;fp1 is greater

;	exponents match, so go thru the mantissa comparing bytes

.sameexp:	ldy #1
.seloop:	lda (_parm1),y		;compare next byte
		cmp (_parm2),y
		beq .nxtbyt
		bcc .fp2gr
		bcs .fp1gr
.nxtbyt:	iny
		cpy #6
		bne .seloop
.equal: 	lda #0			;they equal!
		beq .exit
.fp1gr: 	lda .exp1			;if minus, then reverse
		bpl .fp1ok
		lda #2
		bne .exit
.fp1ok: 	lda #1
		bne .exit
.fp2gr: 	lda .exp1			;if minus, then reverse
		bpl .fp2ok
		lda #1
		bne .exit
.fp2ok: 	lda #2
.exit:		ldx #0
		rts
.exp1:		ds.b	1
.exp2:		ds.b	1
.exp3:		ds.b	1
.exp4:		ds.b	1
	.ENDIF

;	negative (fp1);
;
;	returns: 1 = it's negative, 0 = it's positive

	.IF_REFERENCED negative
negative:	ldy #0
		lda (_parm1),y
		and #$80
		bne .neg
.pos:		lda #0
		beq .exit
.neg:		lda #1
.exit:		ldx #0
		rts
	.ENDIF


	.IF_REFERENCED __setfr01
__setfr01:	ldx _parm2
		ldy _parm2+1
		jsr _fld0r
		ldx _parm3
		ldy _parm3+1
		jsr _fld1r
		rts
	.ENDIF


	.IF_REFERENCED _toascii

_toascii:	ldy #0
		lda (_sptr),y		;get lth byte
		sta .lth
		beq .null
		iny
		inc .lth
.loop:		lda (_sptr),y
		dey
		sta _asciistr,y
		iny
		iny
		cpy .lth
		bne .loop
.done:		ldy .lth
		dey
.rtn:		lda #$9b
		sta _asciistr,y
		rts
.null:		ldy #0
		beq .rtn

.lth:		dc.b	1

	.ENDIF


	.IF_REFERENCED call_cio
call_cio:	lda _parm1
		jsr _getdev	;dev = dev * 16
		tax		;put it in X
		jsr _CIO
		tya		;return status
		ldx #0
		rts
	.ENDIF


	.IF_REFERENCED end_of_program
end_of_program: lda #__EOP & $ff
		ldx #__EOP / 256
		rts
	.ENDIF



;	.IF_REFERENCED load_bbs			 ;load BBS routines if needed
;
;		.include   bbs_c65
;
;	.ENDIF

