#asm
; ZSC-COMP.LIB  -  SUPPORT ROUTINES FOR SMALL-C COMPILER
;	Supplemented with routines from Mike Bernson's version
;
;
;
;  DEFINITIONS
;
CR EQU 0DH
LF EQU 0AH
BS EQU 08
DEL EQU 7FH
CZ EQU 1AH
ESC EQU 1BH
IOBYTE EQU 3
CURDSK EQU 4
BDOS EQU 5
FCB EQU 5CH
OUTBUF EQU 80H
;
; cpm
;
cpm: POP HL
 POP BC
 POP DE
 PUSH DE
 PUSH BC
 PUSH HL
 CALL 5
 JP ccsxt
;
; putc.
;
putc: POP BC 
 POP DE 
 POP HL 
 PUSH HL
 PUSH DE
 PUSH BC
 LD A,(CONFLG) 
 CP 1
 LD A,L 
 JP NZ,WNB 
 JP ATOVDU 
;
; getc - GET BYTE FROM READ (CH 2) OR INCLUDE (3)
;
getc: POP BC
 POP HL
 PUSH HL
 PUSH BC
 LD A,L
 CP 2 
 JP NZ,GETC3 
 CALL GNB1K
GETC1: CP CZ 
 JP NZ,GETC2
 LD A,0FFH 
GETC2: JP ccsxt
GETC3: CALL GNB1KB
 JP GETC1 
;
; gets
;
gets: POP HL
 POP DE 
 PUSH DE
 PUSH HL
 CALL INLIN 
 EX DE,HL
 RET
;
;    OPEN FILE
; ONLY 3 SORTS NEEDED 
; 1. WRITE FILE USING THE STANDARD CPM FCB AND BUFFER (CHANNEL 1)
;    CAN BE CON:OR LST:
; 2. MAIN READ USING FCBI1K AND 1K I/P BUFFER (CHANNEL 2)
; 3. #INCLUDE READ USING FCBIB1K AND 1K BUFFER (CHANNEL 3)
;
fopen: POP BC
 POP DE 
 POP HL 
 PUSH HL
 PUSH DE
 PUSH BC
 LD A,(DE)
 AND 5FH 
 CP 'W'
 JP NZ,FOPEN1
 LD DE,1 
 PUSH DE 
 JP FOPEN4 
FOPEN1: CP 'R' 
 JP NZ,FOPEN2 
 LD DE,2 
 LD A,E
 PUSH DE
 LD DE,FCBI1K
 JP FOPEN7
FOPEN2: CP 'I'
 JP Z,FOPEN3
 LD HL,0 
 RET
FOPEN3: LD DE,3
 LD A,E
 PUSH DE 
 LD DE,FCBIB1K
 JP FOPEN7
FOPEN4: PUSH HL 
 LD DE,CONSTR 
 CALL COMPSTR
 JP Z,FOPEN5
 POP HL
 PUSH HL
 LD DE,LSTSTR
 CALL COMPSTR
 JP NZ,FOPEN6
 LD A,1
FOPEN5: LD (LSTFLAG),A
 POP DE 
 POP HL
 LD A,L
 LD (CONFLG),A 
 RET 
FOPEN6: POP HL 
 LD DE,FCB
 LD A,1 
FOPEN7: CALL SETFCB 
 CP 1 
 JP NZ,FOPEN8 
FOPEN7A: PUSH DE
 LD DE,OUTBUF 
 CALL SETDMA
 POP DE
 CALL DELFIL 
 CALL CREATFL 
 JP Z,DIRFUL 
 XOR A 
 LD (OBP),A
 POP HL 
 RET
FOPEN8: POP HL ;CHAN NO
 PUSH HL
 PUSH DE
 LD A,L
 CP 2
 JP NZ,FOPEN9
 LD DE,IBUF1K
 CALL SETDMA
 POP DE
 CALL OPENFL 
 JP Z,NOFILE
 LD HL,IBUF1K+1024
 LD (IBP1K),HL 
 POP HL
 RET
FOPEN9: LD DE,IBUF1KB
 CALL SETDMA
 POP DE
 CALL OPENFL
 JP Z,NOFILE
 LD HL,IBUF1KB+1024
 LD (IBP1KB),HL
 POP HL
 RET
;
COMPSTR: LD B,4
COMPST1: LD A,(HL)
 CALL CAPSET ;CONVERT TO U/C
 EX DE,HL
 CP (HL)
 EX DE,HL
 RET NZ ;MATCH FAILED
 INC HL
 INC DE
 DEC B
 JP NZ,COMPST1
 XOR A ;SET Z AND SET A TO 0
 RET
;
; fclose
;
fclose: POP BC
 POP HL
 PUSH HL
 PUSH BC
 LD A,L 
 CP 1
 RET NZ 
 LD A,(CONFLG)
 CP 1
 JP Z,FCLOS1 
 LD A,CZ 
 CALL WNB
 LD DE,OUTBUF
 CALL SETDMA
 LD DE,FCB
 CALL DWRITE 
 CALL CLOSEFL 
FCLOS1: XOR A
 LD (LSTFLAG),A 
 LD (CONFLG),A
 RET
;
; SET FCB. ENTER WITH DE->FCB, HL->FILENAME, A NEEDS PRESERVING
;
SETFCB: PUSH AF
 PUSH HL
 PUSH DE
 CALL CLEAR
 POP DE 
 POP HL 
 PUSH DE
 LD (FNSTORE),HL
 CALL SCRUB
SETFCB1: INC HL
 LD A,(HL)
 CP ':' 
 DEC HL
 JP NZ,SETFCB2 
 LD A,(HL)
 CALL CAPSET
 SUB '@'
 LD (DE),A
 INC HL
 INC HL
 JP SETFCB3
SETFCB2: XOR A 
 LD (DE),A
SETFCB3: INC DE
 LD B,8
SETFCB4: CALL SCRUB
 LD A,(HL)
 CALL CAPSET 
 CP '.'
 JP Z,SETFCB5 
 CP 0
 JP Z,SETFCB7
 LD (DE),A
 INC HL
 INC DE
 DEC B
 JP NZ,SETFCB4
SETFCB5: CALL SCRUB
 LD A,(HL)
 CP 0 
 JP Z,SETFCB7 
 CP 20H
 JP Z,SETFCB7
 CP '.'
 INC HL
 JP NZ,SETFCB5 
 LD B,3
 POP DE 
 PUSH DE
 PUSH HL
 LD HL,9
 ADD HL,DE
 EX DE,HL
 POP HL
SETFCB6: CALL SCRUB
 LD A,(HL)
 CALL CAPSET
 CP 0
 JP Z,SETFCB7
 LD (DE),A
 INC HL
 INC DE
 DEC B
 JP NZ,SETFCB6
SETFCB7: POP DE 
 POP AF
 RET
;
; Scrub out '<','"', and '>' from file name
;
SCRUB: LD A,(HL)
 CP ' '
 JR NZ,SCRUB1
 INC HL
 JR SCRUB
SCRUB1: CP '"'
 JR NZ,SCRUB2
 INC HL
 JR SCRUB
SCRUB2: CP '<'
 JR NZ,SCRUB3
 INC HL
 JR SCRUB
SCRUB3: CP '>'
 JR NZ,SCRUB4
 INC HL
 JR SCRUB
SCRUB4: CP 27H ;"'"
 RET NZ
 INC HL
 JR SCRUB
; 
CLEAR: PUSH DE
 POP HL
 LD (HL),0 
 INC HL
 LD A,20H
 LD B,11
CLEAR1: LD (HL),A
 INC HL
 DEC B
 JP NZ,CLEAR1
 XOR A
 LD (HL),A 
 LD HL,20H
 ADD HL,DE
 LD (HL),A
 RET
;
CAPSET: CP 61H ;'a'
 RET C
 CP 7BH ;'z'+1
 RET NC
 SUB 20H
 RET
;
DIRFUL: CALL PFILE 
 LD DE,DFLMSG
DIRFUL1: CALL PMESS
 JP 0 ;Exit to CP/M
;
NOFILE: CALL PFILE
 LD DE,NOFLMSG
 JP DIRFUL1
;
; 
CONSTR: DEFB 'CON:'
LSTSTR: DEFB 'LST:'
NOFLMSG:  DEFB ' - No such file'
 DEFW 0A0DH
 DEFB '$'
DFLMSG:  DEFB ' - Directory full'
 DEFW 0A0DH
 DEFB '$'
;
;PRINT OUT FILE NAME POINTED TO BY (FNSTORE) 
;
PFILE: PUSH HL
 CALL crlf
 LD HL,(FNSTORE)
PFILE1: LD A,(HL)
 CP 0
 JR Z,PFILE2
 CALL ATOVDU
 INC HL
 JR PFILE1
PFILE2: 
 POP HL
 RET
;
; O/P FLAG BYTES
;
LSTFLAG: DEFB 0 ;LST: ON IF 1
CONFLG DEFB 0 ;FLAG TO SHOW CON: IS THE O/P FILE
FNSTORE: DEFS 2 ;Store pointer to file name
; 
ATOVDU: PUSH AF
 PUSH HL
 PUSH DE
 PUSH BC
 LD C,2
 LD E,A
 PUSH DE
 CALL BDOS
 POP DE
 LD C,5
 LD A,(LSTFLAG)
 CP 1 
 CALL Z,BDOS
 POP BC
 POP DE
 POP HL
 POP AF
 RET
;
; crlf
;
crlf: PUSH AF
 LD A,CR
 CALL ATOVDU
 LD A,LF
 CALL ATOVDU
 POP AF
 RET
;
VDUTOA: CALL CHARIN
 JP ATOVDU
;
CHARIN: PUSH HL
 PUSH DE
 PUSH BC
 LD HL,(1)
 LD DE,6
 ADD HL,DE
 LD DE,CHRIN1
 PUSH DE
 JP (HL)
CHRIN1: POP BC
 POP DE
 POP HL
 PUSH AF
 CP 3 
 JP Z,0 
 POP AF
 CP 10H 
 RET NZ
 PUSH HL
 LD HL,LSTFLAG
 LD A,1
 XOR (HL) 
 LD (HL),A
 POP HL
 JP CHARIN
;
INLIN: PUSH HL
 PUSH DE
 PUSH BC
 LD B,0 
 EX DE,HL
INLIN1: CALL CHARIN
 CP CR
 JP Z,INLIN3
 CP BS
 JP Z,INLIN2
 CP DEL
 JP Z,INLIN2
 PUSH AF
 LD A,4EH 
 CP B 
 JP Z,INLIN4
 POP AF
 CALL ATOVDU
 LD (HL),A
 INC HL
 INC B
 JP INLIN1
INLIN2: XOR A
 CP B 
 JP Z,INLIN1
 LD A,BS
 CALL ATOVDU
 DEC HL
 DEC B
 JP INLIN1
INLIN3: CALL crlf
 XOR A 
 LD (HL),A
 POP BC 
 POP DE 
 POP HL
 RET
INLIN4: LD A,BS 
 CALL ATOVDU 
 POP AF
 DEC HL
 CALL ATOVDU
 LD (HL),A
 INC HL
 JP INLIN1
;
; ASSORTED DISK ROUTINES - MANY BASED ON THOSE IN CPMUG VOL 16.
;
; ENTRY IS A GENERAL REGISTER SAVER FOR USE WITH BDOS CALLS
;
ENTRY: PUSH HL
 PUSH DE
 PUSH BC
 CALL 5
 POP BC
 POP DE
 POP HL
 RET
;
; DELFIL - DELETE FILE. FCB POINTED BY DE
;
DELFIL: PUSH BC
 LD C,19 ;DELETE
 CALL ENTRY
 POP BC ;NO EXIT CONDS
 RET
;
; PMESS - PRINTS OUT MESSAGE ->DE  UNTIL $
;
PMESS: PUSH AF
 PUSH BC
 LD C,9
 CALL ENTRY
 POP BC
 POP AF
 RET
;
; OPENFL  OPEN AN EXISTING FILE WHOSE FCB IS POINTED TO BY DE
;
OPENFL: PUSH HL
 PUSH BC
 LD HL,12
 ADD HL,DE
 LD (HL),0 
 LD HL,32
 ADD HL,DE
 LD (HL),0 
 LD C,15 
 CALL ENTRY
 CP 0FFH
 POP BC
 POP HL
 RET
;
; CLOSEFL - CLOSE FILE WHOSE FCB IS POINTED TO BY DE
;
CLOSEFL: PUSH BC
 LD C,16 
 CALL ENTRY
 POP BC
 CP 0FFH 
 RET
;
; CREATFL - CREATE FILE WHOSE FCB IS POINTED TO BY DE
;
CREATFL: PUSH BC
 LD C,22 
 CALL ENTRY
 CP 0FFH 
 POP BC
 RET
;
; SETDMA - SET DMA BUFFER TO ADDRESS IN DE
;
SETDMA: PUSH BC
 LD C,26 
 CALL ENTRY
 POP BC
 RET
;
; DREAD - READ A FILE SECTOR. DE POINTS TO FCB
;
DREAD: PUSH BC
 LD C,20 
 CALL ENTRY
 CP 0 
 POP BC
 RET
;
; DWRITE - WRITE A FILE SECTOR. DE POINTS TO FCB
;
DWRITE: PUSH BC
 LD C,21
 CALL ENTRY
 CP 0 
 POP BC
 RET
;
;  MAIN READ VERSION
; GNB1K - GET NEXT BYTE FROM 1K BUFFER. REFILL BUFF WHEN NEEDED
;
;  DEFINE BUFFERS ETC.
IBUF1K: DEFS 1024 ;I/P BUFF
IBP1K: DEFS 2 ;BUFFER POINTER
GBP1K: DEFS 2 ;TEMP BUFFER POINTER
FCBI1K: DEFB 0 ;FCB FOR BUFFERED FILE
 DEFS 35 ;REST OF FCB
;
GNB1K: PUSH HL
 PUSH DE
 LD HL,(IBP1K) 
 LD DE,IBUF1K+1024
 CALL DPCMP 
 POP DE
 POP HL
 JP NZ,GB1K2
 PUSH HL
 PUSH DE
 PUSH BC
 LD HL,IBUF1K 
 LD (GBP1K),HL
 LD B,8 
GB1K1: PUSH BC
 LD HL,(GBP1K)
 EX DE,HL
 CALL SETDMA
 LD DE,FCBI1K
 CALL DREAD 
 LD HL,(GBP1K)
 LD DE,128
 ADD HL,DE
 LD (GBP1K),HL
 POP BC
 DEC B
 JP NZ,GB1K1
 POP BC
 POP DE
 LD HL,IBUF1K 
 LD (IBP1K),HL
 POP HL
GB1K2: PUSH HL
 LD HL,(IBP1K)
 LD A,(HL)
 INC HL
 LD (IBP1K),HL
 POP HL
 CP 0AH 
 JP Z,GNB1K
 RET
;
; #INCLUDE VERSION
; GNB1KB - GET NEXT BYTE FROM 1K BUFFER. REFILL BUFF WHEN NEEDED
;
IBUF1KB: DEFS 1024 ;I/P BUFF
IBP1KB: DEFS 2 ;BUFFER POINTER
GBP1KB: DEFS 2 ;TEMP BUFFER POINTER
FCBIB1K: DEFB 0 ;FCB FOR BUFFERED FILE
 DEFS 35 ;REST OF FCB
;
GNB1KB: PUSH HL
 PUSH DE
 LD HL,(IBP1KB)
 LD DE,IBUF1KB+1024
 CALL DPCMP
 POP DE
 POP HL
 JP NZ,GB1KB2
 PUSH HL
 PUSH DE
 PUSH BC
 LD HL,IBUF1KB 
 LD (GBP1KB),HL 
 LD B,8 
GB1KB1: PUSH BC
 LD HL,(GBP1KB)
 EX DE,HL
 CALL SETDMA 
 LD DE,FCBIB1K
 CALL DREAD 
 LD HL,(GBP1KB)
 LD DE,128
 ADD HL,DE
 LD (GBP1KB),HL
 POP BC
 DEC B
 JP NZ,GB1KB1
 POP BC
 POP DE
 LD HL,IBUF1KB 
 LD (IBP1KB),HL
 POP HL
GB1KB2: PUSH HL 
 LD HL,(IBP1KB)
 LD A,(HL)
 INC HL
 LD (IBP1KB),HL
 POP HL
 CP 0AH 
 JP Z,GNB1KB
 RET
;
; WRITE NEXT BYTE TO FILE VIA STANDARD BUFFER AT 80H WITH THE
; STANDARD FCB.
;
WNB: PUSH HL
 PUSH DE
 PUSH AF
 LD A,(OBP)
 CP 80H
 JP NZ,WNB0
 LD DE,OUTBUF
 CALL SETDMA 
 LD DE,FCB
 CALL DWRITE 
 JP Z,WNB00 
 CALL PFILE
 LD DE,WERRMSG
 CALL PMESS
 JP 100H 
WERRMSG: DEFB ' Write Error'
 DEFW 0A0DH
 DEFB '$'
WNB00: XOR A 
WNB0: LD E,A
 LD D,0
 INC A
 LD (OBP),A
 LD HL,OUTBUF
 ADD HL,DE
 POP AF
 LD (HL),A
 POP DE
 POP HL
 RET
;
OBP: DEFS 1
;
DPCMP: PUSH BC 
 LD B,A
 LD A,H
 CP D
 JP NZ,DPCMP1
 LD A,L
 CP E
DPCMP1: LD A,B
 POP BC
 RET
; Modified CRUN.LIB routines by Ron Cain
;
ccgchar: LD A,(HL)
ccsxt: LD L,A
 RLCA
 SBC A,A
 LD H,A
 RET
ccgint: LD A,(HL)
 INC HL
 LD H,(HL)
 LD L,A
 RET
ccpchar: LD A,L
 LD (DE),A
 RET
ccpint: LD A,L
 LD (DE),A
 INC DE
 LD A,H
 LD (DE),A
 RET
ccor: LD A,L
 OR E
 LD L,A
 LD A,H
 OR D
 LD H,A
 RET
ccxor: LD A,L
 XOR E
 LD L,A
 LD A,H
 XOR D
 LD H,A
 RET
ccand: LD A,L
 AND E
 LD L,A
 LD A,H
 AND D
 LD H,A
 RET
cceq: CALL cccmp
 RET Z
 DEC HL
 RET
ccne: CALL cccmp
 RET NZ
 DEC HL
 RET
ccgt: EX DE,HL
 JP cclt
ccle: CALL cccmp
 RET Z
 RET C
 DEC HL
 RET
ccge: CALL cccmp
 RET NC
 DEC HL
 RET
cclt: CALL cccmp
 RET C
 DEC HL
 RET
cccmp: LD A,E
 SUB L
 LD E,A
 LD A,D
 SBC A,H
 LD HL,1
 JP M,cccmp1
 OR E
 RET
cccmp1: OR E
 SCF
 RET
ccuge: CALL ccucmp
 RET NC
 DEC HL
 RET
ccult: CALL ccucmp
 RET C
 DEC HL
 RET
ccugt: EX DE,HL
 JP ccult
ccule: CALL ccucmp
 RET Z
 RET C
 DEC HL
 RET
ccucmp: LD A,D
 CP H
 JP NZ,ccucmp1
 LD A,E
 CP L
ccucmp1: LD HL,1
 RET
ccasr: EX DE,HL
ccasr1: LD A,H
 RLA
 LD A,H
 RRA
 LD H,A
 LD A,L
 RRA
 LD L,A
 DEC E
 JP NZ,ccasr1
 RET
ccasl: EX DE,HL
ccasl1: ADD HL,HL
 DEC E
 JP NZ,ccasl1
 RET
ccsub: LD A,E
 SUB L
 LD L,A
 LD A,D
 SBC A,H
 LD H,A
 RET
ccneg: CALL cccom
 INC HL
 RET
cccom: LD A,H
 CPL
 LD H,A
 LD A,L
 CPL
 LD L,A
 RET
ccmult: LD B,H
 LD C,L
 LD HL,0
ccmult1: LD A,C
 RRCA
 JP NC,ccmult2
 ADD HL,DE
ccmult2: XOR A
 LD A,B
 RRA
 LD B,A
 LD A,C
 RRA
 LD C,A
 OR B
 RET Z
 XOR A
 LD A,E
 RLA 
 LD E,A
 LD A,D
 RLA
 LD D,A
 OR E
 RET Z
 JP ccmult1
ccdiv: LD B,H
 LD C,L
 LD A,D
 XOR B
 PUSH AF
 LD A,D
 OR A
 CALL M,ccdeneg
 LD A,B
 OR A
 CALL M,ccbcneg
 LD A,16
 PUSH AF
 EX DE,HL
 LD DE,0
ccdiv1: ADD HL,HL
 CALL ccrdel
 JP Z,ccdiv2
 CALL cccbcde
 JP M,ccdiv2
 LD A,L
 OR 1
 LD L,A
 LD A,E
 SUB C
 LD E,A
 LD A,D
 SBC A,B
 LD D,A
ccdiv2: POP AF
 DEC A
 JP Z,ccdiv3
 PUSH AF
 JP ccdiv1
ccdiv3: POP AF
 RET P
 CALL ccdeneg
 EX DE,HL
 CALL ccdeneg
 EX DE,HL
 RET
ccdeneg: LD A,D
 CPL
 LD D,A
 LD A,E
 CPL
 LD E,A
 INC DE
 RET
ccbcneg: LD A,B
 CPL
 LD B,A
 LD A,C
 CPL
 LD C,A
 INC BC
 RET
ccrdel: LD A,E
 RLA
 LD E,A
 LD A,D
 RLA
 LD D,A
 OR E
 RET
cccbcde: LD A,E
 SUB C
 LD A,D
 SBC A,B
 RET
;
;
;	TAKE COMMAND BUFFER AND BUILD POINTER LIST
;	Routine derived from Mike Bernson's Small-C in CUG
;
ccinit:	
	LD HL,(6)
	DEC HL
	LD SP,HL
	LD HL,80H
	LD E,(HL)
	LD D,0 
	ADD HL,DE
	INC HL
	LD (HL),0
	LD DE,cchptr
	LD HL,80H 
	LD BC,1
ccinit2:
	INC HL
	LD A,(HL)
	OR A 
	JP Z,ccinit4
	CP ' ' 
	JP Z,ccinit2
	LD A,L 
	LD (DE),A
	LD A,H
	INC DE
	LD (DE),A
	INC DE
	INC C 
ccinit3:
	INC HL
	LD A,(HL)
	OR A 
	JP Z,ccinit4
	CP ' ' 
	JP NZ,ccinit3
	LD (HL),0
	JP ccinit2
ccinit4:
	LD HL,cchptr-2
	PUSH BC ;argc
	PUSH HL ;argv
	CALL main
	JP 0  
	DEFW ccNULL
cchptr:
	DEFW ccNULL,ccNULL,ccNULL,ccNULL,ccNULL
	DEFW ccNULL,ccNULL,ccNULL,ccNULL,ccNULL
	DEFW ccNULL,ccNULL,ccNULL,ccNULL,ccNULL
	DEFW ccNULL,ccNULL,ccNULL,ccNULL,ccNULL
	DEFW ccNULL,ccNULL,ccNULL,ccNULL,ccNULL
ccNULL:
	DEFB 'NONAME',0 
;
;   From Mike Bernson
;	USED BY SWITCH TO SEARCH TABLE
;	CALLING FORMAT FROM COMPILER
;	DE-POINTER TO TABLE
;	HL-WHERE TO GO IF VALUE NOT IN TABLE
;	BC- NUMBER OF  ENTRY IN TABLE
;
ccswtch:
	EX (SP),HL
	EX DE,HL
ccswch1:
	LD A,E
	CP (HL) 
	INC HL 
	JP NZ,ccswch2 
	LD A,D  
	CP (HL) 
	JP NZ,ccswch2 
	INC HL
	LD E,(HL)
	INC HL
	LD D,(HL)
	EX DE,HL 
	POP BC 
	JP (HL)  
ccswch2: INC HL 
	INC HL
	INC HL
	DEC B  
	JP NZ,ccswch1
	EX (SP),HL
	POP BC 
	JP (HL) 
#endasm
 (HL) 
	INC HL 
	JP NZ,ccswch2 
	LD A,D  
	CP (HL) 
	JP NZ,ccswch2 
	INC HL
