; << ZAP 1-K MONITOR SYSTEM >> ; by ; TECHNICAL DESIGN LABS, INC. ; RESEARCH PARK ; PRINCETON, NEW JERSEY 08540 ; ; COPYRIGHT JAN. 1977 TDL INC. ; ; ASSEMBLED by Roger Amidon ; .PREL ;THIS MONITOR SUPPLIED IN RELOCATING FORMAT ; LENGTH = Z ;SIZE OF THIS MONITOR ; .TITLE " " .SBTTL / Copyright 1977 by TECHNICAL DESIGN LABS, INC./ ; ; ;-TELEPRINTER ; TTI = 1 ;DATA IN PORT TTO = 1 ;DATA OUT PORT TTS = 0 ;STATUS PORT (IN) TTYDA = 1 ;DATA AVAILABLE MASK BIT TTYBE = 80H ;XMTR BUFFER EMPTY MASK ; RCP = 3 ;READER CONTROL PORT. ;THIS PORT IS PULSED ONCE ;FOR EACH READER REQUEST ;TO SUPPORT A CONTROLLED ;READER. ; ; ; I = 0 ;'I' REG. VALUE FALSE = 0 ;ISN'T SO TRUE = # FALSE ;IT IS SO CR = 0DH ;ASCII CARRIAGE RETURN LF = 0AH ;ASCII LINE FEED BELL = 7 ;DING RUB = 0FFH ;RUB OUT FIL = 00 ;FILL CHARACTERS AFTER CRLF MAX = 7 ;NUMBER OF QUES IN EOF ; ; ; PROGRAM CODE BEGINS HERE ; ZAP: JMP BEGIN ;GO AROUND VECTORS ; GET MEMORY SIZE, ; AND CONTINUE AHEAD ; ; ; ; THESE VECTORS MAY BE USED BY USER WRITTEN ; PROGRAMS TO SIMPLIFY THE HANDLING OF I/O ; FROM SYSTEM TO SYSTEM. WHATEVER THE CURRENT ; ASSIGNED DEVICE, THESE VECTORS WILL PERFORM ; THE REQUIRED I/O OPERATION, AND RETURN TO ; THE CALLING PROGRAM. (RET) ; ; THE REGISTER CONVENTION USED FOLLOWS- ; ; ANY INPUT OR OUTPUT DEVICE- ; CHARACTER TO BE OUTPUT IN 'C' REGISTER. ; CHARACTER WILL BE IN 'A' REGISTER UPON ; RETURNING FROM AN INPUT OR OUTPUT. ; 'CSTS'- ; RETURNS TRUE (0FFH IN 'A' REG.) IF THERE IS ; SOMETHING WAITING, AND ZERO (00) IF NOT. ; 'IOCHK'- ; RETURNS WITH THE CURRENT I/O CONFIGURATION ; BYTE IN 'A' REGISTER. ; 'IOSET'- ; I/O CANNOT BE MODIFIED IN THIS 1K VERSION ; 'MEMCK'- ; RETURNS WITH THE HIGHEST ALLOWED USER ; MEMORY LOCATION. 'B'=HIGH BYTE, 'A'=LOW. ; 'TRAP'- ; THIS IS THE 'BREAKPOINT' ENTRY POINT. ; NOT USED IN THE 1K VERSION, GOES TO THE ; 'ERROR' ROUTINE TO RESET THE MONITOR'S ; STACK. ; JMP CI ;CONSOLE INPUT JMP RI ;READER INPUT JMP CO ;CONSOLE OUTPUT JMP PO ;PUNCH OUTPUT JMP CO ;LIST OUTPUT JMP CSTS ;CONSOLE STATUS MVI A,0 ;I/O CHECK IOSET: RET ;SET TO TTY CONFIGURATION JMP IOSET ;CAN'T SET I/O ON 1K VERSION JMP MEMCK ;MEMORY LIMIT CHECK ERROR: CALL MEMSIZ ;RESET BACK TO MONITOR (TRAP) SPHL ;RE-ESTABLISH A STACK MVI C,'*' ;ANNOUNCE ERROR CALL CO JMPR START ; ; MONITOR NAME & VERSION ; MSG: .BYTE CR,LF,FIL,FIL,FIL .ASCII 'Zap V' .ASCII '2.0' ; MSGL = .-MSG ; STACK = .-2 ;A FAKE STACK TO GET STARTED ; .WORD AHEAD ;AFTER MEMORY SIZE ; AHEAD: SPHL ;SET TRUE STACK MVI B,MSGL ;SAY HELLO TO THE FOLKS CALL TOM ;OUTPUT SIGN-ON MSG START: MVI C,'>' ;PROMPT CHARACTER LXI H,START ;MAIN 'WORK' LOOP PUSH H ;SET UP A RETURN TO HERE CALL CRLF CALL CO STAR0: CALL TI ;GET A CONSOLE CHARACTER ANI 7FH ;IGNORE NULLS JRZ STAR0 ;GET ANOTHER MVI C,2 ;SET-UP C REG. CPI 'D' ;SEE IF 'DISPLAY' COMMAND JRNZ EOF ; ; THIS DISPLAYS THE CONTENTS OF MEMORY IN BASE HEX ; WITH THE STARTING LOCATION ON EACH LINE.(BETWEEN ; THE TWO PARAMETERS GIVEN). 16 BYTES PER LINE MAX. ; DISP: CALL EXLF ;GET DISPLAY RANGE ..D0: CALL LFADR ;CRLF & PRINT ADDR. ..D1: CALL BLK ;SPACE OVER MOV A,M CALL LBYTE CALL HILOX ;RANGE CHECK MOV A,L ANI 0FH ;SEE IF TIME TO CRLF JRNZ ..D1 JMPR ..D0 ; ; THIS OUTPUTS THE END OF FILE (EOF) PATTERN ; FOR THE CHECKSUM LOADER. IT IS USED AFTER ; PUNCHING A BLOCK OF MEMORY WITH THE 'W' ; COMMAND. AN ADDRESS PARAMETER MAY BE GIVEN, ; WHICH WILL BE INCLUDED IN THE END FILE. ; EOF: CPI 'E' ;SEE IF 'EOF' JRNZ FILL CALL EXPR1 ;GET OPTIONAL ADDR. CALL PEOL ;CRLF TO PUNCH MVI C,':' ;FILE MARKER CUE CALL PO XRA A ;ZERO LENGTH CALL PBYTE POP H CALL PADR ;PUNCH OPTIONAL ADDR. XRA A ;FILE TYPE=0 CALL PBYTE ;PUNCH IT JMP NULL ;TRAILER & RETURN ; ; THIS COMMAND WILL FILL A BLOCK OF MEMORY ; WITH A VALUE. IE; F0,1FFF,0 FILLS FROM ; <1> TO <2> WITH THE BYTE <3>. HANDY FOR ; INITIALIZING A BLOCK TO A SPECIFIC VALUE, OR ; MEMORY TO A CONSTANT VALUE BEFORE LOADING ; A PROGRAM. (ZERO IS ESPECIALLY USEFUL.) ; FILL: CPI 'F' ;SEE IF 'FILL' JRNZ GOTO CALL EXPR3 ;GET 3 PARAMETERS ..F: MOV M,C ;STORE THE BYTE CALL HILO JRNC ..F POP D ;RESTORE STACK JMPR START ; IN CASE OF ACCIDENTS ; ; THIS COMMAND ALLOWS EXECUTION OF ANOTHER ; PROGRAM. ; GOTO: CPI 'G' ;SEE IF 'GOTO' JRNZ TEST CALL EXPR1 ;GET AN ADDRESS TO GO TO JMP CRLF ;CRLF & EXECUTE ; ; THIS IS A 'QUICKIE' MEMORY TEST TO SPOT ; HARD MEMORY FAILURES, OR ACCIDENTLY ; PROTECTED MEMORY LOCATIONS. IT IS NOT ; MEANT TO BE THE DEFINITIVE MEMORY DIAGNOSTIC. ; IT IS, HOWEVER, NON-DESTRUCTIVE. ERRORS ARE ; PRINTED ON THE CONSOLE AS FOLLOWS- ; " 04" WHERE, IN THIS PARTICULAR ; EXAMPLE, BIT 2 IS THE BAD BIT. ; BIT LOCATION OF THE FAILURE IS EASILY ; DETERMINED. NON-R/W MEMORY WILL DISPLAY ; FF (ALL BITS BAD) ; TEST: CPI 'J' ;SEE IF 'TEST' JRNZ MOVE CALL EXLF ;GET TWO PARAMS ..T1: MOV A,M ;READ A BYTE MOV B,A ;SAVE IN B REG. CMA MOV M,A ;READ/COMPLIMENT/WRITE XRA M ; & COMPARE JRZ ..T2 ;SKIP IF ZERO (OK) EXAF ;SAVE BAD BYTE CALL HLSP ;PRINT BAD ADDR EXAF ;GET BAD BYTE BACK CALL LBYTE ;PRINT IT CALL CRLF ..T2: MOV M,B ;REPLACE BYTE CALL HILOX ;RANGE TEST JMPR ..T1 ; ; THIS COMMAND MOVES MASS AMOUNTS OF MEMORY ; FROM <1> THRU <2> TO THE ADDRESS STARTING ; AT <3>. THIS ROUTINE SHOULD BE USED WITH ; SOME CAUTION, AS IT COULD SMASH MEMORY IF ; CARELESSLY IMPLEMENTED. ; ; M<1>,<2>,<3> ; MOVE: CPI 'M' ;SEE IF 'MOVE' JRNZ READ CALL EXPR3 ;GET 3 PARAMETERS ..M: MOV A,M ;PICK UP STAX B ;PUT DOWN INX B ;MOVE UP CALL HILOX ;CHECK IF DONE JMPR ..M ; ; THIS COMMAND READS THE CHECK-SUMMED HEX FILES ; FOR BOTH THE NORMAL INTEL FORMAT AND THE TDL ; RELOCATING FORMAT. ON BOTH FILES, A 'BIAS' MAY ; BE ADDED, WHICH WILL CAUSE THE OBJECT CODE TO ; BE PLACED IN A LOCATION OTHER THAN ITS ; INTENDED EXECUTION LOCATION. THE BIAS IS ADDED TO ; WHAT WOULD HAVE BEEN THE NORMAL LOADING ; LOCATION, AND WILL WRAP AROUND TO ENABLE ; LOADING ANY PROGRAM ANYWHERE IN MEMORY. ; ; WHEN LOADING A RELOCATABLE FILE, AN ADDITIONAL ; PARAMETER MAY BE ADDED, WHICH REPRESENTS THE ; ACTUAL EXECUTION ADDRESS DESIRED. THIS ALSO MAY ; BE ANY LOCATION IN MEMORY. ; ; EXAMPLES: ; ; R[CR] =0 BIAS, 0 EXECUTION ADDR. ; R[CR] =<1>BIAS, 0 EXECUTION ADDR. ; R,[CR] =0 BIAS, <1> EXECUTION ADDR. ; R,[CR] =<1>BIAS, <2> EXECUTION ADDR. ; READ: CPI 'R' ;SEE IF 'READ' COMMAND JNZ SUBS CALL EXPR1 ;GET BIAS, IF ANY MOV A,B ;LOOK AT DELIMITER SUI CR ;ALL DONE? MOV B,A ;SET UP RELOCATION OF 0 MOV C,A ; IF CR ENTERED POP D ;BIAS AMOUNT JRZ ..R0 ;CR ENTERED CALL EXPR1 ;GET RELOCATION POP B ;ACTUAL RELOCATION VALUE ..R0: XCHG EXX ;HL'=BIAS, BC'=RELOCATION CALL CRLF LOD0: CALL RIFF ;GET A CHARACTER ANI 7FH ;KILL PARITY BIT SUI ':' ;ABSOLUTE FILE CUE? MOV B,A ;SAVE CUE CLUE ANI 0FEH ;KILL BIT 0 JRNZ LOD0 ; NO, KEEP LOOKING MOV D,A ;ZERO CHECKSUM CALL SBYTE ;GET FILE LENGTH MOV E,A ;SAVE IN E REG. CALL SBYTE ;GET LOAD MSB PUSH PSW ;SAVE IT CALL SBYTE ;GET LOAD LSB EXX ;CHANGE GEARS POP D ;RECOVER MSB MOV E,A ;FULL LOAD ADDR PUSH B ;BC'=RELOCATION PUSH D ;DE'=LOAD ADDR PUSH H ; HL'=BIAS DAD D ; BIAS+LOAD XTHL ;RESTORE HL' POP X ; X=BIAS+LOAD EXX ;DOWNSHIFT POP H ;HL=LOAD ADDR CALL SBYTE ;GET FILE TYPE DCR A ;1=REL. FILE, 0=ABS. MOV A,B ;SAVE CUE BIT POP B ;BC=RELOCATION JRNZ ..A ;ABSOLUTE FILE DAD B ;ELSE RELOCATE DADX B ;BOTH X & HL ..A: INR E ;TEST LENGTH DCR E ;0=DONE RZ DCR A ;TEST CUE JRZ LODR ;RELATIVE ..L1: CALL SBYTE ;NEXT CALL STORE ;STORE IT JRNZ ..L1 ;MORE COMING LOD4: CALL SBYTE ;GET CHECKSUM JRZ LOD0 ;GOOD CHECKSUM JMP ERROR ;BAD, ABORT LODR: MVI L,1 ;SET-UP BIT COUNTER ..L1: CALL LODCB ;GET THE BIT JRC ..L3 ;DOUBLE BIT ..L5: CALL STORE ;WRITE IT JRNZ ..L1 JMPR LOD4 ;TEST CHECKSUM ..L3: MOV C,A ;SAVE LOW BYTE CALL LODCB ;NEXT CONTROL BIT MOV B,A ;SAVE HIGH BYTE EXX PUSH B ;GET RELOCATION EXX XTHL ;INTO HL DAD B ;RELOCATE MOV A,L ;LOW BYTE CALL STORE ;STORE IT MOV A,H ;HIGH BYTE POP H ;RESTORE HL JMPR ..L5 ;DO THIS AGAIN LODCB: DCR L ;COUNT BITS JRNZ ..LC1 ;MORE LEFT CALL SBYTE ;GET NEXT DCR E ;COUNT BYTES MOV H,A ;SAVE THE BITS MVI L,8 ;8 BITS/BYTE ..LC1: CALL SBYTE ;GET A DATA BYTE SLAR H ;TEST NEXT BIT RET SBYTE: PUSH B ;PRESERVE BC CALL RIBBLE ;GET A CONVERTED ASCII CHAR. RLC RLC RLC RLC ;MOVE IT TO HIGH NIBBLE MOV C,A ;SAVE IT CALL RIBBLE ;GET OTHER HALF ORA C ;MAKE WHOLE MOV C,A ;SAVE AGAIN IN C ADD D ;UPDATE CHECKSUM MOV D,A ;NEW CHECKSUM MOV A,C ;CONVERTED BYTE POP B RET STORE: MOV 0(X),A ;WRITE TO MEMORY INX X ;ADVANCE POINTER DCR E ;COUNT DOWN RET ; ; THIS ROUTINE ALLOWS BOTH INSPECTION OF & ; MODIFICATION OF MEMORY ON A BYTE BY BYTE ; BASIS. IT TAKES ONE ADDRESS PARAMETER, ; FOLLOWED BY A SPACE. THE DATA AT THAT ; LOCATION WILL BE DISPLAYED. IF IT IS ; DESIRED TO CHANGE IT, THE VALUE IS THEN ; ENTERED. A FOLLOWING SPACE WILL DISPLAY ; THE NEXT BYTE. A CARRIAGE RETURN [CR] ; WILL TERMINATE THE COMMAND. THE SYSTEM ; ADDS A CRLF AT LOCATIONS ENDING WITH EITHER ; XXX0 OR XXX8. TO AID IN DETERMINING THE ; PRESENT ADDRESS, IT IS PRINTED AFTER ; EACH CRLF. A BACKARROW [_] WILL BACK ; UP THE POINTER AND DISPLAY THE ; PREVIOUS LOCATION. ; SUBS: CPI 'S' ;SEE IF 'SUBSTITUTE' JRNZ WRITE CALL EXPR1 ;GET STARTING ADDR. POP H ..S0: MOV A,M CALL LBYTE ;DISPLAY THE BYTE CALL COPCK ;MODIFY? RC ; NO, ALL DONE JRZ ..S1 ;DON'T MODIFY CPI '_' ;BACKUP? JRZ ..S2 PUSH H ;SAVE POINTER MVI C,1 LXI H,0 CALL EX1 ;GET NEW VALUE POP D ;VALUE IN E POP H MOV M,E ;MODIFY MOV A,B ;TEST DELIMITER CPI CR RZ ;DONE ..S1: INX H ..S3: MOV A,L ;SEE IF TIME TO CRLF ANI 7 CZ LFADR ;TIME TO CRLF JMPR ..S0 ..S2: DCX H ;DECREMENT POINTER JMPR ..S3 ;AND PRINT DATA THERE. ; ; ; THIS ROUTINE DUMPS MEMORY IN THE STANDARD ; INTEL HEX-FILE FORMAT. A START & END ; PARAMETER IS REQUIRED. AT THE CONCLUSION ; OF THE DUMP, AN "END OF FILE" SHOULD BE ; GENERATED WITH THE "E" COMMAND. ; WRITE: CPI 'W' ;SEE IF 'WRITE' COMMAND JRNZ SIZE CALL EXLF ;GET TWO PARAMETERS CALL CI ;PAUSE FOR PUNCH-ON ..W0: CALL PEOL ;CRLF TO PUNCH LXI B,':' ;START-OF-FILE CUE CALL PO ;PUNCH IT PUSH D ;SAVE PUSH H ; POINTERS ..W1: INR B ;CALCULATE FILE LENGTH CALL HILO JRC ..W4 ;SHORT FILE MVI A,24 ;24 BYTES PER FILE SUB B ;ENOUGH YET? JRNZ ..W1 ; NO. POP H ;GET START ADDR BACK. CALL ..W2 ;SEND THE BLOCK POP D ;RESTORE END OF FILE POINTER JMPR ..W0 ;KEEP GOING ..W2: MOV D,A ;INITIALIZE CHECKSUM MOV A,B ;FILE LENGTH CALL PBYTE ;PUNCH IT CALL PADR ;PUNCH ADDRESS XRA A ;FILE TYPE=0 CALL PBYTE ;PUNCH IT ..W3: MOV A,M ;GET A DATA BYTE CALL PBYTE ;PUNCH IT INX H ;POINT TO NEXT BYTE DJNZ ..W3 ;DECREMENT FILE COUNT XRA A SUB D ;CALCULATE CHECKSUM JMP PBYTE ;PUNCH IT, RETURN ..W4: POP H ;CLEAR STACK POP D ; OF POINTERS XRA A ;SET-UP A JMPR ..W2 ;FINISH UP & RETURN ; ; ; THIS IS A MESSAGE OUTPUT ROUTINE. ; IT IS USED BY THE SIGN-ON AND CRLF. ; POINTER IS IN HL (WHEN ENTERED AT ; TOM1) AND LENGTH IN B REG. ; TOM: LXI H,MSG TOM1: MOV C,M ;GET A CHARACTER INX H ;MOVE POINTER CALL CO ;OUTPUT IT DJNZ TOM1 ;KEEP GOING TILL B=0 CALL CSTS ;SEE IF AN ABORT REQUEST ORA A ; WAITING. RZ ;NO. ; ; SEE IF CONTROL-C IS WAITING ; ABORT IF SO. ; CALL CI ANI 7FH ;KILL PARITY BIT CPI 3 ;CONTROL-C? RNZ ; ERRX: JMP ERROR ; ; ; THIS GETS A READER CHARACTER, ; AND COMAPRES IT WITH 'D' REG. ; IT ABORTS ON AN 'OUT-OF-DATA' ; CONDITION. ; RIFF: CALL RI ;GET READER CHARACTER JRC ERRX ;ABORT ON CARRY CMP D ;TEST D RET ; ; THIS ROUTINE WILL RETURN THE ; CURRENT VALUE OF THE HIGHEST ; READ/WRITE MEMORY LOCATION THAT ; IS AVAILABLE ON THE SYSTEM. ; IT WILL "SEARCH" FOR MEMORY ; STARTING AT THE BOTTOM OF MEMORY ; AND GO UPWARDS UNTIL NON-R/W MEMORY ; IS FOUND. ; SIZE: CPI 'Z' ;SEE IF 'SIZE' COMMAND JRNZ UNLD CALL MEMSIZ ;GET THE VALUE ; ; ; CRLF BEFORE HLSP ROUTINE ; LFADR: CALL CRLF ; ; PRINT THE CURRENT VALUE OF H&L, ; AND A SPACE. ; HLSP: CALL LADR ; ; PRINT A SPACE ON THE CONSOLE ; BLK: MVI C,' ' ; ; THIS IS THE MAIN CONSOLE ; OUTPUT ROUTINE. ; TELEPRINTER CONFIGURATION ; I/O DRIVER. ; CO: IN TTS ANI TTYBE JRNZ CO MOV A,C OUT TTO RET ; ; SEND CRLF TO PUNCH DEVICE ; PEOL: MVI C,CR CALL PO MVI C,LF ; ; THIS IS THE 'PUNCH' OUTPUT ; DRIVER. IT IS SET UP FOR THE ; TTY PORTS, BUT MAY BE MODIFIED ; FOR ANOTHER PORT, FOR TRUE ; SEPARATION OF THE CONSOLE ; AND READER/PUNCH DEVICES. ; ; (I.E. - PORT 6 & 7 FOR CASSETTE, ETC.) ; PO: IN TTS ;STATUS PORT ANI TTYBE ;TRANSMITTER BUFFER EMPTY? JRNZ PO ;IF NOT, LOOP. MOV A,C ;GET CHARACTER TO OUTPUT OUT TTO ;TO DATA PORT RET ;DONE ; ; THIS IS A BINARY DUMP ROUTINE THAT MAY BE ; USED WITH BOTH PAPER-TAPE AND/OR CASSETTE ; SYSTEMS. IT PUNCHES A START-OF-FILE MARK ; AND THEN PUNCHES IN FULL 8-BITS DIRECTLY ; FROM MEMORY. IT IS FOLLOWED BY AN END-OF- ; FILE MARKER. THESE DUMPS MAY BE LOADED ; USING THE "L" COMMAND. THEY ARE USEFUL ; FOR FAST LOADING. ; ; U,[CR] ; PUNCHES FROM THRU ; UNLD: CPI 'U' ;SEE IF 'UNLOAD' COMMAND JRNZ NULLX CALL EXLF ;GET TWO PARAMETERS CALL CI ;PAUSE FOR PUNCH-ON (TTY) CALL LEAD ;PUNCH LEADER CALL MARK ;PUNCH FILE MARKER ..U: MOV C,M ;GET MEMORY BYTE CALL PO ;PUNCH IT CALL HILO ;SEE IF DONE JRNC ..U CALL MARK ;PUNCH END FILE MARKER JMPR NULL ; ; THIS PUNCHES NULLS (LEADER/TRAILER). ; IT RETURNS "QUIET" ; NULLX: CPI 'N' ;SEE IF 'NULL' JRNZ HEXN NULL: CALL LEAD ;PUNCH NULLS JMP STAR0 ;RETURN QUIET ; ; CONVERT HEX TO ASCII ; CBYTE: RRC RRC RRC RRC ; CONV: ANI 0FH ;LOW NIBBLE ONLY ADI 90H DAA ACI 40H DAA MOV C,A RET ; ; GET TWO PARAMETERS, PLACE ; THEM IN DE & HL, AND THEN ; CRLF. ; EXLF: CALL EXPR POP D POP H ; ; CONSOLE CARRIAGE RETURN & ; LINE FEED ROUTINE. ; ; THE NUMBER OF FILL CHARACTERS ; MAY BE ADJUSTED TO 0-3 BY THE ; VALUE PLACED IN THE B REG. MINIMUM ; VALUE FOR "B" IS TWO (2). MAXIMUM ; IS FIVE (5). ; CRLF: PUSH H ;SAVE HL PUSH B ; & BC MVI B,4 ;CRLF LENGTH (SET FOR 2 FILLS) CALL TOM ;SEND CRLF POP B POP H RET ; ; TEST THE CONSOLE'S ; KEYBOARD FOR A KEY-PRESS. ; RETURN TRUE (0FFH IN A REG) ; IF THERE IS A CHARACTER ; WAITING. ; CSTS: IN TTS ANI TTYDA MVI A,FALSE RNZ ;MAY NEED PATCHING*** CMA ;IF DIFFERENT I/O USED RET ; ; GET THREE PARAMETERS AND ; CRLF. ; EXPR3: INR C CALL EXPR CALL CRLF POP B POP D POP H RET ; ; GET ONE PARAMETER. ; NO CRLF. ; EXPR1: MVI C,1 ; ; THIS IS THE MAIN "PARAMETER-GETTING" ROUTINE. ; THIS ROUTINE WILL ABORT ON A NON-HEX CHARACTER. ; HEX CHARACTERS, AND PLACES THEM UP ON THE STACK. ; (AS ONE 16 BIT VALUE, CONTAINED IN TWO ; 8-BIT BYTES.) IF A CARRIAGE RETURN IS ENTERED, ; IT WILL PLACE THE VALUE OF "0000" IN THE STACK. ; EXPR: LXI H,0 ;INITIALIZE HL TO ZERO EX0: CALL TI ;GET SOMETHING FROM CONSOLE EX1: MOV B,A ;SAVE IT CALL NIBBLE ;CONVERT ASCII TO HEX. JRC ..EX2 ;ILLEGAL CHARACTER DETECTED DAD H ;MULTIPLY BY 16 DAD H DAD H DAD H ORA L ;OR IN THE SINGLE NIBBLE MOV L,A JMPR EX0 ;GET SOME MORE ..EX2: XTHL ;SAVE UP IN STACK PUSH H ;REPLACE THE RETURN MOV A,B ;TEST THE DELIMITER CALL QCHK JRNC ..EX3 ;DELIMITER ENTERED? DCR C ;CR, SHOULD GO TO ZERO RZ ; RETURN IF IT DOES ..EX3: JNZ ERROR ;SOMETHING WRONG DCR C ;DO THIS AGAIN? JRNZ EXPR ; YES. RET ;ELSE RETURN ; ; RANGE TESTING ROUTINES. ; CARRY SET INDICATES RANGE EXCEEDED. ; HILOX: CALL HILO RNC ;OK POP D ;RETURN ONE LEVEL BACK RET ; HILO: INX H ;INCREMENT HL MOV A,H ;TEST FOR CROSSING 64K BORDER ORA L STC ;CARRY SET=STOP RZ ;YES, BORDER CROSSED MOV A,E ;NOW, TEST HL VS. DE SUB L MOV A,D SBB H RET ;IF CARRY WAS SET, THEN STOP ; ; HEXADECIMAL MATH ROUTINE ; ; THIS ROUTINE IS USEFUL FOR ; DETERMINING RELATIVE JUMP ; OFFSETS. IT RETURNS THE SUM ; & DIFFERENCE OF TWO PARAMETERS. ; ; H, ; ; X+Y X-Y ; HEXN: CPI 'H' ;SEE IF HEX MATH JNZ LOAD CALL EXLF PUSH H ;SAVE HL FOR LATER DAD D ;GET SUM CALL HLSP ;PRINT IT POP H ;THIS IS LATER ORA A ;CLEAR CARRY DSBC D ;GET DIFFERENCE & PRINT IT ; ; PRINT H&L ON CONSOLE ; LADR: MOV A,H CALL LBYTE MOV A,L LBYTE: PUSH PSW CALL CBYTE CALL CO POP PSW CALL CONV JMP CO ; ; THIS ROUTINE SENDS EIGHT RUBOUTS ; TO THE PUNCH DEVICE. ; MARK: LXI B,08FFH ;SET-UP B&C JMPR LE0 ; ; THIS ROUTINE SENDS BLANKS TO THE ; PUNCH DEVICE. ; LEAD: LXI B,4800H ;PRESET FOR SOME NULLS LE0: CALL PO DJNZ LE0 RET ; ; THIS ROUTINE RETURNS TO A USER ; PROGRAM THE CURRENT TOP OF ; MEMORY VALUE MINUS WORKSPACE ; AREA USED BY THE MONITOR. ; MEMCK: PUSH H CALL MEMSIZ MOV B,H MVI A,0C0H ;LEAVE SOME ROOM FOR STACK POP H RET ; ; WE BEGIN IN THE MIDDLE...... ; BEGIN: MVI A,I ;INITIAL 'I' REG. VALUE STAI ;NEEDED IF USING INTERUPT. XRA A ;CLEAR READER CONTROL OUT RCP ; PORT. LXI SP,STACK ;SET UP A FAKE STACK ; .BYTE (MVI) ;SKIP OVER PUSH ; ; THIS IS A CALLED ROUTINE USED ; TO CALCULATE THE TOP OF MEMORY ; STARTING FROM THE BOTTOM OF ; MEMORY, AND SEARCHING UPWARD UNTIL ; FIRST R/W MEMORY IS FOUND, AND THEN ; CONTINUING UNTIL THE END OF THE R/W ; MEMORY. THIS ALLOWS R.O.M. AT ZERO, ; AND INSURES A CONTINUOUS MEMORY BLOCK ; HAS BEEN FOUND. ; IT IS USED BY THE ERROR ROUTINE TO ; RESET THE STACK POINTER. ; MEMSIZ: PUSH B LXI B,ZAP ;POINT TO START OF MONITOR LXI H,-1 ;RAM SEARCH STARTING PT.-1 ..M0: INR H ;FIRST FIND R/W MEMORY MOV A,M CMA MOV M,A CMP M CMA MOV M,A JRNZ ..M0 ..M1: INR H ;R/W FOUND, NOW FIND END MOV A,M CMA MOV M,A CMP M CMA MOV M,A JRNZ ..M2 MOV A,H ;TEST FOR MONITOR BORDER CMP B JRNZ ..M1 ;NOT THERE YET ..M2: DCR H ;BACK UP POP B RET ;VALUE IN HL ; ; THIS GETS A READER CHARACTER, AND ; CONVERTS IT FROM ASCII TO HEX. ; RIBBLE: CALL RIFF ANI 7FH NIBBLE: SUI '0' ;QUALIFY & CONVERT RC ;<0 CPI 'G'-'0' ;>F? CMC ;PERVERT CARRY RC CPI 10 ;NMBR? CMC ;PERVERT AGAIN RNC ;RETURN CLEAN SUI 'A'-'9'-1 ;ADJUST CPI 10 ;FILTER ":" THRU "@" RET ; ; SEND H&L VALUE TO PUNCH DEVICE ; PADR: MOV A,H CALL PBYTE MOV A,L ; ; PUNCH A SINGLE BYTE ; PBYTE: PUSH PSW ;NIBBLE AT A TIME CALL CBYTE CALL PO POP PSW ;NEXT NIBBLE PUSH PSW ;SAVE FOR CHECKSUM CALL CONV CALL PO POP PSW ;ORIGINAL BYTE HERE ADD D ;ADDED TO CHECKSUM MOV D,A ;UPDATE CHECKSUM RET ; ; COPCK: MVI C,'-' CALL CO CALL TI ; ; TEST FOR DELIMITERS ; QCHK: CPI ' ' ;RETURN ZERO IF DELIMITER RZ CPI ',' RZ CPI CR ;RETURN W/CARRY SET IF CR STC RZ CMC ;ELSE NON-ZERO, NO CARRY RET ; ; MAIN CONSOLE INPUT ROUTINE ; CI: IN TTS ANI TTYDA JRNZ CI IN TTI RET ; ; READER INPUT ROUTINE, WITH ; TIME-OUT DELAY. INCLUDES ; PULSING OF HARDWARE PORT ; TO INDICATE REQUEST FOR ; READER DATA. ; ; THIS MAY BE ALTERED TO ANY ; I/O PORT CONFIGURATION TO ENABLE ; SEPARATE READER/PUNCH DEVICE. ; RI: PUSH H MVI A,0FFH ;MAY BE ALTERED TO SUIT OUT RCP ;PULSE READER CONTROL PORT XRA A ;CLEAR IT OUT RCP MOV H,A ;CLEAR FOR TIME-OUT TEST RI0: IN TTS ;MAY BE MODIFIED *** ANI TTYDA ;BUT ALWAYS USE 'ANI' JRZ RI2 ;TO CLEAR CARRY PUSH B MVI B,0FFH ;SHORTEN FOR HIGH-SPEED DEVICE DL0: XTHL ;WASTE TIME XTHL ;FOR DELAY DJNZ DL0 POP B DCR H JRNZ RI0 RI1: STC ;*NOTE: CARRY SET TO INDICATE ; NO DATA. RI2: IN TTI RID: POP H RET ; ; THIS ROUTINE READS A BINARY FILE ; IMAGE, IN THE FORM AS PUNCHED IN ; THE "U" (UNLOAD) COMMAND. IT TAKES ; ONE PARAMETER, WHICH IS THE STARTING ; ADDRESS OF THE LOAD, AND WILL PRINT ; THE LAST ADDRESS(+1) LOADED ON THE ; CONSOLE DEVICE. ; LOAD: CPI 'L' ;SEE IF 'LOAD' COMMAND JRNZ NEXT CALL EXPR1 ;INITIAL LOAD ADDRESS POP H CALL CRLF MVI D,0FFH ;START-OF-FILE TAG ..L0: MVI B,4 ;FIND AT LEAST FOUR 0FFH'S ..L1: CALL RIFF JRNZ ..L0 DJNZ ..L1 ..L2: CALL RIFF ;4 FOUND, NOW WAIT FOR NON-0FFH JRZ ..L2 MOV M,A ;FIRST REAL DATA BYTE MVI A,BELL ;TELL TTY OUT TTO ..L3: INX H CALL RIFF JRZ ..EL ;POSSIBLE END OF FILE MOV M,A JMPR ..L3 ..EL: MVI B,1 ;INITIALIZE ..EL0: CALL RIFF JRNZ ..EL1 INR B ;COUNT QUES MVI A,MAX ;LOOK FOR EOF CMP B ;FOUND MAX? JRNZ ..EL0 ;NOPE JMP LADR ;YEP, PRINT END ADDR ..EL1: MOV M,D INX H DJNZ ..EL1 MOV M,A ;REAL BYTE JMPR ..L3 ; ; ; THIS IS THE INTERNAL KEYBOARD ; HANDLING ROUTINE. IT WILL IGNORE ; RUBOUTS (0FFH) AND BLANKS (00), ; AND IT WILL NOT ECHO CR'S & N'S. ; (NO N'S FOR THE "NULL" COMMAND). ; IT CONVERTS LOWER CASE TO UPPER ; CASE FOR THE LOOK-UP OF COMMANDS. ; ; OTHER CHARACTERS ARE ECHOED AS THEY ; ARE RECIEVED. ; TI: CALL CI ANI 7FH ;KILL PARITY BIT INR A ;IGNORE RUBOUTS RM DCR A ;IGNORE NULLS RZ CPI 'N' ;IGNORE N'S FOR NULL CMND RZ CPI 'n' JRZ ..T CPI CR ;IGNORE CR'S RZ PUSH B MOV C,A CALL CO MOV A,C POP B CPI 'A'-1 ;CONVERT TO UPPER CASE RC CPI 'z'+1 RNC ..T: ANI 05FH RET ; ; ; ; NEXT: RET ;ADDITIONAL COMMANDS ;MAY BE TESTED FROM HERE, ;AND THE MONITOR EXTENDED ;FROM BEYOND THIS POINT. ; ; Z: ;END OF PROGRAM ; ; ; .END ZAP