;SHORT MEMORY TEST PROGRAM
;JULY 15, 1977
;***
; MEMTEST now prints to disk after a 128 character
; buffer fills. Each input and output character is
; intercepted,stored in buffer DSKBUF, and counted by
; subroutine STOBYT.  The buffer is put on the disk
; via CP/M file writing. Specifically, CONFILE.TXT is
; assembled, record by record (128 chr chunks), by
; DISKIT. The majority of my modifications lie at START
; and added subroutines, definitions, & code are in the
; I/O section at the end of the program. 
;                                    D.Stein 8/18/80
;***
; MEMTEST modified to check console status during all
; long loop cycles.  If a chr is found it is echoed,
; and a status report ( consisting of the current phase
; number and the current test address ) is printed
; to the console.  See subroutine CheckCON at end of
; the program for more details.     D.Stein 10/7/80
; MEMSHORT is a short version of MEMTEST.  These modi-
; fications are at the beginning of PHASE 2 and the
; beginning of PHASE 3. 00FF has been inserted instead
; of 0080, and FF00 has been inserted instead of FF7F.
; These changes shorten the 'walk' procedure, and thus
; the length of the test.           D.Stein 10/07/80
;***
; MEMSHORT modified to limit errors logged into file to 16
; the problem was that boards would pull down the network.
; Also the bank of memory status deleted.
;				    k.g.holmberg 5/21/82
STRTAD	EQU	100H
BDOS	EQU	0005H
WBOOT	EQU	0000H
	ORG	STRTAD
comcheck:
	lxi	sp,comstk
;set the command line flag for default (no com line assumed)
	mvi	A,1
	sta	comflg
;check the command line for 1,4,8,or C option
	lxi	H,comchr
	mov	A,M	;how many comm chrs?
	cpi	0	;none?
	jz	START
	cpi	1	;just a car ret?
	jz	START
;----------
;Command line exists. Read the first non blank 
;character. Terminate search on carriage return.
getcom:	
	inx	H	;get to next command line addr
	mov	A,M
	cpi	' '	;blank?
	jz	getcom	;get next command chr
	cpi	0Dh	;car ret?
	jz	START
	cpi	'1'	;Low memtest option?
	jz	test1
	cpi	'4'	;High memtest option?
	jz	test4
	cpi	'8'	;Higher memtest option?
	jz	test8
	cpi	'C'	;Highest memtest option?
	jz	testC
	jmp	START	;No option,ignore com line
;low memtest option
test1:	mvi	A,0
	sta	comflg	; set internal data flag
	lxi	H,data1
	shld	datachr	;set pointer to data1
	jmp	START
;high memtest option
test4:	mvi	A,0
	sta	comflg	;set internal data flag
	lxi	H,data4
	shld	datachr	;set pointer to data4
	jmp START
;higher memtest option
test8:	mvi	A,0
	sta	comflg	;set internal data flag
	lxi	H,data8
	shld	datachr	;set pointer to data8
	jmp	START
testC:	mvi	A,0
	sta	comflg	;set internal data flag
	lxi	H,dataC
	shld	datachr	;set pointer to dataC
	jmp	START
START:
;initalize 128 chr buffer for disk output
	lxi	H,dskbuf
	shld	bufchr	; begin buffer at dskbuf
	mvi	A,0
	sta	bufcnt	; zero the counter, too
;------------------
;Fill in the File Control Block (CP/M)
; at default address FCBaddr (BOOT + 5Ch)
; See CP/M interface guide for details.
	mvi	B,16	; counter
	lxi	D,FCBdata ; FCB data addr
	lxi	H,FCBaddr ; FCB addr
FCBfill:ldax	D	; get data byte
	xchg		; DE is FCB addr
	stax	D	; transfer data byte
	xchg		; HL is FCB addr
	inx	H	; next FCB addr byte
	inx	D	; next data byte
	dcr	B	; 16...0
	mov	A,B	; get in acc for check
	cpi	0	; all 16 bytes transferred?
	jnz	FCBfill	
;------------------
	JMP	BEGIN
STAD:	DW	0000	;START ADDRESS
SIZE:	DW	0000	;SIZE TO BE CHECKED
INCR:	DW	0000	;TEST INCREMENT
;
BADB:	DB	0	;BAD BYTE
GOODB:	DB	0	;PATTERN BEING TESTED
ERLOC:	DW	0	;ADDRESS OF BAD BYTE
TLOC:	DW	0	;WALKING BIT PATTERN
RECORD:	DW	0000	;
BMPCNT:	DW	0000	;
COUNT:	DW	0000	;
ENDAD:	DW	0000	;ADDRESS OF LAST LOC+1
SAVAD:	DW	0000	;SAVE INITIAL STARTAD
SPSAVE:	DW	0000	;SAVE INITIAL STACK POINTER
;
CHACNT: DB	0	;OUTPUT BUFFER COUNT
PHASE:	DB	0	;PHASE ID
REPFLG:	DB	0	;REPEAT TEST FLAG
NTFLAG:	DB	0	;TYPE FLAG
;stack defined at bottom of program
;
;
BEGIN:
	ei		; enable interupts
	LXI	H,0000	;CLEAR H&L
	DAD	SP	;CAPTURE STACK POINTER
	SHLD	SPSAVE	;SAVE IT FOR RETURN
	LXI	SP,STACK	;INIT SP
	CALL	LOGINT	;INITIALIZE LOG AREA
	CALL	DOCRLF	;FRESH LINE
;
        LXI    H,MEMTM0 ;BEGINNING MESSAGE
        CALL   TTYSTR   ;STRING TO TTY
        CALL   DOCRLF   ;NEW LINE
        LXI    H,MEMTM1 ;I/P ADDRESS MSG
        CALL   TTYSTR   ;MSG OUT
        LXI    H,STAD+1 ;STRT ADDRESS
        CALL   ADDRIN   ;GET IT
        LHLD   STAD     ;GET BEGINNING ADDRESS
        SHLD   SAVAD    ;SAVE FOR REPEAT FUNCTION
        CALL   DOCRLF   ;NEW LINE
        LXI    H,MEMTM2 ; 'FOR' XXXX BYTES
        CALL   TTYSTR   ;PUT IT OUT
        LXI    H,SIZE+1 ;LENGTH LOC
        CALL   ADDRIN   ;GET TEST LENGTH (IN HEX)
        LHLD   SIZE     ;TOTAL TEST SIZE
        XCHG            ;INTO D&E
        LHLD   STAD     ;GET BEGINNING ADDRESS
        DAD    D        ;BEGINNING+SIZE=END LOC+1
        SHLD   ENDAD    ;SAVE END LOC
        CALL   DOCRLF   ;
        LXI    H,MEMTM6 ;MSG ADDRESS
        CALL   TTYSTR   ;PUT IT OUT
        LXI    H,INCR+1 ;GET TEST SIZE
        CALL   ADDRIN   ; *
ASKGN:  CALL   DOCRLF   ;NEW LINE
        LXI    H,MEMTM5 ;
        CALL   TTYSTR   ;MSG TO TTY
        CALL   TTYINB   ;GET REPLY
        CPI    59H      ;Y FOR YES?
	jnz    aa1
        CZ     STYP     ;SET TYPE ALL
	jmp    flgstm
aa1:	cpi    79h	;lower case yes
	jnz    aa2
	cz     styp	;set type all
	jmp    flgstm
aa2:    CPI    4EH      ;N FOR NO?
	jnz    aa3
        CZ     NSTYP    ;SET NO TYPE ALL
	jmp    flgstm
aa3:	cpi    6Eh	;lower case no
	cz     nstyp	;set no type all
FLGSTM: CALL   DOCRLF   ;NEW LINE
        LXI    H,REPMSG ;CONTINUOUS TESTING, Y OR N
        CALL   TTYSTR   ;MSG OUT
        CALL   TTYINB   ;GET RESPONSE
        CPI    4EH      ;N FOR NO
        JZ     NOREP    ;LEAVE FLAG ZERO FOR NO
	cpi    6Eh	;lower case no
	jz     norep	;leave flag zero for no
        CPI    59H      ;Y FOR YES?
	jz     here
	cpi    79h	;lower case yes
	jz     here
        Jmp    FLGSTM   ;ASK AGAIN IF NEITHER
HERE:   MVI    A,0FFH   ;SET A TO FF
        STA    REPFLG   ;SET REPEAT FLAG
        JMP    FLGST    ;GO...
NOREP:  XRA    A        ;CLEAR A
        STA    REPFLG   ;SET NO REPEAT
FLGST:  CALL   DOCRLF   ;NEW LINE
        LXI    H,PHASE  ; INIT PHASE
        MVI    M,0      ; *
        CALL   BMPPH    ; INIT PHASE
        XRA    A        ; START WITH 0
;
LP11:	call   CheckCON	; check for console chr
        CALL   SETM     ; SET MEMORY TO VALUE IN ACC
        CALL   CMPM     ; COMPARE MEMORY WITH VALUE IN ACC
        INR    A        ; BMP TO NXT CODE
        JNZ    LP11     ; JMP IF NOT 0
;
;  END OF PHASE 1
;
;  BEGIN PHASE 2 - WALK A 1 THRU A FIELD OF 0'S.
;
        LXI    B,00FFH  ; SET UP TO WALK A 1 THRU 0'S
        CALL   WALK     ; DO IT
;
;  END OF PHASE 2
;
;  BEGIN PHASE 3 - WALK A 0 THRU A FIELD OF 1'S
;
        LXI    B,0FF00H ; SET UP TO WALK A 0 THRU 1'S
        CALL   WALK     ; DO IT
;
;  END OF MEMORY CHECK
;
        CALL   DOCRLF   ;NEW LINE
        CALL   LOGOUT   ;PUT OUT LOG INFO
        LHLD   INCR     ;GET INCREMENT
        XCHG            ;INTO D&E
        LHLD   STAD     ;GET CURRENT START ADDRESS
        DAD    D        ;BUMP BY INCR
        SHLD   STAD     ;NEW START ADDR
        XCHG            ;INTO D&E
        LHLD   ENDAD    ;GET ENDING LOC
        MOV    A,H      ;
        CMP    D        ;SEE IF WE'VE PASSED ENDLOC
        JC     TSTND    ;YES IF CARRY SET
        JNZ    FLGST    ;CONTINUE WITH TEST
        MOV    A,L      ;
	CMP	E	;= END LOC?
        JNZ    FLGST    ;CONTINUE TEST IF NO
TSTND:  LXI    H,MEMTM4 ;END MSG
        CALL   TTYSTR
        CALL   DOCRLF   ;
        LDA    REPFLG   ;REPEAT?
        ORA    A        ; ?
        JZ     WBOOT    ;WBOOT (NO) IF ZERO
        CALL   LOGINT   ;ZERO LOG TABLE
        LHLD   SAVAD    ;GET BEGINNING TEST ADDRESS
        SHLD   STAD     ;RESTORE STAD
        CALL   DOCRLF   ;NEW LINE
        LXI    H,RESTRT ;RESTART MSG
        CALL   TTYSTR   ;MSG OUT
        JMP    FLGST    ;REPEAT...
RETURN: LHLD   SPSAVE   ;GET CALLERS SP
        SPHL            ;SET-UP SP
        RET             ;
;
;
SETM:   CALL   SETRG    ; SET UP HL=A(MEM), DE=SIZE
SMLP1:  MOV    M,A      ; STORE A INTO MEM
        INX    H        ; BMP TO NXT LOC
        DCR    E        ; DEC LP CTL
        JNZ    SMLP1    ; JMP IF MORE
        DCR    D        ; ALL DONE?
        JNZ    SMLP1    ; JMP IF NO
        RET             ; RETURN IF YES
;
CMPM:   CALL   SETRG    ; SET UP HL & DE
CMLP1:  CMP    M        ; IS MEM SAME AS ACC?
        JNZ    CMPER    ; JMP IF NO
CMPOK:  INX    H        ; BMP TO NXT LOC
        DCR    E        ; DEC LP CTL
        JNZ    CMLP1    ; JMP IF MORE
        DCR    D        ; DONE?
        JNZ    CMLP1    ; JMP IF NO
        RET             ; RETURN IF YES
;
CMPER:  PUSH   PSW      ; SAVE PSW
        LDA    PHASE    ; GET PHASE NO. IN A
        CPI    1        ; IN 1ST PHASE?
        JZ     ERR      ; JMP IF YES
        LDA    TLOC     ; AT TEST LOC?
        CMP    L        ; *
        JNZ    ERR      ; JMP IF NO
        LDA    TLOC+1   ; *
        CMP    H        ; *
        JNZ    ERR      ; *
        POP    PSW      ; RESTORE PSW
        JMP    CMPOK    ; CONTINUE
;
ERR:    POP    PSW      ; RESTORE ACC
        PUSH   PSW      ; PUT IT BACK ON STK
        STA    GOODB    ; STORE GOOD BYTE
        MOV    A,M      ; GET BAD BYTE
        STA    BADB     ; STORE IT
        LDA    GOODB    ;GET GOOD BYTE
        MOV    M,A      ;FIX-UP BAD BYTE
        SHLD   ERLOC    ; STORE ERROR LOCATION
        CALL   SAVE     ; SAVE ALL ON STACK
        LDA    NTFLAG   ;GET NO TYPE FLAG
        ORA    A        ;NO TYPE?
        JNZ    CLOG     ;YES IF NOT ZERO
	LDA    CHACNT
	CPI    10H
	JZ     CLOG
	INR    A
	STA    CHACNT
        LDA    CHCNT    ;CURRENT O/P COUNT
        CPI    54       ;MAX YET?
        JC     TTNCR    ;NO IF CARRY SET
        CALL   DOCRLF   ;NEXT LINE PLEASE
TTNCR:  CALL   SPTTY    ;SPACE CARRIAGE
        LXI    H,413DH  ; A=
        CALL   HLCTTY   ; A= TO TTY
        LHLD   ERLOC    ;GET FAILING LOCATION
        CALL   HLBTTY   ;PUT IT OUT
        CALL   SPTTY    ;SPACE CARRIAGE
        LXI    H,GBM    ;GOOD/BAD MESSAGE
        CALL   TTYSTR   ;MESSAGE OUT
        LHLD   BADB     ;GET G/B BYTES
        CALL   HLBTTY   ;PUT THEM OUT
        LDA    PHASE    ;GET CURRENT PHASE
        CPI    1        ;FIRST?
        JZ     CLOG     ;RESTART IF YES
        CALL   SPTTY    ;SPACE CARRIAGE
        LXI    H,573DH  ; W=    (WALK LOCATION)
        CALL   HLCTTY   ;W= TO TTY
        LHLD   TLOC     ;GET WALK LOCATION
        CALL   HLBTTY   ;...TO TTY
CLOG:   CALL   LOG      ;GO LOG ERROR
;
RSTRT:  
        CALL   UNSAVE   ; RESTORE ALL
        POP    PSW      ; RESTORE ACC
        JMP    CMPOK    ; CONTINUE
;
SETRG:  PUSH   PSW      ;SAVE A
        CALL   INPTST   ;ESC TEST
        JZ     STCC     ;
        CPI    ESCAPE   ;
        JNZ    STCC     ;
        CALL   DOCRLF   ;
        JMP    RETURN   ;
STCC:   CPI    0AH      ;LINE FEED SAYS
        CZ     LOGOUT   ;PRINT CURRENT LOG...
        CPI    54H      ; 'T' FOR TYPE ERRORS?
        CZ     STYP     ;SET TYPE IF YES
        CPI    4EH      ; 'N' FOR NOTYPE?
        CZ     NSTYP    ;RESET TYPE IF YES
        POP    PSW      ;RESTORE A
        LHLD   INCR
        XCHG            ; DE=LOOP SIZE
        LHLD   STAD     ; HL=A(LOC TO BE TESTED)
        INR    E        ; TEST E FOR 0
        DCR    E        ; *
        RZ              ; RETURN IF DE OK
        INR    D        ; OTHERWISE ADD 1 TO D
        RET             ; AND RETURN
;
BMPPH:  CALL   DOCRLF   ;NEW LINE ON TTY
        LXI    H,PHASEM ;PHASE MESSAGE
        CALL   TTYSTR   ;MESSAGE TO TTY
        LXI    H,PHASE  ; HL=A(PHASE)
        INR    M        ; BMP PHASE BY 1
        MOV    A,M      ; GET PHASE IN ACC
        CALL   ACBTTY   ;PUT OUT PHASE NUMBER
        CMA             ; SET UP FOR OUT
        OUT    0FFH     ; WRITE PHASE NO TO LITES
        RET             ; RETURN
;
;
WALK:   CALL   BMPPH    ; BMP TO NXT PHASE
        LHLD   STAD     ; INIT TLOC
        SHLD   TLOC     ; *
        MOV    A,B      ; INIT MEM TO SET VALUE
        CALL   SETM     ; *
        JMP    WALK1    ; BEGIN WALK
        EJECT           ;
WLP1:   MOV    A,B      ; GET BASE PATTERN IN A
        CALL   CMPM     ; CHECK ALL LOCATIONS
        MOV    A,C      ; GET WALKING BIT IN A
        RRC             ; SHIFT ONE STEP
        MOV    C,A      ; RETPRN IT TO C
        XRA    B        ; DETERMINE WHERE BIT IS
        JM     WNEW     ; JMP IF BACK TO BEGINNING
WALK1:  LHLD   TLOC     ; GET A(TST LOC) IN HL
WALK2:  MOV    M,C      ; PUT WALKING BIT INTO TST LOC
	call   CheckCON ; check for console chr
        JMP    WLP1     ; GO CHECK MEMORY FOR CHANGES
	
;
WNEW:   call   CheckCON ; check for console chr
	XCHG            ; GET HI MEM LIMIT IN DE
        LHLD   TLOC     ; GET A(TST LOC) IN HL
        MOV    M,B      ; RESTORE TST LOC TO NORMAL
        INX    H        ; BMP TO NXT TST LOC
        SHLD   TLOC     ; STORE NEW TST LOC
        MOV    A,E      ; CHECK FOR END
        CMP    L        ; *
        JNZ    WALK2    ; JMP IF MORE
        MOV    A,D      ; *
        CMP    H        ; DONE?
        JNZ    WALK2    ; JMP IF NO
        RET             ; RETURN IF YES
STYP:   XRA    A        ;CLEAR A FOR TYPE FLAG
        STA    NTFLAG   ;SET TO TYPE ALL
        RET             ;
NSTYP:  MVI    A,0FFH   ;SET FLAG FOR
        STA    NTFLAG   ;  NO TYPE...
        RET             ;
;
GBM:    DB     'GB=$'    ;
PHASEM: DB     'PHASE $'       
MEMTM0: DB     '** MEMORY DIAGNOSTIC **'
	DB	0DH,0AH,0AH,'Type (ESC) to re-start.',0dh,0ah,0ah,'$'
MEMTM1: DB     'BEGINNING TEST LOCATION (IN HEX): $'
MEMTM2: DB     'TOTAL TEST LENGTH IN (HEX) BYTES: $'
MEMTM4: DB    'TEST FINISHED TEST FINISHED **** '  
	DB	  'TEST FINISHED TEST FINISHED **** '
	DB	  'TEST FINISHED TEST FINISHED **** '
	DB	  'TEST FINISHED TEST FINISHED ****$'
MEMTM5: DB     'RECORD EACH ERROR ON CONSOLE?  (Y OR N): $'
MEMTM6: DB     'TEST INCREMENT (IN HEX): $'
REPMSG: DB     'REPEAT TEST? (Y OR N): $'
RESTRT: DB     'RESTARTING$'
; SUBROUTINES FOR CHARACTER & STRING I/O
;
; SAVE & UNSAVE ROUTINES
SAVE:   SHLD   TEMPHL   ;SAVE H&L
        XTHL            ;GET RETURN, PUSH H
        PUSH   PSW      ;SAVE PSW
        PUSH   B        ;SAVE B&C
        PUSH   D        ;SAVE D&E
        PUSH   H        ;RETURN BACK ONTO STACK
        LHLD   TEMPHL   ;RESTORE ORIGINAL H&L
        RET             ;
UNSAVE: POP    H        ;RESTORE RETURN
        POP    D        ;RESTORE D&E
        POP    B        ;RESTORE B&C
        POP    PSW      ;RESTORE PSW
        XTHL            ;RETURN ONTO STACK, POP H
        RET             ;
DOCRLF: CALL   SAVE     ;SAVE ALL
        LXI    H,CRLF   ;CRLF STRING
        MVI    B,7      ;7 COUNT
        CALL   STCTTY   ;STRING TO TTY
        XRA    A        ;CLEAR AC
        STA    CHCNT    ;CLEAR LINE CHARACTER COUNT
        CALL   UNSAVE   ;RESTORE ALL
        RET             ;
SPTTY:  PUSH   PSW      ;SAVE PSW
        MVI    A,BLANK  ; 'SPACE' INTO AC
        CALL   ACCTTY   ;CHARACTER IN AC TO TTY
        POP    PSW      ;RESTORE PSW
        RET             ;
ACCTTY: PUSH   B        ;SAVE
        MOV    C,A      ;SAVE O/P CHARACTER
GETTBE:
	PUSH B! PUSH D! PUSH H
	MOV	E,C
	MVI	C,2
	CALL	BDOS
	POP	H! POP D! POP B
	mov	A,C	; get chr back in acc
	call	stobyt	; save in buffer for disk outp
        LDA    CHCNT    ;GET LINE CHARACTER COUNT
        ADI    01       ;PLUS 1
        STA    CHCNT    ;SAVE
        MOV    A,C      ;DATA TO AC AGAIN
        POP    B        ;RESTORE
        RET             ;
TTYSTR:
	PUSH	B
	XCHG
	MVI	C,9	;CP/M PRINT FUNCTION
	CALL	BDOS
	POP	B
	RET
;
INPTST:
	PUSH B! PUSH D! PUSH H
	MVI	C,11
	CALL	BDOS	
	JZ	DONE11
	MVI	C,1
	CALL	BDOS	; inputted chr is in acc
	call	stobyt	; save in buffer for disk outp
DONE11:
	POP H! POP D! POP B
	RET
STCTTY: CALL   SAVE     ;SAVE ALL
STCOUT: MOV    A,M      ;NEXT CHARACTER INTO AC
        CALL   ACCTTY   ;PUT IT OUT
        INX    H        ;NEXT MEMORY LOC
        DCR    B        ;COUNT -1
        JNZ    STCOUT   ;OUTPUT 'B' CHARACTERS
        CALL   UNSAVE   ;RESTORE ALL
        RET             ;
ACBTTY: PUSH   PSW      ;SAVE
        RRC             ;SWAP
        RRC             ; RIGHT AND LEFT
        RRC             ;  BITS WITHIN
        RRC             ;   THE BYTE.
        ANI    00FH     ;KEEP ONLY RIGHT 4 BITS
        CALL   HEXEX    ;GENERATE ASCII FROM NIBBLE
        POP    PSW      ;ORIGINAL BYTE AGAIN
        ANI    00FH     ;GET SECOND NIBBLE
        CALL   HEXEX    ;NIBBLE INTO ASCII
        RET             ;
HEXEX:  CPI    10       ;LOWER THAN 10?
        JM     CON      ;JUMP IF YES
        ADI    007H     ;
CON:    ADI    030H     ;ASCII BIAS
        JMP    ACCTTY   ;PUT OUT THIS CHARACTER
HLCTTY: PUSH   PSW      ;SAVE
        MOV    A,H      ;GET FIRST CHARACTER
        CALL   ACCTTY   ;PUT IT OUT
        MOV    A,L      ;SECOND CHARACTER
        CALL   ACCTTY   ;PUT IT OUT
        POP    PSW      ;RESTORE
        RET             ;
HLBTTY: PUSH   PSW      ;SAVE
        MOV    A,H      ;FIRST BYTE
        CALL   ACBTTY   ;PUT OUT 2 ASCII CHARACTERS
        MOV    A,L      ;SECOND BYTE
        CALL   ACBTTY   ;OUTPUT 2 MORE
        POP    PSW      ;RESTORE
        RET             ;
TTYINB:
	PUSH B! PUSH D! PUSH H
	lda	comflg	;flag for command line data
	cpi	0	;do we get data internally?
	jnz	coninb	;no, jump around this.
;----------
;If a command line option was used (H or L) then
;this routine gets the chr from the program, not crt.
;
;get the chr from either lodata or hidata
	lhld	datachr
	mov	A,M
	inx	H	;move to next data chr
	shld	datachr	;save for next time through
	push	PSW
	mov	E,A
	mvi	C,2
	call	BDOS	;output the chr. to console
	pop	PSW
	jmp	savbyt	;chr in A, proceed as usual
;----------
coninb:	
	MVI	C,1
	CALL	BDOS	; inputted chr returns in acc
savbyt:	POP H! POP D! POP B
	call	stobyt	; save in buffer for disk outp
        STA    LSTINP   ;SAVE AS LAST I/P CHARACTER
        RET             ;
HEXIN:  CALL   TTYINB   ;GET A BYTE FROM TTY
        CALL   TSTESC   ;ESCAPE TEST (GET OUT?)
        CALL   MAP      ;ASCII CHR TO HEX NIBBLE
        RLC             ;
        RLC             ;
        RLC             ;
        RLC             ;
        ANI    0F0H     ;SAVE TOP NIBBLE
        MOV    M,A      ;SAVE IN MEMORY
        CALL   TTYINB   ;GET ANOTHER TTY CHARACTER
        CALL   TSTESC   ;ESCAPE TEST (GET OUT?)
        CALL   MAP      ;ASCII CHARACTER TO HEX NIBBLE
        ANI    00FH     ;SAVE RIGHT NIBBLE
        ORA    M        ;COMBINE WITH LEFT NIBBLE
        MOV    M,A      ;BACK INTO MEMORY
        RET             ;
MAP:    PUSH   D        ;SAVE D
        MOV    D,A      ;SAVE AC
        ANI    040H     ;NUMERIC?
        MOV    A,D      ;RESTORE AC
        JZ     MAPRTN   ;OK IF NUMERIC
        SUI    001H     ;-1
        ADI    00AH     ;MAP TO A-F
MAPRTN: POP    D        ;RESTORE D
        RET             ;
TSTESC: CPI    ESCAPE   ;INPUT=ESCAPE
        JZ     CYESC    ;ESC IF ZERO
        CPI    ALTMOD   ;ALSO CK TTY ALT MODE
        RNZ             ;
CYESC:  CALL   DOCRLF   ;NEW LINE
        JMP    START    ;BACK TO COMMAND I/P
ADDRIN: CALL   HEXIN    ;GET FIRST HEX ADDRESS CHARACTER
        DCX    H        ;LOCATION FOR LOW BYTE
        CALL   HEXIN    ;GET SECOND ADDRESS CHARACTER
        RET             ;
CRLF:   DB     00AH,00DH,07FH,07FH,07FH,07FH,07FH ;
BLANK   EQU    020H          ;
BELL    EQU    007H          ;
ESCAPE  EQU    01BH     ;
ALTMOD  EQU    07DH     ;
TTYCTL  EQU    0        ;UART CONTROL PORT
TTYDTA  EQU    1        ;UART DATA PORT
;#TBE     EQU    80H      ;XMIT BUFFER EMPTY
RDA     EQU    40H      ;CHARACTER AVAILABLE
SCD     EQU    02H      ;SET CARRIER DETECT
DTR     EQU    20H      ;DATA TERMINAL READY (LOW=TRUE)
S10CPS  EQU    004H     ;
S30CPS  EQU    00       ;
HOST    EQU    001H     ;3P+S PERIPHERAL DRIVER
CHCNT:  DB     00       ;
LSTINP: DB     00       ;
TEMPHL: DW     0000     ;
LOGINT:                 ;ZERO LOG TABLE
        CALL   SAVE     ;SAVE ALL
        LXI    H,LOGTBL ;GET LOG TABLE ADDR
        XRA    A        ;ZERO A
        MOV    B,A      ;COUNT OF 256
        MVI    C,4      ;  TIMES 4 = 1024
LOGILP: MOV    M,A      ;ZERO LOCATION
        INX    H        ;NEXT LOC
        DCR    B        ;COUNT -1
        JNZ    LOGILP   ;LOOP THRU TABLE
        DCR    C        ;MAJOR COUNT -1
        JNZ    LOGILP   ;LOOP THRU 1K
        CALL   UNSAVE   ;RESTORE ALL
        RET             ;
LOG:    ; EIGHT 1K BY 1 CHIPS PER BLOCK
        CALL   SAVE     ;
        LHLD   ERLOC    ;GET LOC OF BAD BYTE
        CALL   LOGAD    ;
        LXI    H,LOGTBL ;ADDRESS OF TABLE
        DAD    D        ;GET ROW ADDRESS
        XCHG            ;SAVE IN D&E
        LHLD   BADB     ;GET BAD & GOOD BYTE
        MOV    A,H      ;PUT GOOD INTO A
        XRA    L        ;KEEP ONLY DIFFERENT BITS
        MVI    B,8      ;# OF ROW CHIPS
        XCHG            ;GET MEM ADDR BACK
BITST:  RAL             ;GET NEXT BIT IN CARRY
        JNC    NXTB     ;NEXT BIT IF OK
        PUSH   PSW      ;SAVE AC & FLAGS
        MOV    D,M      ;GET HI COUNT BYTE
        INX    H        ;TO NEXT
        MOV    E,M      ;GET LOW COUNT BYTE
        INX    D        ;BUMP COUNT
        MOV    A,D      ;CHECK
        ORA    E        ;  FOR
        JNZ    PUTC     ;    OVERFLOW
        DCX    D        ;BACK TO 65535 IF OVERFLOW
PUTC:   MOV    M,E      ;COUNT
        DCX    H        ;  BACK INTO
        MOV    M,D      ;    MEMORY
        POP    PSW      ;RESTORE AC & FLAGS
NXTB:   INX    H        ;BUMP CHIP
        INX    H        ;  POINTER
        DCR    B        ;CHIP COUNT -1
        JNZ    BITST    ;LOOP THRU CHIPS
        CALL   UNSAVE   ;RESTORE ALL
        RET             ;
LOGOUT: ; 1K X 1 LOGOUT ROUTINE
        CALL   SAVE     ;SAVE ALL
        LHLD   STAD     ;GET START ADDRESS
        CALL   LOGAD    ;
        LXI    H,LOGTBL ;GET LOGTBL ADDRESS
        DAD    D        ;LOGTBL + TEST START ADDRESS
        XCHG            ;SAVE
        LHLD   INCR     ;GET TEST INCREMENT
         MOV   A,H      ;K PART INTO A
        ANI    0FCH     ;1K BOUNDRY
        RLC             ;
        RLC             ;
        MOV    H,A      ;SAVE A
        ANI    0F0H     ;NOTHING LESS THAN 16
        MOV    L,A      ;INTO L
        MOV    A,H      ;RESTORE A
        ANI    0FH      ;GET OVERFLOW
        MOV    H,A      ;SIZE NOW IN H&L
        DAD    D        ;GET END TEST LOCATION
        XCHG            ;BEG IN H&L, END IN D&E
NCC:    MVI    B,8      ;8 CHIPS
NC:     MOV    A,M      ;GET HI COUNT BYTE
        INX    H        ;BUMP TO LOW BYTE
        MOV    A,M      ;GET LOW COUNT BYTE
	INX	H	;TO NEXT HI COUNT BYTE
        DCR    B        ;CHECK CHIPS
        JNZ    NC       ;CONT IF NOT 8 YET
        MOV    A,L      ;CHECK FOR END LOCATION
        CMP    E        ; *
        JNZ    NCC      ;NOT YET IF NOT ZERO
        MOV    A,H      ;SAME ON HI ADDRESS BYTE
        CMP    D        ; *
        JNZ    NCC      ;NOT YET IF NOT ZERO
        CALL   UNSAVE   ;RESTORE ALL
        RET             ;
LOGAD:  LXI    D,0000   ;CLEAR D&E
        MOV    A,H      ;HI-ADDR INTO A
        ANI    0FCH     ;ZAP NON 1K BOUNDRIES
        RLC             ;TIMES FOUR
        RLC             ;  (ROW INDEX)
        MOV    D,A      ;SAVE A
        ANI    0F0H     ;NOTHING LESS THAN 16
        MOV    E,A      ;INTO E
        MOV    A,D      ;RESTORE A
        ANI    0FH      ;GET OVERFLOW
        MOV    D,A      ;D&E NOW CONTAINS SIZE
        RET             ;
        DW     0000     ;CATCH ASSEMBLER BUG
;------------------
;		Subroutine: stobyt
; Regs  in: A (a console input or output character)
; Regs out: A (unchanged character)
; Regs destroyed: none
; Variables used:	bufchr	-next chr in buffer
;			bufcnt	-chr counter
STOBYT:
	push PSW ! push B ! push D ! push H
	lhld	bufchr		; get next chr addr
	mov	M,A		; write it to buffer
	inx	H		; increment buff addr
	shld	bufchr		; save next chr addr
	mov	C,A		; save chr in C
;increment counter and test for full buffer
	lda	bufcnt
	inr	A
	cpi	128		; 128 chrs ready?
	jz	Diskit		; put it on the disk
	sta	bufcnt		; save chr counter
	mov	A,C		; restore chr
	pop H ! pop D ! pop B ! pop PSW
	ret
;------------------
;		Subroutine: Diskit
; Regs  in:	None
; Regs out:	None
; Regs destroyed:	None
; Variables used:	bufchr,bufcnt
;
DISKIT:
;The 128 chr buffer (at dskbuf) is full. CONFILE.TXT
;is opened, and the next record to write, FCBrc,
;is found and loaded into FCBcr.  We write to the
;next record (dumping from the 128 chr buffer),
;then close the file.
;open the file
openf:	mvi	C,open	; prepare to open file
	lxi	D,FCBaddr
	call 	BDOS
	cpi	0FFh	; unsuccessful open?
	jnz	getrec	; no, it was AOK
	mvi	C,create; create 'confile.txt'
	lxi	D,FCBaddr
	call	BDOS
	jmp	openf	;try to open it again
;Get to last record of file and 
; find FCBrc then set FCBcr
getrec:	lxi	D,FCBrc	
	ldax	D	; get rec count in acc
	lxi	D,FCBcr	; load cur rec addr 
	stax	D	; next rec is cur rec
;set dma address
	lxi	D,dskbuf ; 128 chr buffer addr
	mvi	C,dma	; prepare to set dma
	call	BDOS
;write the record
	lxi	D,FCBaddr 
	mvi	C,wnr	;write next record
	call 	BDOS ; write buffer to disk
;check for successful write
	cpi	0	; no errors?
	;WHAT DO I DO IF THERE'S AN ERROR?
;reset dma
	lxi	D,boot+80h
	mvi	C,dma
	call	BDOS
;close file CONFILE.TXT
	lxi	D,FCBaddr
	mvi	C,close
	call	BDOS	; close the file
;------------------
;reset 128 chr buffer and reset counter
	lxi	H,dskbuf
	shld	bufchr	; reset buffer for next 128
	mvi	A,0
	sta	bufcnt	; reset counter
	pop H ! pop D ! pop B ! pop PSW
	ret
;
;
;----------------
; Subroutine:  CheckCON
; Regs  in:	none
; Regs out:	none
; Destroyed:	none
; Check for a chr ready from the console.
; Print status if a chr is found.
CheckCON:
push PSW ! push B ! push D ! push H
	mvi	C,constat
	call	BDOS
	rrc		  ; set carry if chr ready
	jnc	resume	  ; return if no chr found
	mvi	C,conin	  ; chr found
	call	BDOS	  ; read the chr
	cpi	3	  ; is chr a ^C?
	jz	WBOOT	  ; abort if ^C. 
	lxi	D,PROGmsg
	mvi	C,prtstr
	call	BDOS	  ; Print 'IN PROG' msg.
	lda	PHASE	  ; Get current phase
	call	prtchr	  ; and print it.
	lxi	D,LOCmsg
	mvi	C,prtstr
	call	BDOS	  ; Print 'CURR TEST LOC' msg
	lhld	TLOC	  ; Get Test Location in HL
	push	H
	mov	A,H
	call	prtchr	  ; print 1st byte of location
	pop	H
	mov	A,L
	call	prtchr	  ; print 2nd byte of location
	lxi	D,CARRret
	mvi	C,prtstr
	call	BDOS	  ; and space down a line
resume:	pop H ! pop D ! pop B ! pop PSW
	ret
;-------
; Sub: prtchr
; Make a hex byte an ascii byte. Print it.
prtchr:
	push	PSW
	rlc
	rlc
	rlc
	rlc
	ani	0Fh	; mask left 4 bits
	adi	90h
	daa
	aci	40h
	daa
	mov	E,A
	mvi	C,conout
	call	BDOS	; print 1st nibble
	pop	PSW
	ani	0Fh	; mask left 4 bits
	adi	90h
	daa
	aci	40h
	daa
	mov	E,A
	mvi	C,conout
	call	BDOS	; print 2nd nibble
	ret
;-------
; CheckCON Messages
PROGmsg: DB	0Dh,0Ah,' SHORT MEMORY TEST IS IN PROGRESS'
	 DB	0Dh,0Ah,' CURRENT PHASE: $'
LOCmsg:  DB	0Dh,0Ah,' CURRENT TEST LOCATION: $'
CARRret: DB	0Dh,0Ah,'$'
;
boot	equ	0
conin	equ	1
conout	equ	2
prtstr	equ	9
constat	equ	0Bh
open	equ	0Fh
close	equ	10h
create	equ	16h
wnr	equ	21	; write next record
make	equ	22
dma	equ	26
;
FCBaddr	equ	boot + 5Ch	; FCB address
FCBrc	equ	FCBaddr + 15 ; record count
FCBcr	equ	FCBaddr + 32 ; current record
FCBdata:DB	0,'CONFILE TXT',0,0,0,0,0,0,0,0 
bufchr:	DW	0	; filled in at START
bufcnt:	DB	0	; updated by stobyt,Diskit
dskbuf:	DS	128	;chr buffer for disk outp
;
;command line data addresses and definitions
;
comchr	equ	BOOT+80h
comflg:	DB	0
datachr:DW	0
data1:	DB	'100030001000yn '
data4:	DB	'400040004000yn '
data8:	DB	'800040004000yn '
dataC:	DB	'C00020001000yn '
stk:	DS	128
comstk	EQU	$
stk2:	DS	128
stack	equ	$
LOGTBL  EQU    $        ;1K FOR ERROR LOG TABLE HERE
;
        END
