;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