home
***
CD-ROM
|
disk
|
FTP
|
other
***
search
/
ftp.barnyard.co.uk
/
2015.02.ftp.barnyard.co.uk.tar
/
ftp.barnyard.co.uk
/
cpm
/
walnut-creek-CDROM
/
CPM
/
MEMTEST
/
BRAINWSH.ASM
< prev
next >
Wrap
Assembly Source File
|
2000-06-30
|
37KB
|
1,133 lines
;BBBB RRRR AAA III N N W W AAA SSS H H
;B B R R A A I NN N W W A A S S H H
;B B R R A A I N N N W W A A S H H
;BBBB RRRR A A I N NN W W W A A S HHHHH
;B B R R AAAAA I N N W W W AAAAA S H H
;B B R R A A I N N W W W A A S S H H
;BBBB R R A A III N N WWW A A SSS H H
;
;
;A Z80 PROGRAM TO TEST MEMORY RIGOROUSLY AND QUICKLY
;RUN WITH NO M1 WAIT STATES TO FIND SLOW CHIPS
;
;last modified 8 jun 1981 at nosc hawaii to configure for that system
;
;A SERIALIZED CIPHER IS HIDDEN IN THIS PROGRAM BY WHICH IT MAY BE
;TRACED TO THE SOURCE OF ITS RELEASE.
;
;
ORG 0100H
CR EQU 0DH
LF EQU 0AH
TCR EQU 8DH ;WITH BIT 7 SET FOR TERMINATING STRINGS
TLF EQU 8AH
TSP EQU 0A0H
MAXADR EQU 0FFFFH ;64K IF NO MEMORY MAPPED IO
START JR ST1 ;JUMP AROUND DATA AREA
GIL equ 1 ;home system configuration
ZOBEX equ 0 ;nosc configuration
;USER'S JUMP TABLE GOES HERE
ORG 106H
INIT: JP INITX
CHKIN: JP CHKINX
CRTO: JP CRTOX
PRTO: JP PRTOX
FREEMEM:DEFW ENDOFIT
PBYTE: JP CRTOX ;SWITCH FOR PRINTER OR CRT
FIRST DEFW 0 ;FIRST ADDR TO TEST
LAST DEFW 0 ;LAST ADR TO TEST
NEX1K DEFW 0 ;NEXT 1K CHUNK FOR XTALK
END1K DEFW 0 ;END OF 1K CHUNK
NBYTES DEFW 0 ;LAST - FIRST +1
ITER DEFB 0 ;NO OF TIMES TO DO TEST
CTR DEFB 0 ;COUNTER FOR ITERATIONS
ERCTR DEFW 0 ;ERROR COUNTER
TYCTR DEFB 0 ;COUNTS ADDRESS TYPEOUTS IN XTALK
TESTAD DEFW 0 ;CURRENT ADR FOR IBUS TEST
BYTCNT DEFW 0 ;# BYTES LEFT TO TEST
LONGI: DEFB 0FFH ;FF IF LONG TEST NOT WANTED, 0 IF IT IS
XTLK: DEFB 0FFH ;FF IF XTALK TESTS NOT WANTED
CONTMD: DEFB 0FFH ;FF IF CONTINUOUS MODE NOT WANTED
ST1 LD SP,STACK ;GIVE STACK 64 BYTES OF ROOM
XOR A ;CLEAR A
LD DE,STAKBAK
LD HL,STACK-3 ;LEAVE ROOM FOR THE CALL
CALL SADEHL ;ZERO STACK AREA
CALL INIT ;DO WHATEVER HOUSEKEEPING IS NEEDED
LD HL,HITHERE
CALL GETANS
JP NZ,ST2
LD HL,(PRTO+1) ;GET PRINTER ADDRESS
JP ST3
ST2: LD HL,(CRTO+1) ;GET CRT ADDRESS
ST3: LD (PBYTE+1),HL ;PUT CRT OR PRT ADR IN VECTOR
LD HL,NOTMSG
CALL TYPMSG
LD HL,START
CALL TYPSHL ;TYPE BEGIN OF PROGRAM
LD HL,(FREEMEM) ;DON'T TEST BELOW END PROGRAM
CALL TYPSHL
LD HL,ENTMSG
CALL TYPMSG ;TYPE ENTRY MESSAGE
CALL GETHEX ;GET FIRST ADDRESS
LD (FIRST),HL ;STORE FIRST ADDRESS
CALL GETHEX ;GET LAST ADDRESS
LD (LAST),HL ;STORE LAST ADDRESS
LD HL,(LAST) ;COMPUTE NBYTES
LD BC,(FIRST)
AND A ;CLEAR CARRY FLAG
SBC HL,BC ;DO SUBTRACT
INC HL ;ADD ONE
LD (NBYTES),HL ;STORE NBYTES TO TEST
;
LD HL,ITMSG
CALL TYPMSG ;TYPE ITERATIONS MESSAGE
CALL GETHEX ;GET FROM TERMINAL
LD A,L
LD (ITER),A ;MAX IS FF
LD HL,LNGMSG
CALL GETANS ;ASK IF WANT LONG IBUS TEST
LD (LONGI),A ;STORE 0 IF YES, FF IF NO
LD HL,XTKMSG
CALL GETANS ;ASK IF WANT CROSSTALK TESTS
LD (XTLK),A
LD HL,CONMSG
CALL GETANS ;ASK IF WANT TO TEST FOREVER
LD (CONTMD),A
LD HL,0
LD (ERCTR),HL ;CLEAR ERROR COUNTER
;NOW BEGIN TESTING
;
; ZEROES AND ONES TEST
;
;
; STORE ALL ZEROES THRU AREA
;
; READ BACK AND TEST
;
;
; STORE ALL ONES THRU AREA
;
; READ BACK AND TEST
;
;
; RECYCLE N ITERATIONS
;
;
;DO ZEROES AND ONES TEST FIRST
BIGLP: CALL SETCNT ;SET CTR TO ITERATIONS
LD HL,ZMSG
CALL TYPMSG
T1 LD A,0 ;START WITH ZEROES
CALL STR ;STORE IN WHOLE AREA
CALL RD ;CHECK FOR ERRORS
LD A,0FFH ;NOW DO ALL ONES
CALL STR
CALL RD
CALL NTERUP ;SEE IF ANYTHING TYPED
CALL CKCNT ;SEE IF CTR IS ZERO YET
JR NZ,T1 ;GO BACK AND DO IT AGAIN
;
; INCREMENTING BYTE TEST
;
;
; STORE 1 TO FF (NEVER 00) IN CONSECUTIVE BYTES
;
; (USE CPI TO VERIFY STORED CORRECTLY)
;
; REPEAT TIL END OF AREA
;
;
; READ BACK AND TEST FOR KNOWN VALUES
;
; RECYCLE N ITERATIONS
;
;
;DO ROTATING PATTERN TEST
CALL SETCNT ;SET CTR FOR INCREMENTING PATTERN TEST
LD HL,INCMSG ;NOW DO INCREMENTING PATTERN
CALL TYPMSG ;TYPE INCREMENTING PATTERN TEST
T2 CALL STRROT ;STORE PATTERNS
CALL RDROT ;TEST THEM
CALL NTERUP ;SEE IF BOSS WANTS TO STOP
CALL CKCNT ;SEE IF ITERATIONS DONE
JR NZ,T2 ;NOT YET
;
;
; PART A: (NOP TEST)
;
; STORE FF EVERYWHERE EXCEPT PROGRAM
;
; SET UP 38H TO JP XYZ
;
; STORE NO-OP (00 BYTE)
;
; STORE RST 38H (FF BYTE) IN NEXT BYTE
;
; LOAD REGISTERS WITH KNOWN PATTERN
;
; JP NO-OP
;
;
; XYZ: TEST TO SEE IF CAME FROM RIGHT PLACE
;
; TEST TO SEE IF REGISTERS CHANGED
;
; SET 00 BYTE TO FF (UNLESS DOING LONG MODE)
;
; INDEX UP ONE BYTE AND REPEAT
;
;
;
; PART B: (INSTRUCTION TEST)
;
; SET UP AS FOR PART A
;
;
; STORE SHORT PROGRAM THAT TRANSFERS DATA AND SHIFTS
;
; SET UP REGISTERS WITH KNOWN PATTERNS
;
; CALL PROGRAM
;
;
; SEE IF CAME BACK PROPERLY
;
; TEST REGISTERS FOR PROPER VALUES
;
; INDEX TO NEXT BYTE AND REPEAT TO END OF AREA
;
; RECYCLE N ITERATIONS
;
;
;DO INSTRUCTION READUP TESTS
;THIS TEST IS DEATH ON SLOW MEMORY CHIPS BECAUSE THE Z80 WITH
;NO M1 WAIT STATES NEEDS MEMORY ACCESS TIME UP TO 130 NS FASTER
;ON INSTRUCTION READUP THAN IT DOES FOR OPERAND READ/WRITE.
;THIS TEST WRITES IN ALL RAM MEMORY EXCEPT THE PROGRAM AREA
;IN ORDER TO DEFEND AGAINST WHAT BAD INSTRUCTION READUP CAN
;DO TO A PROGRAM. VERY VERY BAD CHIPS CAN STILL WIPE OUT
;THE PROGRAM THEORETICALLY, ALTHOUGH IT HAS NOT BEEN OBSERVED
;SINCE THE LATEST BULLETPROOF STACK CODE HAS BEEN ADDED.
;
SLOCHIP XOR A ;CLEAR TYPEOUT COUNTER
LD (TYCTR),A
CALL SETCNT ;PRESET COUNT OF ITERATIONS
LD HL,IBUSMS ;TYPE TEST WE'RE DOING
CALL TYPMSG
LD A,0FFH ;STORE FF EVERYWHERE
LD DE,0
LD HL,START-1
CALL SADEHL ;STORES FF FROM ZERO TO BASE
LD DE,(FREEMEM) ;FIRST BYTE OF FREE MEMORY
LD HL,MAXADR ;END OF ALLOWED RAM SPACE
CALL SADEHL ;FROM END OF PROGRAM TO END OF MEMORY
IBUS: LD DE,(FIRST)
LD HL,(LAST)
LD A,0FFH
CALL SADEHL ;STORE FF IN TEST MEMORY
LD HL,(NBYTES)
LD BC,LNGTH
AND A ;CLEAR CARRY
SBC HL,BC ;LEAVE ROOM FOR TEST PROGRAM
LD (BYTCNT),HL ;SAVE BYTES LEFT TO TEST
LD HL,(FIRST)
LD (TESTAD),HL ;SAVE CURRENT TEST ADDRESS
LD (GOTHAR+1),HL ;IN CASE DO LONG TEST ALWAYS JUMP TO BEGIN
NOPFF: LD (HL),00H ;NO OP
INC HL
LD (HL),0FFH ;RESTART 38H
DEC HL
LD A,(LONGI) ;GET LONG TEST FLAG
OR A ;IF 0 WE'LL DO IT
JR Z,YLI ;JUMP AROUND STORE OF PLACE TO JUMP
LD (GOTHAR+1),HL ;PRESET JSR
YLI: LD A,0C3H ;JP INST
LD (38H),A ;STORE AT RESTART 38H LOCATION
LD HL,TESTO ;PLACE TO GO
LD (39H),HL ;STORE IT
CALL LDEM ;LOAD UP REGS WITH KNOWN PATTERN
GOTHAR: JP 0 ;PLACE TO GO GETS STORED HERE
;
;
TESTO: LD IX,NOPMSG ;MESSAGE OF WHICH TEST FAILED
CALL ICHECK ;SEE IF REGS ARE OK
POP HL ;GET RETURN ADR FROM STACK
DEC HL
DEC HL
PUSH HL ;SAVE WHERE CAME FROM
LD DE,(TESTAD) ;WHERE WE SHOULD HAVE COME FROM
AND A
SBC HL,DE
JR Z,REAL ;IF CAME FROM RIGHT PLACE
LD HL,LOSTMSG
CALL LOSTIT ;OOPS
;
;NOW TRY A FEW REAL INSTRUCTIONS
;
REAL:
LD SP,STACK
LD DE,(TESTAD)
LD HL,TESTCOD
LD BC,LNGTH
LDIR ;BLOCK MOVE PROGRAM TO TEST AREA
LD HL,(TESTAD)
LD (CALLIT+1),HL ;THIS TIME WE'LL DO A CALL
LD A,0C3H ;JP
LD (38H),A
LD HL,WILDBLUE
LD (39H),HL ;IN CASE FLY OFF THE HANDLE SOMEWHERE
CALL LDEM ;LOAD UP REGISTERS
CALLIT CALL 0 ;HERE WE GO - I HOPE
;SHOULD COME BACK HERE IF CODE IS EXECUTED ANYTHING LIKE RIGHT
CUMBAK: LD SP,STACK ;IN CASE STACK GOT CLOBBERED BY BAD MEM
LD IX,EXMSG ;TEST THAT FAILED MESSAGE
CALL ICHECK ;SEE IF REGS ARE WHAT THEY SHOULD BE
LD HL,(TESTAD)
LD A,(HL)
CP 0AAH ;SEE IF SWAP GOT DONE RIGHT
CALL NZ,ERR9
INC HL ;POINT TO NEXT BYTE
LD A,(HL)
CP 0AAH
CALL NZ,ERR9
DUNONE: CALL NTERUP ;SEE IF OP WANTS ANYTHING
LD HL,(TESTAD) ;GET HL BACK
LD BC,(BYTCNT) ;GET BC BACK
LD A,(LONGI) ;0 IF LONG TEST WANTED
LD (HL),A ;SET 00 OR FF WHERE INST WAS
CPI ;HL UP, BC DOWN
LD (TESTAD),HL ;UPDATE TEST ADDRESS
LD (BYTCNT),BC ;UPDATE # BYTES LEFT TO TEST
JP PE,NOPFF ;GO BACK FOR MORE
THRU1: CALL NTERUP
LD A,(TYCTR) ;UPDATE TIMES TYPED
INC A
LD (TYCTR),A
AND 1FH ;USE 5 BITS TO COUNT TO 32
CALL Z,CRLF ;THAT'S ENOUGH
LD HL,SPIMSG ;TYPE SPACE I TO INDICATE ONE PASS
CALL TYPMSG
CALL CKCNT
JP NZ,IBUS ;GO BACK FOR ANOTHER PASS
JP GWRT ;GO TO CROSSTALK TESTS
RDYGO: DEFM 'READY TO LEAP?',CR,LF
TESTCOD:NOP
NOP
LD A,E
RLA
LD IX,5555H
LD HL,0AAAAH
LD SP,(TESTAD)
INC SP
INC SP ;SO WILL PUSH TO FIRST TWO BYTES
PUSH IX
EX (SP),HL ;HL_5555, (TESTAD)_AAAA
LD SP,STACK-2
TESTND: RET ;RETURN TO CALLER
LNGTH: EQU TESTND-TESTCOD+1
;
;STORES A FROM ADR IN DE THRU ADR IN HL
SADEHL: AND A ;CLEAR CARRY
SBC HL,DE
INC HL ;#BYTES TO STORE
LD B,H
LD C,L ;TO BYTE COUNTER
EX DE,HL ;GET WHAT WAS IN DE
PUTIT: LD (HL),A
CPI
JP PE,PUTIT ;LOOP BACK TIL DONE
RET
;
;LOADS REGISTERS WITH KNOWN PATTERN
;
LDEM LD A,0B4H ;AS GOOD A NUMBER AS ANY
LD BC,0BBCCH
LD DE,0DD5AH
LD HL,5555H
OR A ;CLEAR CARRY BIT
RET
;
;CHECKS CONTENTS OF REGISTERS TO SEE THEY ARE WHAT SHOULD BE
;
ICHECK: JR C,ERR1 ;CARRY SHOULD NOT BE SET
CP 0B4H
JR NZ,ERR2 ;A SHOULD BE B4
LD A,B
CP 0BBH
JR NZ,ERR3
LD A,C
CP 0CCH
JR NZ,ERR4
LD A,D
CP 0DDH
JR NZ,ERR5
LD A,E
CP 5AH
JR NZ,ERR6
LD A,H
CP 55H
JR NZ,ERR7
LD A,L
CP 55H
JR NZ,ERR8
RET ;NO ERRORS IF GOT THIS FAR
ERR1 LD HL,CBIT
JR TYERR
ERR2 LD HL,ACHNG
JR TYERR
ERR3 LD HL,BCHNG
JR TYERR
ERR4 LD HL,CCHNG
JR TYERR
ERR5 LD HL,DCHNG
JR TYERR
ERR6 LD HL,ECHNG
JR TYERR
ERR7 LD HL,HCHNG
JR TYERR
ERR8 LD HL,LCHNG
JR TYERR
ERR9: LD HL,EXSP
;ENTERED WITH IX POINTING AT MESSAGE ABOUT WHICH TEST FAILED
;HL POINTS TO ERROR MESSAGE
;
TYERR: CALL CRLF
PUSH HL
PUSH IX
POP HL ;GET WHICH TEST FAILED IN HL
CALL TYPMSG ;TYPE IT
LD HL,(ERCTR) ;GET NO OF ERRORS SO FAR
INC HL
LD (ERCTR),HL ;UPDATE IT
CALL TYPSHL ;TYPE NO OF ERRORS
CALL SPACE
POP HL
CALL TYPMSG ;HL POINTS TO MESSAGE
CALL SPACE
LD A,'@'
CALL PBYTE
LD HL,(TESTAD) ;WHERE WE WERE TESTING WHEN THINGS GOT BAD
CALL TYPSHL ;TYPE THIS ADDRESS
CALL NTERUP ;SEE IF STOP AFTER THIS ERROR
RET
;
;TYPES WHERE WE WERE WHEN WE GOT LOST, AND MAYBE
;WHERE WE GOT TO MORE OR LESS
LOSTIT: CALL TYERR
LD HL,TOMSG ;TYPE "TO"
CALL TYPMSG
POP HL ;PASS BY RETURN ADR ON STACK
POP HL ;GET FROM WHENCE WE WENT TO 38H
DEC SP
DEC SP
DEC SP
DEC SP ;GET STACK BACK IN SHAPE
CALL TYPSHL ;TYPE IT
CALL NTERUP
RET
;
;COME HERE FROM INSTRUCTION TEST IF DIDN'T DO NORMAL RETURN
WILDBLUE: LD IX,EXMSG ;TEST WHICH FAILED
CALL ICHECK
LD HL,LOSTMSG
CALL LOSTIT ;TYPE WHAT LITTLE WE KNOW ABOUT IT
POP HL ;STACK CLEANUP
POP HL ;STACK CLEANUP
JP DUNONE ;GIVE UP ON THIS ADDRESS, GO TO NEXT
;
;BEGIN CROSSTALK TESTS (RUNNING TIME GOES UP EXPONENTIALLY)
;
;ONLY EXECUTES THESE TWO TESTS ONCE, REGARDLESS OF INTERATION COUNTER
;BECAUSE THEY ARE SO LONG RUNNING. WILL NOT DO TEST AT ALL UNLESS AREA
;IS AT LEAST 400H (1024) IN SIZE.
;
; EXPONENTIAL WRITE TEST
;
;
; ZERO THE AREA
;
; CLEAR INDEX 1
;
;
; LOOP1: STORE FF BYTE (INDEX 1)
;
; CLEAR INDEX 2
;
;
; LOOP2: STORE 00 (INDEX 2)
;
; SEE IF FF STILL OK
;
; BUMP INDEX 2
;
; LOOP2 TIL END OF AREA
;
;
; BUMP INDEX 1
;
; LOOP1 TIL END OF AREA
;
; EXIT TO EXPONENTIAL READ TEST
;
;
GWRT: XOR A ;CLEAR TYPEOUT COUNTER
LD (TYCTR),A
LD A,(XTLK) ;SEE IF WANT TO DO THESE TESTS AT ALL
OR A ;SET FLAGS
JP NZ,DONE ;NOT WANTED
T3 LD HL,GWRMSG
CALL SETUP ;GET AREA DEFINED, ETC
WLP0: CALL COMCOD ;LOOP HOUSEKEEPING SUBR
JP C,STRD ;DONE IF MINUS
LD DE,(NEX1K) ;DE KEEPS TRACK OF WHERE THE FF IS
WLP2: CALL TYPEAD ;TYPE ADDRESS IF MULTIPLE OF 100H
LD HL,(NEX1K) ;STARTING ADR OF 1K CHUNK
LD BC,03FFH ;ALWAYS 1 K CHUNKS
LD A,0FFH
LD (DE),A ;STORE THE FF BYTE
WMLP XOR A ;CLEAR A
LD (HL),A ;STORE A ZERO BYTE WHERE HL IS
LD A,(DE) ;GET SUPPOSED FF BYTE
CP 0FFH ;SEE IF IT STILL IS FF
JR NZ,WOOPS ;MAYBE OK, MAYBE NOT
XOR A ;CLEAR A AGAIN
WLP1 CPI ;COMPARE A & (HL), DEC BC
JP PO,WEND1 ;THRU AREA?
JR Z,WMLP ;CHECK NEXT ADDRESS
CALL ERR ;BYTE WASN'T ZERO
JR WMLP
;
WOOPS AND A ;CLEAR CARRY FLAG
PUSH HL ;SAVE ADDRESS POINTER
SBC HL,DE ;COMPARE TO WHERE FF SUPPOSED TO BE
POP HL ;GET POINTER BACK
JR NZ,WERR ;REAL ERROR, IT WASN'T HERE
LD A,0FFH ;NOW RESTORE THE CLOBBERED FF
LD (DE),A
JR WLP1 ;KEEP GOING
;
WERR INC HL ;SIMULATE ACTION OF CPI ON HL
CALL ERR ;TYPE OUT THE ERROR
JR WMLP
;
WEND1 LD HL,(END1K) ;SEE IF WE'RE THRU THE AREA YET
AND A ;CLEAR CARRY
SBC HL,DE ;COMPARE
JR NZ,KG1 ;NOT DONE YET
CALL UPDATE ;SET NEXT 1K CHUNK
JR WLP0 ;CONTINUE TESTING WITH NEXT CHUNK
KG1: INC DE ;UP POINTER TO FF BYTE
JR WLP2
;
;
; EXPONENTIAL READ TEST
;
;
; ZERO THE AREA
;
;
; LOOP1: STORE FF (INDEX 1)
;
; CLEAR INDEX 2
;
;
; LOOP2: READ BYTE (INDEX 2)
;
; TEST FOR CORRECTNESS
;
; SEE IF FF STILL OK
;
; BUMP INDEX 2
;
; LOOP2 TIL END OF AREA
;
;
; BUMP INDEX 1
;
; LOOP1 TIL END OF AREA
;
; EXIT
;
;
;EXPONENTIAL READ CROSSTALK TEST
;
STRD LD HL,GRDMSG
CALL SETUP
RDLP0: CALL COMCOD
JR C,DONE ;YES
LD DE,(NEX1K) ;DE KEEPS TRACK OF FF BYTE
STLP: CALL TYPEAD ;TYPE ADDRESS EVERY 100H
LD HL,(NEX1K) ;BEGIN PASS AT FIRST BYTE
LD BC,03FFH ;ALWAYS TEST 1K
LD A,0FFH ;ALL ONES
LD (DE),A ;STORE FF IN (DE)
XOR A ;CLEAR A
MLP CPI ;SEE IF THIS BYTE IS ZERO
JP PO,END1 ;AT END OF AREA IF PO
JR Z,MLP ;KEEP LOOKING FOR FF OR END OF AREA
MAYBE PUSH HL ;SAVE NEXT BYTE TO TEST
DEC HL ;TO GET BACK TO BYTE JUST TESTED
AND A ;CLEAR CARRY FLAG
SBC HL,DE ;SEE IF WHERE FF WAS SUPPOSED TO BE
JR NZ,ERROR ;NO, THIS IS AN ERROR FOR SURE!
POP HL
JR MLP ;FF WAS SUPPOSED TO BE HERE
END1: LD HL,(END1K)
AND A ;CLEAR CARRY FLAG
SBC HL,DE
JR NZ,KG2 ;IF NOT DONE WITH 1K CHUNK YET
CALL UPDATE
JR RDLP0
KG2: LD A,(DE) ;GET THE SUPPOSED FF BYTE
CP 0FFH ;SEE IF IT STILL IS FF
JR NZ,ERROR ;LOST THE FF
XOR A ;CLEAR A
LD (DE),A ;CLEAR THE FORMER FF BYTE
INC DE
JR STLP ;END OF ONE LOOK, GO STORE FF IN NEXT BYTE
;
;
;END OF ONE PASS OF SAND DUNE TESTS
DONE LD HL,DUNMSG
CALL TYPMSG
LD HL,ERCTR
LD A,(ERCTR+1)
ADD A,(HL)
OR A
JR Z,MEMOK ;ERROR COUNTER WAS ZERO
LD HL,BADMSG
D1: CALL TYPMSG
LD HL,(ERCTR)
CALL TYPSHL
LD HL,ERSMSG
CALL TYPMSG ;TYPE TOTAL NO OF ERRORS
LD A,(CONTMD) ;SEE IF WANT TO TEST FOREVER
OR A
JP Z,BIGLP ;YES, GO ANOTHER ROUND OF INTERATIONS
JP START ;GO BACK AND ASK FOR MORE
MEMOK: LD HL,OKMSG
JR D1 ;TYPE GOOD MESSAGE
ERROR POP HL
CALL ERR
JP MLP
; TYPES TEST NAME, CLEARS AREA, SETS FIRST 1K CHUNK ADDRESS
SETUP: CALL TYPMSG ;TYPE TEST NAME
CALL CLAREA ;ZERO THE TEST AREA
LD HL,(FIRST) ;STARTING ADDRESS
LD (NEX1K),HL ;PRESET
RET
;CONTROLS TEST AREA IN 1K CHUNKS AT A TIME TO KEEP
;RUNNING TIME REASONABLE SINCE IT GOES UP AS THE SQUARE
;OF THE NUMBER OF BYTES TESTED. RETURNS NEGATIVE FLAG
;WHEN TOTAL AREA FINISHED.
COMCOD: LD HL,(NEX1K) ;GET START OF 1K CHUNK TO TEST
LD DE,03FFH
ADD HL,DE ;COMPUTE LAST ADR OF 1K CHUNK
LD (END1K),HL ;SAVE IT
EX DE,HL ;END1K TO DE
LD HL,(LAST)
AND A ;CLEAR CARRY
SBC HL,DE ;SEE IF THROUGH TOTAL AREA YET
RET ;RETURN C IF DONE
CLAREA LD A,0 ;CLEARS THE TEST AREA TO ZEROES
CALL STR
RET
SETCNT LD A,(ITER) ;GET ITERATIONS DESIRED
LD (CTR),A ;STORE IN CTR
RET
;
CKCNT LD HL,CTR ;POINT AT CTR
DEC (HL) ;DECREMENT THE COUNT
RET ;WITH THE FLAGS SET
;STORE A PATTERN ROUTINE
STR LD DE,(FIRST) ;GET BEGINNING
LD HL,(LAST)
CALL SADEHL
RET
;READ AND TEST PATTERN
RD LD HL,(FIRST)
LD BC,(NBYTES)
RD1 CPI ;SEE IF SAME AS A
CALL NZ,ERR
JP PE,RD1
RET
;TYPE OUT ERROR
;HL HAS ADDRESS OF FAILURE
;A HAS GOOD BYTE
ERR PUSH HL ;SAVE WHERE WE'RE AT
PUSH AF ;SAVE A AND FLAGS
DEC HL ;GET ACTUAL ADR WHERE FAILED
PUSH HL
CALL CRLF
LD HL,(ERCTR) ;# SO FAR
INC HL ;ADD THIS ONE
LD (ERCTR),HL ;STORE IT BACK
CALL TYPSHL ;TYPE # OF ERRORS SO FAR
POP HL ;GET ADDRESS OF FAILURE
CALL TYPSHL
CALL SPACE
LD A,(HL) ;GET BAD BYTE
CALL P2HEX
LD HL,SHDBE
CALL TYPMSG ;TYPE SHOULD BE
POP AF ;GET A BACK
PUSH AF
CALL P2HEX ;TYPE GOOD BYTE
CALL NTERUP ;SEE IF WANT TO STOP A WHILE
POP AF
POP HL
RET
;STORE INCREMENTING PATTERN
STRROT LD A,0
LD HL,(FIRST)
LD BC,(NBYTES)
ROT1 INC A
JR Z,ROT1 ;NEVER USE ZERO
LD (HL),A ;STORE BYTE
CPI ;CK IT ALREADY
CALL NZ,ERR ;WOOPS
JP PE,ROT1
RET
;CHECK INCREMENTING PATTERNS
RDROT LD A,0
LD HL,(FIRST)
LD BC,(NBYTES)
RDROT1 INC A ;NEXT PATTERN
JR Z,RDROT1 ;NEVER ALLOWED ZERO
CPI
CALL NZ,ERR
JP PE,RDROT1
RET
;UPDATE POINTER TO NEXT 1K CHUNK OF MEMORY TO TEST
;
UPDATE: LD HL,(END1K) ;UPDATE FOR NEXT 1K CHUNK
INC HL
LD (NEX1K),HL
RET
;
;ROUTINE TO TYPE ADDRESS EVERY 100H (FROM DE)
TYPEAD: LD A,E
CP 0 ;SEE IF A MULTIPLE OF 100H
RET NZ ;NO, DON'T BOTHER TO TYPE ADDRESS YET
CALL NTERUP ;SEE IF WANT TO WAIT A BIT
LD H,D ;GET NEXT ADDRESS IN HL
LD L,E
CALL TYPSHL
LD A,(TYCTR) ;GET NUMBER OF TIMES THIS LINE
INC A
LD (TYCTR),A ;UPDATE IT
AND 0FH ;ONLY USE LOWER 4 BITS
RET NZ ;LESS THAN 16 TIMES
CALL CRLF ;16 X 5 = 80 AND THAT'S ENUF PER LINE
RET
;
;ROUTINE TO SEE IF ANYTHING BEEN TYPED FROM KEYBOARD.
;RETURNS IMMEDIATELY IF NOT. IF C/R, RESTART PROGRAM
;FROM SQUARE ONE. IF ?, TYPE LOCATION CURRENTLY TESTING,
;IF ANYTHING ELSE, JUST DELAY TIL
;ANOTHER KEY STRUCK.
NTERUP: CALL CHKIN ;SEE IF ANYTHING BEEN TYPED?
RET Z ;NO
AND 7FH ;GET RID OF PARITY BIT IF ANY
CP '?' ;SEE IF WANT TO FIND OUT WHERE
JP Z,WHRWE
CP 0DH ;SEE IF C/R
JP Z,START ;START ALLL OVER
LD HL,INTMSG ;TYPE "INTERRUPTED"
CALL TYPMSG
NTW CALL CHKIN ;WAIT FOR ANOTHER CHARACTER
RET NZ ;GOT ONE
JR NTW ;UNTIL WE GET ANY CHARACTER TO RESTART
WHRWE: LD HL,WHRMSG
CALL TYPMSG
LD HL,(TESTAD) ;GET ADDRESS CURRENTLY TESTING
CALL TYPSHL
RET
;TYPES MESSAGE POINTED BY HL, GETS A CHARACTER FROM KBD,
; AND RETURNS WITH A REG =0 IF CHAR WAS A Y, ELSE A=FF
; Z FLAG WILL BE SET IF YES, NZ SET IF NOT YES
GETANS: CALL TYPMSG ;TYPE MESSAGE
CALL GCHR ;GET ANSWER FROM KBD
PUSH AF ;SAVE IT
CALL CRLF ;FOR NEATNESS
POP AF
CP 'Y' ;DID OP TYPE A Y
JR Z,GOTYES
CP 'y' ;CK FOR LOWER CASE TOO
GOTYES: LD A,0
RET Z ;ANSWER WAS Y
LD A,0FFH
RET ;ANSWER WAS NOT Y
;
; GET CHARACTER FROM INPUT.
;
GBYTE: CALL CHKIN
JR Z,GBYTE ;NOT READY YET
AND 7FH ;STRIP OFF BIT 7?????
RET
;
SPACE: LD A,20H ;FALLS THRU TO PCHR
;
;PRINTS CHARACTER IN A, PLUS LINEFEED AND 2 NULLS IF
;CHAR IS A CARRIAGE RETURN. PRESERVES ALL REGISTERS
;
PCHR: PUSH AF
PUSH HL
AND 7FH
CALL PBYTE ;PRINT THE CHAR
LD HL,LFNN
CP CR ;WAS IT A C/R?
CALL Z,TYPMSG ;PRINT LINE FEED AND 2 NULLS
POP HL
POP AF
RET
;
LFNN: DEFB 8AH
;
; GET CHARACTER. RETURNS IT IN A.
; ALTERS F.
;
GCHR: CALL GBYTE
CALL PCHR
JR Z,GCHR ;IF NULL DON'T RETURN
CP 61H ;SEE IF LOWER CASE
JR C,SK2 ;LESS THAN LC A
CP 7BH ;SEE IF MORE THAN Z
JR NC,SK2 ;NOT A LOWER CASE
SUB 20H ;CONVERT TO UPPER CASE
SK2 RET
;
;
; CRLF. ALTERS A ONLY.
;
CRLF: LD A,CR
JR PCHR
;
;
; GETS A 4 DIGIT (OR LESS) HEX NUMBER FROM
; KEYBOARD INTO HL. IGNORES LEADING SPACES
; CONTINUES UNTIL A NON-HEX CHARACTER IS TYPED.
; RETURNS WITH THE LATTER IN A, AND HL SET TO
; THE LAST 4 HEX DIGITS (OR LESS) TYPED.
; LOSES AF AND HL
;
;
GETHEX: SUB A
;
GNHL: PUSH BC ;SAVE
LD HL,0 ;CLR BUFFER
; STRIP LEADING SPACES & GET CHAR
CALL SKSG
; FIRST CHAR MUST BE HEX
CALL HEXSH ;IF HEX, SHIFT INTO HL
JP C,HEXERR ;O/W, HEXERR
GN1: CALL GCHR
CALL HEXSH ;IF HEX SHIFT INTO HL
LD A,B ;RESTORE CHAR
JR NC,GN1 ;IF HEX, CONTINUE
POP BC ;IF NON-HEX, DONE
RET
HEXERR LD A,'?'
CALL PBYTE
CALL CRLF
JR GETHEX ;RESTART
;
;
; IF A CONTAINS HEX CHAR, SHIFTS BINARY EQUIVALENT
; INTO HL. IF NOT HEX, RET WITH CY SET. SAVES
; ORIGINAL CHAR IN B
;
HEXSH: LD B,A
SUB '0' ; < '0'?
RET C
ADD A,'0'-'G'
RET C
SUB 'A'-'G'
JR NC,HX1 ;OK IF >= 'A'
ADD A,07H; 'A'-'9'+1
RET C
HX1: ADD A,'9'+1-'0'
; THE A-REG NOW CONTAINS THE HEX DIGIT IN BINARY.
; (THE HIGH-ORDER NIBBLE OF A IS 0.)
HXSH4: ADD HL,HL ;SHIFT 4 BITS INTO HL
ADD HL,HL
ADD HL,HL
ADD HL,HL
OR L
LD L,A
RET
;
;
; RETURNS WITH A NON-SPACE IN THE A-REG.
; IF ENTERED WITH A-REG CONTAINING A NULL
; OR A SPACE, GETS NEW CHARS UNTIL FIRST
; NON-SPACE OCCURS. ALTERS AF.
;
SKSG0: SUB A
;
SKSG: OR A ;DOES A CONTAIN NULL?
SK1: CALL Z,GCHR ;YES
CP 20H ;SPACE?
JR Z,SK1 ;YES, KEEP LOOKING
CP ',' ;PASS BY COMMAS TOO
JR Z,SK1
CP CR ;RETURNS ZFLAG IF CR
RET
;
;
; PRINT THE NUMBER IN HL.
; PRESERVES ALL BUT A.
;
TYPSHL: CALL SPACE
;
PNHL: LD A,H
CALL P2HEX
LD A,L
; ;(CONTINUE BELOW)
;
; PRINT THE NUMBER IN THE A-REGISTER.
; PRESERVES ALL REGISTERS.
;
P2HEX: CALL P1HEX
RRA
P1HEX: RRA
RRA
RRA
RRA
PUSH AF
AND 0FH ;MASK
CP 10D ; <= 9?
JR C,PH1
ADD A,7 ;A THRU F
PH1: ADD A,30H ;ASCII BIAS
CALL PCHR ;PRINT IT
POP AF
RET
;
;
; PRINT MESSAGE. ENTER WITH ADDR OF MSG
; IN HL. THE MESSAGE IS TERMINATED
; AFTER PRINTING A NULL (00) CHARACTER OR ONE WHOSE
; BIT 7 WAS SET.
; PRESERVES FLAGS, INCREMENTS HL.
;
;
;
TYPMSG: PUSH AF ;SAVE
PS1: LD A,(HL)
INC HL
CALL PCHR
OR A ;SET FLAGS
JR Z,PS2 ;NULL CHARACTER, EXIT
RLA ;LAST CHARACTER?
JR NC,PS1 ;IF NOT, LOOP
PS2: POP AF
RET
;
DUNMSG DEFB LF
DEFB CR
DEFB ' FINISHED'
DEFB CR
DEFB TLF
ERSMSG: DEFB ' TOTAL ERRORS'
DEFB CR
DEFB TLF
SHDBE DEFB ' SHOULD BE'
DEFB TSP
ENTMSG DEFB LF
DEFB CR
DEFB '"FIRST LAST" ? ?'
DEFB TSP
ZMSG DEFB 'TESTING ZEROES, THEN ONES'
DEFB LF
DEFB TCR
INCMSG DEFB 'INCREMENTING BYTE TEST'
DEFB LF
DEFB TCR
IBUSMS: DEFB LF
DEFB CR
DEFB 'IBUS TEST'
DEFB CR
DEFB TLF
NOPMSG: DEFB 'FAILED NOP TEST'
DEFB TSP
EXMSG: DEFB 'FAILED INST TEST'
DEFB TSP
GRDMSG DEFB LF
DEFB CR
DEFB 'CROSSTALK READ TEST'
DEFB LF
DEFB TCR
GWRMSG DEFB LF
DEFB CR
DEFB 'CROSSTALK WRITE TEST'
DEFB LF
DEFB TCR
ITMSG DEFB 'ITERATIONS? (1 TO FF)'
DEFB TSP
HITHERE:DEFB CR
DEFB LF
DEFB 'BRAINWASH 2.3 - Copyright 1979 by Jim Gilbreath'
DEFB CR
DEFB LF
DEFM 'OUTPUT TO PRINTER?',CR,LF
NOTMSG: DEFB 'DONT TEST 38-3A OR FRO'
DEFB 0CDH
INTMSG: DEFB LF
DEFB CR
DEFB 'INTERRUPTED'
DEFB CR
DEFB TLF
LOSTMSG DEFB ' FLEW AWA'
DEFB 0D9H
CBIT: DEFB 'CARRY GOT SE'
DEFB 0D4H
ACHNG: DEFB 'A CHANGE'
DEFB 0C4H
BCHNG: DEFB 'B CHANGE'
DEFB 0C4H
CCHNG: DEFB 'C CHANGE'
DEFB 0C4H
DCHNG: DEFB 'D CHANGE'
DEFB 0C4H
ECHNG: DEFB 'E CHANGE'
DEFB 0C4H
HCHNG: DEFB 'H CHANGE'
DEFB 0C4H
LCHNG: DEFB 'L CHANGE'
DEFB 0C4H
EXSP: DEFM 'EX (SP),HL failed'
TOMSG: DEFB ' T'
DEFB 0CFH
LNGMSG: DEFB 'LONG INST TEST? (Y/N)'
DEFB TSP
XTKMSG: DEFB 'DO CROSSTALK TESTS? (Y/N)'
DEFB TSP
CONMSG: DEFB 'TEST FOREVER? (Y/N)'
DEFB TSP
BADMSG DEFB 'POOR MEMORY!'
DEFB 0ACH ;COMMA
OKMSG DEFB 'GOOD MEMORY'
DEFB 0ACH ;COMMA
SPIMSG: DEFB ' '
DEFB 0C9H ;I+80H
WHRMSG: DEFM CR,LF,'Testing'
STAKBAK DEFS 64 ;STACK BETTER NOT GET ANY LOWER THAN THIS
STACK: DEFB 0
; I/O PACKAGE
IF GIL ;home configuration
STAT EQU 1 ;STATUS PORT
DATA EQU 0
DAV EQU 2
TBE EQU 1
PRSTAT EQU 3
PRDAT EQU 2
PRTBE EQU 1
INITX: ;DO HOUSEKEEPING
DI ;TURN OFF INTERRUPTS
LD A,1 ;TO DISABLE ROM SO ALL RAM CAN BE TESTED
OUT (1FH),A ;FOR GILBREATH CPU
OUT (7FH),A ;FOR SSM ROM BOARD
RET
ENDIF ;gil
IF ZOBEX ;nosc system
stat equ 1 ;crt status port
data equ 0 ;crt data port
dav equ 1 ;bit mask for kbd input active
tbe equ 4 ;bit mask for tx buffer empty
prstat equ 3 ;printer status port
prdat equ 2 ;printer data port
prdav equ 1 ;printer input mask
prtbe equ 4 ;printer tx buffer empty bit mask
initx: ;do housekeeping
ld a,1 ;to disable rom so all ram can be tested
out (0ch),a ;for zobex cpu board
ret
ENDIF ;zobex
; CHECK INPUT & RETURN WITH DATA IF READY. ONLY REG CHANGE IS A.
;
CHKINX: IN A,(STAT)
AND DAV
RET Z ;DATA NOT READY, RETURN WITH Z FLAG SET
IN A,(DATA) ;RETURN WITH DATA AND Z FLAG CLEARED
RET
;
; TYPE CHARACTER. CHANGE NO REGISTERS.
;
CRTOX: PUSH AF
PBY1: IN A,(STAT)
AND TBE
JR Z,PBY1
POP AF
OUT (DATA),A
RET
PRTOX: ;PRINT CHARACTER, CHANGE NO REGISTERS
IF ZOBEX
push af ;save char
in a,(prstat) ;get printer port status
and prdav ;see if got char
jr z,list1 ;no
in a,(prdat)
and 7fh
cp 'S'-40h ;see if stop code
jr nz,list1
plist2: in a,(prstat) ;got a stop, wait til next one
and prdav
jr z,plist2 ;loop til get char
in a,(prdat)
and 7fh
cp 'Q'-40h ;see if go code
jr nz,plist2 ;loop til get it right
list1: in a,(prstat)
and prtbe ;ck busy bit
jr z,list1 ;loop til bit goes hi meaning ready
pop af ;get char to print
out (prdat),a ;send character
ret
ENDIF ;zobex
IF GIL
ret ;no printer in here as yet
ENDIF; gil
ENDOFIT:DEFB 0 ;FIRST MEMORY AVAILABLE TO TEST
SIZE EQU ENDOFIT-START ;NUMBER OF TOTAL BYTE IN PROGRAM
END