REV EQU 16H ;	06/13/79  R. CURTISS	NO ERR ON REWIND CLOSED FILE

;REV EQU 15H ;	06/10/79  R. CURTISS	DREV, C, ICNTL

;REV EQU 14H ;	05/31/79  R. CURTISS	FIX LF, MORE, XDEVC, GBPDEV

;REV EQU 13H ;	05/30/79  R. CURTISS	XDEVC FIX, PATCH SPACE

;REV EQU 12H ;	05/29/79  R. CURTISS	IWRT5,MCHOFF

;REV EQU 11H ;	05/29/79  R. CURTISS	MORE,FPRS,FNAME

;REV EQU 10H ;	05/29/79  R. CURTISS	NEW VERSION
;
; STAGE2 MAIN PROGRAM AND I/O OPERATION PACKAGE
;
; REVISION B02  03/15/78  R. CURTISS   ADD COMMENTS
;
MAIN	EQU	100H
PROGR	EQU	1000H

	ORG	MAIN

	JMP	F4IO	; MAIN ENTRY POINT - PROGRAM STARTUP
	DB	REV	; IOOP REVISION

	JMP	IOOP	; ENTRY POINT - I/O PACKAGE
	DB	DREV	; DISK I/O REVISION

	JMP	TRAP	; ENTRY POINT - END OF MACROS DETECTED
	NOP

	JMP	MEMSET	; ENTRY POINT - SET UP FLUB MEMORY BOUNDS
	NOP

PROGRM:	JMP	PROGR	; EXTERNAL REFERENCE - STAGE2, FLT1, FLT2
	NOP

EXIT:	JMP	0000H	; EXTERNAL REFERENCE - RETURN TO CP/M
	NOP
;
; -------------------------------------
;
; MAIN PROGRAM
;
	DS	38H	; STACK SPACE

F4IO:	LXI	SP,F4IO
;
	CALL	INIT
	CALL	PROGRM
;
;	 CLOSE ALL CHANNELS
;
	CALL	GCLOSE

	CALL	EXIT
	JMP	F4IO
;
; --------------------------------------
;
; INITIALIZE CHANNEL I/O TABLE
;
INIT:
	MVI	B,6*MAXCH
	LXI	D,CHAN
	LXI	H,JCHAN+1
;
INIT1:
	LDAX	D
	MOV	M,A
	INX	D
	INX	H
	DCR	B
	JNZ	INIT1
;
	CALL	FINIT	; GET FILES FROM COMMAND LINE
	RET
;
; -----------------------------------------
;
; INITIAL VALUES FOR CHANNEL CONTROL TABLE
;
CHAN:
;		R W O C U S
	DB	1,0,1,1,2,1	;	CHANNEL 1 - INPUT FILE
	DB	1,1,1,1,1,1	;	CHANNEL 2 - SCRATCH FILE
	DB	0,1,1,1,2,1	;	CHANNEL 3 - OUTPUT FILE
	DB	0,1,1,1,3,1	;	CHANNEL 4 - LISTING FILE
	DB	1,1,0,0,2,4	;	CHANNEL 5 - CONSOLE I/O
;
MAXCH	EQU	($-CHAN)/6
;
;
;	R  KCH+1  READ ACCESS
;		0 - ILLEGAL
;		1 - CHANNEL AVAILABLE FOR READ
;
;	W  KCH+2  WRITE ACCESS
;		0 - ILLEGAL
;		1 - MACHINE READABLE OUTPUT
;		2 - HUMAN READABLE OUTPUT
;		3 - FIRST LINE OF HUMAN READABLE OUTPUT
;		    ALLOWS TOP OF FORM
;
;	O  KCH+3  OPEN ACCESS
;		0 - NO ACTION REQUIRED
;		1 - OPEN REQUIRED
;
;	C  KCH+4  CONTROL ACCESS (CLOSE)
;		0 - NO ACTION REQUIRED
;		1 - CLOSE REQUIRED
;
;	U  KCH+5  DEVICE CODE
;		0 - NULL DEVICE
;		1 - DISK
;		2 - CONSOLE
;		3 - LIST DEVICE
;
;	S  KCH+6  CHANNEL STATUS
;		0 - NOT AVAILABLE
;		1 - CLOSED
;		2 - OPEN FOR READ
;		3 - OPEN FOR WRITE
;		5 - END OF FILE ON READ
;		    END OF MEDIUM ON WRITE
;
; -------------------------------------
;
TRAP:	NOP		; TRAP AT END OF MACRO READING
	NOP
	RET
;
; --------------------------------------
;
; SET FLUB MEMORY BOUNDS
;	DE  LOW LIMIT
;	HL  HIGH LIMIT
;
MEMSET:	LHLD	0006H	; GET BDOS ENTRY ADDRESS
	DCR	H	; ONE PAGE LESS TO BE SAFE
	RET
;
; ----------------------------------------
;
;	I/O SUPERVISOR
;
;  OPERATION CODE
;	0 - CLOSE
;	1 - WRITE
;      -1 - READ
;
;  OPERATION STATUS
;	0 - NORMAL
;	1 - EOF OR END OF MEDIUM
;	2 - ILLEGAL OPERATION
;	3+  ERROR CODE
;
;  STATUS = IOOP ( OPERATION , CHANNEL , BUFFER )
;		      (A)        (B)      (HL)     
;
;	MAXLEN:	DB	N
;	LENGTH:	DS	1
;	BUFFER:	DS	N+1
;
; READ OPERATION
;	REGISTER	BEFORE		AFTER
;	    A		  -1		STATUS
;	    B		CHANNEL
;	   HL		START OF LINE	
;	BUFFER		MAXLEN		LENGTH
;					LINE DATA
;
; WRITE OPERATION
;	REGISTER	BEFORE		AFTER
;	    A		   1		STATUS
;	    B		CHANNEL
;	   HL		START OF LINE
;	BUFFER		LENGTH
;			LINE DATA
;
; CLOSE/REWIND OPERATION
;	REGISTER	BEFORE		AFTER
;	    A		  0		STATUS
;	    B		CHANNEL
;
IOOP:
	STA	JOP	; SAVE OPERATION CODE
	SHLD	POINT	; SAVE BUFFER POINTER
	MOV	A,B
	STA	NCHAN	; SAVE CHANNEL NUMBER
	ORA	A	; TEST CHANNEL NUMBER
	JM	LL7	; JUMP IF < 0   ERROR CONDITION
	JZ	LL5	; JUMP IF = 0   NULL CHANNEL   BIT BUCKET
;
	CPI	MAXCH+1
	JP	LL7	; JUMP IF CHANNEL > MAX CHANNEL
;
	CALL	MCHOFF	; MAKE CHANNEL OFFSET
	XCHG
	SHLD	CHOFF	; CHANNEL OFFSET
	XCHG
;
	LXI	H,JCHAN+6  ; STATUS = JCHAN(KCH+6)
	DAD	D
	MOV	A,M
	ORA	A
	JZ	LL7	; JUMP IF STATUS = UNAVAILABLE
;
	MOV	B,A	; SAVE CHANNEL STATUS
	LDA	JOP
	ORA	A
	JM	LL10	; JUMP IF READ OPERATION
	JNZ	LL20	; JUMP IF WRITE OPERATION
;
; -------------------------------------
;
;	 CONTROL OPERATION
;
	MOV	A,B	; GET CHANNEL STATUS
	CPI	1
	JZ	LL4	; JUMP IF STATUS = CLOSED
;
	LXI	H,JCHAN+4
	DAD	D
	MOV	A,M	; CONTROL ACCESS = JCHAN(KCH+4)
;
	ORA	A
	JZ	LL3	; JUMP IF CONTROL OPERATION UNAVAILABLE
;
	PUSH	D	; SAVE KCH
	CALL	ICNTL	; PERFORM CONTROL OPERATION
	POP	D	; RESTORE KCH
	RET
;
LL3:
	LXI	H,JCHAN+6  ; SET CHANNEL STATUS TO INACTIVE
	DAD	D
	MVI	M,1	;    JCHAN(KCH+6) = 1
;
LL4:			; NORMAL TERMINATION
	XRA	A	;    SET OPERATION STATUS TO ZERO
	RET
;
LL5:			; NULL CHANNEL I/O
	LDA	JOP
	ORA	A
	JP	LL4	; JUMP IF NOT READ OPERATION
;
LL6:
	MVI	A,1	; EOF STATUS OR END OF MEDIUM
	RET
;
LL7:
	MVI	A,2	; ILLEGAL OPERATION STATUS
	RET
;
; ---------------------------------
;
;	 READ OPERATION
;
LL10:
	MOV	A,B	; GET CHANNEL STATUS
	DCR	A
	JZ	LL11	; JUMP IF CLOSED
	DCR	A
	JZ	LL12	; JUMP IF OPEN FOR READ
	DCR	A
	JZ	LL7	; JUMP IF OPEN FOR WRITE   ERROR
	DCR	A
	JZ	LL12	; JUMP IF OPEN FOR BOTH READ AND WRITE
	DCR	A
	JZ	LL6	; JUMP IF END OF FILE
	JMP	LL7	; ERROR
;
LL11:
	LXI	H,JCHAN+1
	DAD	D
	MOV	A,M	; GET READ ACCESS PERMISSION
;
	ORA	A
	JZ	LL7	; JUMP IF READING NOT ALLOWED
;
	LXI	H,JCHAN+6
	DAD	D
	MVI	M,2	; SET CHANNEL STATUS OPEN FOR READ
;
	LXI	H,JCHAN+3
	DAD	D
	MOV	A,M	; GET OPEN ACCESS FOR CHANNEL
	ORA	A
	JZ	LL12	; JUMP IF OPEN NOT REQUIRED
;
	PUSH	D	; SAVE KCH
	LXI	B,IACCE	; READ ACCESS
	CALL	IOPEN
	POP	D
	ORA	A
	RNZ		; RETURN IF OPEN ERROR
;
LL12:
	PUSH	D	; SAVE KCH
	CALL	IREAD	; PERFORM READ OPERATION
	POP	D
	JMP	LL30
;
; -------------------------------------
;
;	 WRITE OPERATION
;
LL20:
	MOV	A,B	; GET CHANNEL STATUS
	DCR	A
	JZ	LL21	; JUMP IF CLOSED
	DCR	A
	JZ	LL7	; JUMP IF OPEN FOR READ
	DCR	A
	JZ	LL22	; JUMP IF OPEN FOR WRITE
	DCR	A
	JZ	LL22	; JUMP IF OPEN FOR READ OR WRITE
	DCR	A
	JZ	LL6	; JUMP IF AT END OF MEDIUM
	JMP	LL7	; ERROR
;
LL21:
	LXI	H,JCHAN+2
	DAD	D
	MOV	A,M	; GET WRITE ACCESS
	ORA	A
	JZ	LL7	; JUMP IF WRITING NOT POSSIBLE
;
	LXI	H,JCHAN+6
	DAD	D
	MVI	M,3	; SET CHANNEL OPEN FOR WRITE
;
	LXI	H,JCHAN+3
	DAD	D
	MOV	A,M	; GET OPEN ACCESS
	ORA	A
	JZ	LL22	; JUMP IF NO OPEN REQUIRED
;
	PUSH	D	; SAVE KCH
	LXI	B,OACCE	; WRITE ACCESS
	CALL	IOPEN
	POP	D
	ORA	A
	RNZ		; RETURN IF OPEN ERROR
;
LL22:
	PUSH	D	; SAVE KCH
	CALL	IWRIT	; PERFORM WRITE OPERATION
	POP	D
;
;
LL30:
	CPI	1
	RNZ		; RETURN IF NOT EOF OR EOM
;
	LXI	H,JCHAN+6
	DAD	D
	MVI	M,5	; SET STATUS TO EOF OR EOM
	RET
;
; --------------------------------------
;
;	BUFFER READ ROUTINE
;
IREAD:	CALL	GBPDEV	; HL = BUFFER POINTER
	ORA	A	; A  = DEVICE CODE
	JZ	IRED0	; JUMP IF 0 - NULL

	DCR	A
	JZ	IRED1	; JUMP IF 1 - DISK

	DCR	A
	JZ	IRED2	; JUMP IF 2 - CONSOLE IN

IRED0:	MVI	A,1	; END OF FILE OR ERROR CONDITION
	RET
;
;
IRED1:	PUSH	H
	DCX	H
	SHLD	ARGLST+2  ; SET LENGTH POINTER
	DCX	H
	SHLD	ARGLST	  ; SET MAX LENGTH POINTER
	CALL	GFTAB	; HL = FILE TABLE POINTER
	POP	D	; DE = BUFFER POINTER
	LXI	B,ARGLST
	CALL	LREAD	; READ LINE
	ORA	A
	RZ		; RETURN IF NO ERROR OR EOF

IREOF:	CALL	MORE	; CHECK FOR CHAN 1 MULTIPLE INPUTS
	JZ	IREAD	; JUMP IF ANOTHER INPUT FILE

	RET

ARGLST:	DW	0	; MAX LINE LENGTH POINTER
	DW	0	; ACTUAL LINE LENGTH POINTER
;
; GET LINE FROM CONSOLE
;
IRED2:	XCHG
	DCX	D
	DCX	D
	CALL	CIB	; INPUT BUFFER FROM CONSOLE
	MVI	E,0AH
	CALL	CO	; SEND LINE FEED TO CONSOLE
	LHLD	POINT
	MOV	A,M
	CPI	1AH	; CONTROL Z
	JZ	IREOF	; JUMP IF FIRST CHAR IN BUFFER IS ^Z

	XRA	A	; NO ERROR
	RET
;
; ------------------------------------
;
; CHECK FOR CHANNEL 1 MULTIPLE INPUTS
;
MORE:	LDA	NCHAN
	DCR	A
	JZ	MORE1	; JUMP IF CHAN 1

	MVI	A,1	; END OF FILE
	RET

MORE1:	LHLD	FNPTR1	; P = IP
	MVI	C,','
	CALL	SCAN
	JZ	MORE2	; JUMP IF ',' FOUND

	MVI	A,1	; END OF FILE
	RET

MORE2:	INX	H
	SHLD	FNPTR1	; IP = P+1

	CALL	GDEVIC	; GET DEVICE CODE
	DCR	A
	JNZ	MORE3	; JUMP UNLESS 1 - DISK

	CALL	GFTAB	; HL = FILE TABLE POINTER
	CALL	DCLOSE	; CLOSE DISK FILE

MORE3:	LHLD	FNPTR
	MVI	B,1
	CALL	XDEVC	; LU(1) = XUNIT(IP)
	ORA	A
	JZ	MORE8	; ERROR IF NUL:

	CPI	3
	JZ	MORE	; ERROR IF LIST DEVICE

	LXI	B,IACCE
	CALL	IOPEN	; OPEN FILE IF DISK
	RET

MORE8:	MVI	A,1	; END OF FILE
	RET
;
; -------------------------------------
;
;	BUFFER WRITE ROUTINE
;
IWRIT:
	LXI	H,JCHAN+2	; GET WRITE ACCESS
	DAD	D
	MOV	B,M	; JHOW = JCHAN(KCH+2)
;
	DCR	B
	JZ	IWRTB	; JUMP IF JHOW = 1  MACHINE READABLE FILE
;
	DCR	B
	JZ	IWRTA	; JUMP IF JHOW = 2  HUMAN READABLE OUTPUT
;
;	***	MAYBE OUTPUT FORM FEED
	MVI	M,2	; SET JHOW TO 2   TOP OF FORM DONE
	CALL	GBPDEV	; HL - BUFFER POINTER
	CPI	3	; A  - DEVICE CODE
	JNZ	IWRT1	; JUMP UNLESS LIST DEVICE

	MVI	E,0CH
	CALL	LO	; FORM FEED TO PRINTER
IWRTA:
IWRTB:	CALL	GBPDEV	; HL - BUFFER POINTER
	ORA	A	; A  - DEVICE CODE
	RZ		; RETURN IF 0 - NULL DEVICE

	DCR	A
	JZ	IWRT1	; JUMP IF 1 - DISK DEVICE

	DCR	A
	JZ	IWRT2	; JUMP IF 2 - CONSOLE OUT

	DCR	A
	JZ	IWRT3	; JUMP IF 3 - LIST DEVICE

	MVI	A,1	; ERROR CONDITION
	RET
;
;
IWRT1:	LHLD	POINT	; RECALL BUFFER POINTER
	LDA	NCHAN	; RECALL CHANNEL NUMBER
	CPI	5
	JZ	IWRT2	; JUMP IF CONSOLE CHANNEL

	PUSH	H
	CALL	GFTAB	; HL = FILE TABLE POINTER
	POP	D	; DE = BUFFER POINTER
	MOV	B,D
	MOV	C,E
	DCX	B	; BC = POINTER TO LINE LENGTH
	CALL	LWRITE	; WRITE LINE
	ORA	A
	RZ		; RETURN IF NO ERROR

	MVI	A,1
	RET
;
; SEND LINE TO CONSOLE
;
IWRT2:	DCX	H
	MOV	C,M	; GET LINE LENGTH
	INR	C

IWRT2L:	DCR	C
	JZ	IWRT2D

	INX	H
	MOV	E,M
	PUSH	B
	PUSH	H
	CALL	CO
	POP	H
	POP	B
	JMP	IWRT2L

IWRT2D:	MVI	E,0DH
	CALL	CO
	MVI	E,0AH
	CALL	CO
	XRA	A	; NO ERROR
	RET
;
; SEND LINE TO LIST DEVICE
;
IWRT3:	DCX	H
	MOV	C,M	; GET LINE LENGTH
	INR	C

IWRT3L:	DCR	C
	JZ	IWRT3D

	INX	H
	MOV	E,M
	PUSH	B
	PUSH	H
	CALL	LO
	POP	H
	POP	B
	JMP	IWRT3L

IWRT3D:	MVI	E,0DH
	CALL	LO
	MVI	E,0AH
	CALL	LO
	XRA	A
	RET
;
; -------------------------------------
;
;	OPEN CHANNEL
;
IOPEN:
	PUSH	B	; BC POINTS TO ACCESS CODE
	CALL	GFTAB	; HL = FILE TABLE POINTER
	PUSH	H
	CALL	FNAME	; DE = FILE NAME POINTER
	POP	H
	POP	B
	RZ		; RETURN UNLESS DISK DEVICE

	CALL	DOPEN	; OPEN FILE
	ORA	A
	RZ		; RETURN IF NO ERROR

	MVI	A,1
;	***	***	ERROR MESSAGE
	RET
;
; --------------------------------------
;
;	CLOSE CHANNEL
;
ICNTL:	CALL	GBPDEV	; HL - BUFFER POINTER
	CPI	1	; A  - DEVICE CODE
	JNZ	ICNT3	; JUMP UNLESS 1 - DISK DEVICE

	LXI	H,JCHAN+6
	DAD	D
	MVI	M,1	; SET STATUS CLOSED

	CALL	GFTAB	; HL = FILE TABLE POINTER
	CALL	DCLOSE	; CLOSE FILE
	ORA	A
	RZ		; RETURN IF NO ERROR

	MVI	A,1
	RET

ICNT3:
	XRA	A	; SET OPERATION STATUS = 0
	RET
;
; ------------------------------------
;
; GET BUFFER POINTER & DEVICE CODE NUMBER
;		HL	A
;
GBPDEV:	LHLD	CHOFF	; RECALL CHANNEL OFFSET
	XCHG
	LXI	H,JCHAN+5
	DAD	D	; ADD CHANNEL OFFSET
	MOV	A,M	; DEVICE CODE
	LHLD	POINT
	RET
;
; ---------------------------------
;
; GET FILE TABLE POINTER
;
GFTAB:	LDA	NCHAN	; GET CHANNEL NUMBER
	DCR	A
	ADD	A
	MOV	E,A
	MVI	D,0
	LXI	H,FTABP
	DAD	D
	MOV	A,M
	INX	H
	MOV	H,M
	MOV	L,A
	RET
;
; -------------------------------------
;
; GET FILE NAMES FROM COMMAND LINE
;
FINIT:	LXI	D,80H
	LXI	H,COMLIN-1
	LDA	80H
	INR	A
	MOV	C,A	; # OF CHARACTERS

FINIT1:	LDAX	D
	MOV	M,A
	INX	H
	INX	D
	DCR	C
	JNZ	FINIT1

FINIT2:	MVI	M,0	; TERMINATE LINE WITH NULL
	CALL	FINIT3	; CONVERT TO UPPER CASE
	CALL	FPRS	; PARSE COMMAND LINE
	RZ		; RETURN IF NO COMMAND LINE ERROR

	LXI	D,COMERR
	CALL	COB	; ERROR MESSAGE TO CONSOLE
	LXI	D,COMLIN-2
	CALL	CIB	; GET NEW COMMAND LINE
	LXI	H,COMLIN-1
	MOV	E,M	; GET LINE LENGTH
	MVI	D,0
	INX	H
	DAD	D
	JMP	FINIT2


FINIT3:	LXI	H,COMLIN-1
	MOV	C,M	; LENGTH OF COMMAND LINE
	INX	H
	INR	C

FINIT4:	DCR	C
	RZ		; RETURN IF AT END OF LINE

	MOV	A,M	; GET CHARACTER
	CALL	FINIT5	; CONVERT IF LOWER CASE
	MOV	M,A
	JMP	FINIT4

FINIT5:	CPI	'A'+20H
	RC		; RETURN IF < 'a'
	CPI	'Z'+21H
	RNC		; RETURN IF > 'z'
	SUI	20H
	RET
;
; --------------------------------------
;
; PARSE COMMAND LINE
;
FPRS:	LXI	H,COMLIN  ; P = ^COM
	MVI	C,'='
	CALL	SCAN
	JZ	FPRS1	; JUMP IF '=' FOUND

	LXI	H,COMLIN
	SHLD	FNPTR1	; IP = ^COM
	LXI	H,FNCON
	SHLD	FNPTR3	; OP = ^'CON:'
	LXI	H,FNLST
	SHLD	FNPTR4	; LP = ^'LST:'
	JMP	FPRS3

FPRS1:	MVI	M,0	; MEM(P) = 0
	INX	H	; P = P + 1
	SHLD	FNPTR1	; IP = P

	LXI	H,COMLIN  ; P = ^COM
	SHLD	FNPTR3	; OP = ^CHANNEL 3 SPECIFICATION
	MVI	C,','
	CALL	SCAN
	JZ	FPRS2	; JUMP IF ',' FOUND

	LXI	H,FNLST
	SHLD	FNPTR4	; LP = ^'LST:'
	JMP	FPRS3

FPRS2:	MVI	M,0	; MEM(P) = 0
	INX	H	; P = P + 1
	SHLD	FNPTR4	; LP = ^CHANNEL 4 SPECIFICATION

FPRS3:	LHLD	FNPTR1
	MVI	B,1
	CALL	XDEVC	; LU(1) = XUNIT(IP)
	ORA	A
	JZ	FPRS8	; ERROR IF NUL: SPECIFIED

	CPI	3
	JZ	FPRS8	; ERROR IF LST: SPECIFIED

	LHLD	FNPTR3
	MVI	B,3
	CALL	XDEVC	; LU(3) = XUNIT(OP)

	LHLD	FNPTR4
	MVI	B,4
	CALL	XDEVC	; LU(4) = XUNIT(LP)

	XRA	A	; NO COMMAND ERROR DETECTED
	RET

FPRS8:	ORI	1	; COMMAND ERROR DETECTED
	RET
;
; -------------------------------------
;
SCAN:	MOV	A,M
	CMP	C
	RZ		; RETURN IF SEARCH SUCCESSFUL

	ORA	A
	JZ	SCAN1	; JUMP IF END OF STRING

	INX	H
	JMP	SCAN

SCAN1:	INR	A	; Z=0 - SEARCH FAILS
	RET
;
; -------------------------------------
;
; GET FILE NAME POINTER FOR OPEN
;
FNAME:	CALL	GDEVIC	; GET DEVICE CODE
	CPI	1
	JZ	FNAME1	; JUMP IF DISK DEVICE

	XRA	A
	RET

FNAME1:	LDA	NCHAN
	DCR	A
	ADD	A
	MOV	E,A
	MVI	D,0
	LXI	H,FNPTR  ; FILE NAME POINTER TABLE
	DAD	D
	MOV	E,M
	INX	H
	MOV	D,M
	MVI	A,1
	ORA	A
	RET

GDEVIC:	LHLD	CHOFF	; CHANNEL TABLE OFFSET
	LXI	D,JCHAN+5
	DAD	D
	MOV	A,M
	RET
;
; --------------------------------------
;
;	HL - POINTER TO FILE NAME
;	B  - CHANNEL NUMBER

;	A  - DEVICE CODE NUMBER
;
XDEVC:	CALL	SKIPB	; SKIP BLANKS
	MVI	C,0	; NULL DEVICE
	JZ	XDEVC4	; JUMP IF , = OR NULL FOUND

	PUSH	H
	LXI	D,XDVTBL-2  ; SPECIAL DEVICE CODE TABLE

XDEVC2:	INX	D
XDEVC1:	INX	D
XDEVC0:	LDAX	D
	MOV	C,A
	CPI	1
	JZ	XDEVC3	; JUMP IF END OF TABLE

	POP	H
	PUSH	H
	INX	D

	LDAX	D
	INX	D
	CMP	M
	JNZ	XDEVC2	; JUMP IF NO MATCH

	INX	H
	LDAX	D
	INX	D
	CMP	M
	JNZ	XDEVC1	; JUMP IF NO MATCH

	INX	H
	LDAX	D
	INX	D
	CMP	M
	JNZ	XDEVC0	; JUMP IF NO MATCH

	INX	H	; TABLE MATCH FOUND
	MVI	A,':'
	CMP	M
	JZ	XDEVC3	; JUMP IF COLON

	MVI	C,1	; DISK DEVICE ASSUMED

XDEVC3:	POP	H	; RESTORE STACK

XDEVC4:	PUSH	B	; B - CHAN #   C - DEVICE CODE #
	CALL	MCHOFF	; MAKE CHANNEL OFFSET POINTER
	POP	B
	LXI	H,JCHAN+5
	DAD	D
	MOV	M,C	; JCHAN(CH+5) = DEVICE CODE
	MOV	A,C
	RET
;
;
XDVTBL:	DB	0,'NUL'
	DB	2,'CON'
	DB	2,'TTY'
	DB	2,'CRT'
	DB	2,'KBD'
	DB	3,'LST'
	DB	3,'LPT'
	DB	1
;
;
SKIPB:	MOV	A,M
	ORA	A
	RZ

	SUI	','
	RZ

	MOV	A,M
	SUI	'='
	RZ

	MOV	A,M
	CPI	' '
	RNZ

	INX	H
	JMP	SKIPB
;
; -----------------------------------
;
MCHOFF:	DCR	B	; COMPUTE CHANNEL OFFSET
	MOV	A,B	;    FOR TABLE LOOKUP
	RLC		;    KCH = (JCH-1)*6
	ADD	B
	RLC
	MOV	E,A
	MVI	D,0
	RET
;
; -------------------------------------
;
; CONSOLE I/O
;
BDOS	EQU	0005H

CIB:	MVI	C,10
	CALL	BDOS
	RET

COB:	MVI	C,9
	CALL	BDOS
	RET

CO:	MVI	C,2
	CALL	BDOS
	RET

LO:	MVI	C,5
	CALL	BDOS
	RET
;
; ------------------------------------
;
;	STORAGE
;
JCHAN:	DS	6*MAXCH+1  ; WORKING STORAGE FOR I/O TABLE
JOP:	DS	1	; STORAGE FOR OPERATION CODE
POINT:	DS	2	; BUFFER POINTER
NCHAN:	DS	1	; STORAGE FRO CHANNEL NUMBER
LEN:	DS	1	; LINE LENGTH
CHOFF:	DS	2	; CHANNEL TABLE OFFSET
;
IACCE:	DB	1	; READ ACCESS CODE
OACCE:	DB	3	; WRITE ACCESS CODE WITH DELETE

FTABP:	DW	FTAB1
	DW	FTAB2
	DW	FTAB3
	DW	FTAB4

FTAB1:	DB	0,0,0,'1'	; CHAN 1 FILE TABLE
	DS	33+128

FTAB2:	DB	0,0,0,'2'
	DS	33+128

FTAB3:	DB	0,0,0,'3'
	DS	33+128

FTAB4:	DB	0,0,0,'4'
	DS	33+128

FNPTR:
FNPTR1:	DS	2
FNPTR2:	DW	FNCH2
FNPTR3:	DS	2
FNPTR4:	DS	2

FNCH2:	DB	'STAGE2.CH2',0

FNNUL:	DB	'NUL:',0
FNCON:	DB	'CON:',0
FNLST:	DB	'LST:',0

	DB	128,0
COMLIN:	DS	129	; STORAGE FOR COMMAND LINE

COMERR:	DB	0DH,0AH,'>>>>> COMMAND ERROR - REENTER'
	DB	0DH,0AH,'$',0
;
;
