
;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
; CONVERTED TO TDL AZM FORMAT KGH 6/22/82
;***
	.PABS
	.PHEX
STRTAD	==	100H
BDOS	==	0005H
WBOOT	==	0000H
CR	==	0Dh
LF	==	0Ah
WBOOT	==	0
	.LOC   STRTAD
comcheck:
	CALL	START
	CALL	TEST1
	CALL	TEST4
	CALL	TEST8
	CALL	TESTC
RETURN: JMP	WBOOT
;----------
;low memtest option
TEST1:	lxi	H,data1
	shld	datachr	;set pointer to data1
	jmp	BEGIN
;high memtest option
TEST4:	lxi	H,data4
	shld	datachr	;set pointer to data4
	jmp 	BEGIN
;higher memtest option
TEST8:	lxi	H,data8
	shld	datachr	;set pointer to data8
	jmp	BEGIN
TESTC:	lxi	H,dataC
	shld	datachr	;set pointer to dataC
	jmp	BEGIN
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	
	RET
;------------------
STAD:	.word 	0000	;START ADDRESS
SIZE:	.word 	0000	;SIZE TO BE CHECKED
INCR:	.word 	0000	;TEST INCREMENT
;
BADB:	.byte 	0	;BAD BYTE
GOODB:	.byte 	0	;PATTERN BEING TESTED
ERLOC:	.word 	0	;ADDRESS OF BAD BYTE
TLOC:	.word 	0	;WALKING BIT PATTERN
RECORD:	.word 	0000	;
BMPCNT:	.word 	0000	;
COUNT:	.word 	0000	;
ENDAD:	.word 	0000	;ADDRESS OF LAST LOC+1
SAVAD:	.word 	0000	;SAVE INITIAL STARTAD
SPSAVE:	.word 	0000	;SAVE INITIAL STACK POINTER
;
PHASE:	.byte 	0	;PHASE ID
;stack defined at bottom of program
;
;
BEGIN:
	ei		; enable interupts
	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   ; *
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
        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   ;
        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    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:  LDA    PHASE    ; PUT PHASE BACK IN LITES INVERTED
        OUT    0FFH     ; *
        CALL   UNSAVE   ; RESTORE ALL
        POP    PSW      ; RESTORE ACC
        JMP    CMPOK    ; CONTINUE
;
SETRG:  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
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
;
GBM:    .byte   3
	.ASCII	'GB='    
PHASEM: .byte   6
	.ASCII	'PHASE '       
MEMTM0: .byte   23
	.ASCII	'** MEMORY DIAGNOSTIC **'
MEMTM1: .byte   34
	.ASCII	'BEGINNING TEST LOCATION (IN HEX): '
MEMTM2: .byte   34
	.ASCII	'TOTAL TEST LENGTH IN (HEX) BYTES: '
MEMTM4: .byte   130
	.ASCII	'TEST FINISHED TEST FINISHED **** '  
	.ASCII 	'TEST FINISHED TEST FINISHED **** '
	.ASCII  'TEST FINISHED TEST FINISHED **** '
	.ASCII  'TEST FINISHED TEST FINISHED **** '
MEMTM6: .byte   25
	.ASCII	'TEST INCREMENT (IN HEX): '
REPMSG: .byte   25
	.ASCII	[CR][LF]'REPEAT TEST? (Y OR N): '
RESTRT: .byte   10
	.ASCII	'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        ;SAVE B&C
        MOV    B,M      ;GET MSG COUNT
        INX    H        ;BUMP TO MSG PROPER
        CALL   STCTTY   ;CHARACTER STRING TO TTY
        POP    B        ;RESTORE B&C
        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:   .byte      00AH,00DH,07FH,07FH,07FH,07FH,07FH ;
BLANK    =     020H          ;
BELL     =     007H          ;
ESCAPE   =     01BH     ;
ALTMOD   =     07DH     ;
TTYCTL   =     0        ;UART CONTROL PORT
TTYDTA   =     1        ;UART DATA PORT
;#TBE      =     80H      ;XMIT BUFFER EMPTY
RDA      =     40H      ;CHARACTER AVAILABLE
SCD      =     02H      ;SET CARRIER DETECT
DTR      =     20H      ;DATA TERMINAL READY (LOW=TRUE)
S10CPS   =     004H     ;
S30CPS   =     00       ;
HOST     =     001H     ;3P+S PERIPHERAL DRIVER
CHCNT:  .byte      00       ;
LSTINP: .byte      00       ;
TEMPHL: .word      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
        CALL   DOCRLF   ;NEW LINE
        CALL   DOCRLF   ;   "
NCC:    MVI    B,8      ;8 CHIPS
NC:     MOV    A,M      ;GET HI COUNT BYTE
        CALL   ACBTTY   ;PUT IT OUT
        INX    H        ;BUMP TO LOW BYTE
        MOV    A,M      ;GET LOW COUNT BYTE
        CALL   ACBTTY   ;PUT IT OUT
	CALL	SPTTY	;SPACE
	INX	H	;TO NEXT HI COUNT BYTE
        DCR    B        ;CHECK CHIPS
        JNZ    NC       ;CONT IF NOT 8 YET
        CALL   DOCRLF   ;NEW LINE
        CALL   DOCRLF   ;   "
        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   DOCRLF   ;NEW LINE
        CALL   DOCRLF   ;   "
        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             ;
        .word      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: .byte 	0Dh,0Ah
	.ASCII	' SHORT MEMORY TEST IS IN PROGRESS'
	 .byte 	0Dh,0Ah
	.ASCII	' CURRENT PHASE: $'
LOCmsg:  .byte 	0Dh,0Ah
	.ASCII	' CURRENT TEST LOCATION: $'
CARRret: .byte 	0Dh,0Ah
	.ASCII	'$'
;
boot	 = 	0
conin	 = 	1
conout	 = 	2
prtstr	 = 	9
constat	 = 	0Bh
open	 = 	0Fh
close	 = 	10h
create	 = 	16h
wnr	 = 	21	; write next record
make	 = 	22
dma	 = 	26
;
FCBaddr	 = 	boot + 5Ch	; FCB address
FCBrc	 = 	FCBaddr + 15 ; record count
FCBcr	 = 	FCBaddr + 32 ; current record
FCBdata:.byte 	0
	.ASCII	'CONFILE TXT'
	.BYTE	0,0,0,0,0,0,0,0 
bufchr:	.word 	0	; filled in at START
bufcnt:	.byte 	0	; updated by stobyt,Diskit
dskbuf:	.blkb 	128	;chr buffer for disk outp
;
;command line data addresses and definitions
;
comchr	 = 	BOOT+80h
comflg:	.byte 	0
datachr:.word 	0
data1:	.ASCII 	'100030001000 '
data4:	.ASCII 	'400040004000 '
data8:	.ASCII 	'800040004000 '
dataC:	.ASCII 	'C00020001000 '
stk:	.blkb 	128
Šcomstk	 = 	.
stk2:	.blkb 	128
stack	 = 	.
LOGTBL   =     .        ;1K FOR ERROR LOG TABLE HERE
;
.END

