#asm
;
;              CP/M CONSOLE I/O ROUTINES FOR SMALL-C
;    These should be included with: '#include CONIO.LIB'
;    They should be inserted after CRUN.LIB
;
;  Functions in CONIO.LIB:
;
; cpm(DE_value,C_value)   General BDOS entry
; getchar()               Get char from console
; putchar(char)           Send char to console
; gets(buffer)            Get null terminated string into buffer
; puts(buffer)            Output string to console
; crlf()                  Output cr/lf
; lston()                 Turn on LST:
; lstoff()                Turn off LST:
; getkbd()		  Get char from kbd without echo
;
;
;  DEFINITIONS
;
CR EQU 0DH
LF EQU 0AH
BS EQU 08
TAB EQU 09
DEL EQU 7FH
CZ EQU 1AH
ESC EQU 1BH
ccBDOS EQU 5
;
;
;
; Entry to CP/M routines
; Function format: cpm(DE value,C value);
;
cpm: POP HL ;Save return
 POP BC
 POP DE ; Get DE or E value
 PUSH DE ; Restore stack
 PUSH BC
 PUSH HL
 CALL ccBDOS ; Call CP/M BDOS
 JP ccsxt ;Sign extend A into HL and return
;
; Get a character from the console and return in HL
; Function format:  getchar()
;
getchar: CALL ccVTOA ;GET INPUT CHAR INTO A
 JP ccsxt ; Sign extend A to HL
;
; O/P a character to the console.
; Function format:  putchar(c)
;
putchar: LD A,L ;c into A
 CALL ccATOV ;O/P to CON: 
 JP ccsxt
;
; Get string into buffer from console. String terminated by null
;   Function format: gets(buffer)
;
gets: EX DE,HL ; Pointer to I/P buffer
 CALL ccINLN ;Get I/P into buffer
 EX DE,HL ;Exit with HL pointing to start of buffer
 RET
;
;       O/P null terminated string to CON: 
;       Function argument points to start.
;       Function format:  puts(buffer)
;
puts: PUSH HL ;Save pointer for return
ccPUTS1: LD A,(HL) ;O/P loop till null.
 CP 0
 JP Z,ccPUTS5
 CP '\'
 JP NZ,ccPUTS3
 INC HL
 LD A,(HL)
 CP 'b'
 JP NZ,ccPUTS2
 LD A,BS
 JP ccPUTS3
ccPUTS2: CP 'n'
 CALL Z,crlf
 JP Z,ccPUTS4
 CP 't'
 JP NZ,ccPUTS3
 LD A,TAB
ccPUTS3: CALL ccATOV
ccPUTS4: INC HL
 JP ccPUTS1
ccPUTS5: POP HL ;String done
 RET
;
; Subroutine to o/p A to console
; All regs saved
; 
ccATOV: PUSH AF
 PUSH HL
 PUSH DE
 PUSH BC
 LD C,2
 LD E,A
 PUSH DE
 CALL ccBDOS
 POP DE
 LD A,(ccLSTFG)
 CP 1
 LD C,5
 CALL Z,ccBDOS ;LST:
 POP BC
 POP DE
 POP HL
 POP AF
 RET
ccLSTFG: DEFB 0 ;Flag to show that LST: O/P is on
;
; O/P CRLF - Uses 'ccATOV'
;
crlf: PUSH AF
 LD A,CR
 CALL ccATOV
 LD A,LF
 CALL ccATOV
 POP AF
 RET
;
;  Functions to turn LST: on or off
;  Function formats: lston() and lstoff()
;
lston: LD A,1 ;Mark flag and return
ccLSTN1 LD (ccLSTFG),A
 RET
lstoff: XOR A
 JP ccLSTN1
;
; Get char from VDU
; Everything saved except AF
; ^C gives warm start
;
ccVTOA: PUSH HL
 PUSH DE
 PUSH BC
 LD C,1
 CALL ccBDOS
ccVTA1: POP BC
 POP DE
 POP HL
 PUSH AF
 CP 3 ;^C?
 JP Z,0    ;WARM START WITH ^C
 POP AF
 RET
;
; Get keyboard char without echo. Not CP/M 1.4 
;
getkbd: LD C,6
 LD E,0FFH
 CALL ccBDOS
 JP ccsxt
;
; Get input char without echo
;
ccCIN: PUSH HL
 PUSH DE
 PUSH BC
 LD HL,(1)
 LD DE,6
 ADD HL,DE
 LD DE,ccCIN1
 PUSH DE
 JP (HL)
ccCIN1: JP ccVTA1
;
; Get input line into buffer
; Enter with DE pointing to start of buffer.
; Exit with DE pointing to start of line terminated by null.
; 78 chars. maximum.
; Uses: 'ccATOV','ccCIN','crlf'
;
ccINLN: PUSH HL
 PUSH DE
 PUSH BC
 LD B,0 ; Zero char. counter
 EX DE,HL   ;Point to I/P buffer
ccINLN1: CALL ccCIN
 CP CR
 JP Z,ccINLN3
 CP BS ; Handle BS or DEL
 JP Z,ccINLN2
 CP DEL
 JP Z,ccINLN2
 PUSH AF
 LD A,4EH ;max allowed
 CP B ;End of I/P buff?
 JP Z,ccINLN4
 POP AF
 LD (HL),A
 CALL ccATOV
 INC HL
 INC B
 JP ccINLN1
ccINLN2: XOR A
 CP B ;Don't BS past start
 JP Z,ccINLN1
 LD A,BS
 CALL ccATOV
 DEC HL
 DEC B
 JP ccINLN1
ccINLN3: CALL crlf   ;CR/LF
 XOR A ;Mark end of input
 LD (HL),A
 POP BC ;Recover regs.
 POP DE 
 POP HL
 RET
ccINLN4: LD A,BS ;Handle overflow
 CALL ccATOV  ;Del. prev. char.
 POP AF
 DEC HL
 DEC B
 CALL ccATOV
 LD (HL),A
 INC HL
 INC B
 JP ccINLN1
;
#endasm
INLN4: LD A,BS ;Handle overflow
 CALL ccATOV  ;Del. prev. char.
 POP AF
 DEC HL
 DEC B
 CALL ccATO