PAGE * * ******************************************* * * * * * COMMAND INTERPRETER * ********************* * * * SOME CHARACTERS * CR EQU 13 ASCII CR LF EQU 10 ASCII LF SEMI EQU 59 SEMICOLON COMMA EQU ',' SLASH EQU '/' NSIGN EQU '#' ZCHR EQU '0' ASTRC EQU '*' * ********************* * * * EOF ON INPUT FILE, IF CIFILE = 0 (CONSOLE), THEN * DO A CLOSE ALL, ELSE DO A SHORT RESET. * CIEIF LDA CIFILE ORA A CHECK FOR ZERO JNZ USRES NOT ZERO, DO A SHORT RESET TO MOVE THE CONSOLE MVI A,255 CLOSE ALL FILES CALL SYS DB CAOP JMP CIABT JMP USRES WHY NOT? * ********************* * * * "RETURN" ENTRY * * PROCESS NEXT COMMAND, IF ANY * IF NONE, RETYPE PROMPT * RETURN LXI SP,CISTK CALL INRST RESET INT TRAPS LHLD CRTRAP CHECK RETURN TRAP INX H IF =-1, NOTHING TO DO MOV A,H ORA L JZ CI50 NONE DCX H <> -1, JUMP TO ADDRESS PUSH H HERE WE GO LXI H,-1 SHLD CRTRAP CLEAR TRAP RET . GO TO TRAPPER * ********************* * * * SET ERROR TRAPS TO CI STANDARD AND RESET INT TRAPS * CIRST LXI H,0 SHLD AERR SHLD FERR DCX H SHLD EERR * * RESET BOTH INTERRUPT TRAPS * * RETURN HL=-1 * INRST LXI H,0 SHLD DSKRD SET DISKREADY TO 0 DCX H NOW FOR -1 SHLD BDSK1 SHLD BDSK2 RET . MUST RETURN WITH -1 * ********************* * * * ECHO CHARACTER TO CI LOG FILE * * COME WITH CHAR IN A, AND RETURN THAT WAY * CRECHO MVI A,CR ENTRY POINT TO ECHO A CARRIAGE RETURN * ECHOUT MOV B,A LDA ECFILE CALL WB WRITE IT OUT CALL CI98 PANIC!!! MOV A,B RET * ********************* * * * RETURN AND SET TRAP * * COME HERE WITH TRAP ADDRESS IN USER HL * RETRAP LHLD UHL * SET CRTRAP AND FALL INTO CI SHLD CRTRAP * ********************* * * * READ AND PROCESS A COMMAND * CI LXI SP,CISTK SETUP STACK * CI50 LXI H,CIMSG RESET PROMPT STRING SHLD TDPRO CALL CIRST * * EAT LEADING BLANKS AND ","'S * CI51 CALL CIBNK JZ CIEIF ZERO INDICATES EOF CALL CIBUP WASN'T " " OR ","... BACK UP 1 CHAR * * ECHO THE COMMAND * LDA SWECH RRC JNC CI59 NO ECHO LXI H,0 SHLD CECT SET COUNT TO ZERO * CI53 LDA ECFILE GET ECHO FILE NUMBER DCR A CZ CRECH DO A CR IF IT'S #1 XRA A STA CERC CRLF COUNT TO ZERO * CI55 LDA CIFILE CALL RB JMP CI57 CALL ECHOUT PRINT CHAR LHLD CECT INX H SHLD CECT INCREMENT CHARACTER COUNT * CPI CR JZ CI58 CR -- DONE CPI ';' JZ CI57 ; -- DONE * LXI H,CERC INR M BUMP LINE POSITION MVI A,72 DO AUTO CRLF FOR TTY'S ETC CMP M JNC CI55 NOT PAST, KEEP GOING CALL CRECH PAST 70, TYPE CR JMP CI53 LOOP * ********************* * * * DONE WITH ECHO, MOVE BACK * CI57 CALL CRECHO TYPE A CR * CI58 LHLD CECT MOV B,H MOV C,L BC HAVE NUMBER OF CHARACTERS TYPED LDA CIFILE MVI D,128 CALL SYS DB SPAOP SPACE BACK JMP CIABT ERROR- CAN'T BACK UP * * * * INITIALIZE FOR COMMAND READ * CNBF EQU DKBUF PUT NAME OUT OF THE WAY! * CI59 LXI H,CNBF SHLD CPNT SET STORAGE POINTER MVI A,NMLEN+2 STA CICNT SET MAX CHAR COUNT MVI A,1 STA XQFLG SET XEQ FLAG * * YES, HERE WE AGAIN EAT BLANKS AND COMMAS * CALL CIBNK JZ USRES END OF FILE JMP CI65 GO PROCESS THE FIRST CHR * * * READ COMMAND * CI60 LDA CIFILE CALL RB JMP USRES SHORT RESET TO CONSOLE * CI65 CPI CR JZ CI68 ITS A CR, GO PROCESS CPI SEMI JZ CI68 ITS A SEMICOLON, GO PROCESS CPI BLNK JZ CI71 SPACE, GO PROCESS CPI COMMA JZ CI67 MOV B,A LDA CICNT ORA A ANY MORE CHARACTERS NEEDED? JZ CI60 NO, JUST IGNORE DCR A STA CICNT YES, COUNT DOWN LHLD CPNT MOV M,B STORE CHARACTER INX H MVI M,0 SHLD CPNT UPDATE POINTER JMP CI60 * * * COMMA, INHIBIT EXECUTION * CI67 XRA A STA XQFLG JMP CI71 GO PROCESS * ********************* * * * EAT COMMA'S AND SPACES FROM CI FILE * CIBNK LDA CIFILE CALL RB NOP XRA A SET UP FOR EOF RETURN RET CPI BLNK JZ CIBNK CPI COMMA RNZ JMP CIBNK LOOP FOR " ","," OR EOF * ********************* * * * BACKUP ONE CHARACTER IN CIFILE * CIBUP LDA CIFILE LXI B,1 MVI D,128 CALL SYS DB SPAOP BACKUP 1 CHAR JMP CIABT SERIOUS ERROR RET * ********************* * * * CLOSE LOAD FILE * CICLO LDA CICNT CALL SYS CLOSE DB CLOOP JMP CIABT ERROR RET * ********************* * * * PROCESS COMMAND * * COME HERE FOR CR AND ; * BACKUP SO ROUTINE CAN SEE THE CHARACTER * CI68 LDA CICNT CHECK FOR NULL COMMAND CPI NMLEN+2 CNZ CIBUP BACKUP IF NON-NULL, IF NULL FOLLOWING TEST WILL * DO. CI71 LDA CICNT CPI NMLEN+2 CHECK FOR NULL COMMAND JZ RETURN YES * * OPEN FILE * LXI D,CNBF NAME POINTER CI71A LXI H,-1 SHLD AERR GET MOST ERRORS INX H =0, SYSTEM BUFFER OPTION CALL SYS OPEN FILE DB OPEOP JMP CIOER TRY TO REPORT THE ERROR * STA CICNT SAVE FILE NUMBER LXI H,0 SHLD AERR SET NORNAL ERROR TRAPPING * * CHECK FILE TYPE * LDA FTYPE ANI IMTYPE JNZ CI94 NOT IMAGE FILE, CANT LOAD * * LOAD THE FILE * CI75 LDA CICNT GET FILE NUMBER LXI B,4 4 BYTES LXI D,CBUF INTO CBUF CALL SYS READ BLOCK DB RBLOP JMP CI80 EOF ENCOUNTERED * * * NORMAL RETURN...GET COUNT AND DEST * LHLD CBUF WE READ IT TO HERE MOV B,H MOV C,L BC HAVE COUNT LHLD CBUF+2 HL GET DESTINATION MOV A,B CHECK FOR ZERO COUNT ORA C JZ CI96 YES, PROBABLY UTILITY LDA CICNT A WILL BE NUMBER XCHG . DE HAVE ADDRESS CALL SYS A STILL HAS NUMBER DB RBLOP JMP CI89 BAD LOAD FILE JMP CI75 OK, DO NEXT BLOCK * ********************* * * * CHECK FOR SELF START * CI80 CPI EER0 CHECK FOR EOF JNZ CI98 NOT EOF, VERY BAD MOV A,C CPI 2 ARE 2 BYTES LEFT JZ CI95 YES, SELF START * * CLOSE FILE * CALL CICLO LDA XQFLG IF XQFLG=0 (=> COMMA), ORA A THEN JUST HANDLE NEXT JZ CI59 WITHOUT ECHO JMP RETURN TRY NEXT COMMAND * ********************* * * CI94 MVI A,CIER1 NOT IMAGE FILE JMP CI90 * * * BAD LOAD FILE, CLOSE FIRST * CI89 MVI A,CIER0 * * COME HERE WITH ERROR # IN A * * CI90 PUSH PSW SAE ERROR NUMBER CALL CICLO CLOSE THE LOAD FILE POP PSW A = ERROR # * CIOER STA ERCD SET ERROR NUMBER FOR UTILITY CALL MVI A,CCLDE =CODE FOR LOADER STA EOPR SET OPERATION MVI A,0 MESSAGE AND NO RETURN LXI H,CNBF -> FILE NAME JMP ERRP9 GIVE MESSAGE * ********************* * * * CATESTROPHIC ERROR * CI98 POP H SHOW ADDRESS CI99 MVI A,CSER0 CATESTROPHIC * ********************* * * * ABORT. USE EXISTING REGISTERS * CIABT PUSH PSW RESTORE ECHO FILE TO CONSOLE MVI A,1 STA ECFILE POP PSW CALL SYS DB ABTOP * ********************* * * * * START UP USER PROGRAM * * CLOSE THE FILE * CI95 CALL CICLO LHLD CBUF SET START ADDRESS * * COME HERE WITH HL EQUAL TO START ADDRESS * THE FILE WILL NOT BE CLOSED * CI96 LDA XQFLG ORA A JZ CI59 COMMAND ENDED WITH "," - LOAD NEXT FILE LDA XA PUSH H LHLD XHL RET * PAGE * * ******************************************* * * * * * CONSOLE TELETYPE DRIVER * * SSTA EQU 0FAH SOL STATUS PORT USTA EQU 0 UDAI EQU 0FCH SOL INPUT PORT UDAO EQU 1 INRDY EQU 1 SOL READY BIT OTRDY EQU 128 * BUFT EQU 80 BUFFER SIZE IN BYTES (255 MAX) BUFT2 EQU 40 OUTBUF SIZE * ********************* * * DRIVER TABLE * TDRIV DW TDRL READ BLOCK DW TDRL READ NEXT DW IDAC READ LAST, NO CAN DO DW TDWL WRITE BLOCK, NEXT DW TDWL WRITE BLOCK DW TDNGO REWIND DW TDNGO EOF DW TDNGO CLOSE DW IDAC SEEK DW TDCTL CONTROL DW 0 BUFFER SIZE HOLDER DB 1 IMMEDIATE TRANSFER OPTION DW TDNGO INITIALIZE, ETC... A CONVINIENT RETURN * ******************************************* * * * * CONSOLE INPUT DRIVER DISPATCH POINT * CONIN LDA STFLG CHARACTER WAITING? ORA A JZ CONI1 NO XRA A =0 STA STFLG CLEAR FLAG LDA INBYT RETURN WAITING CHR JMP CONI2 GO * ********************* * * * GET CHR FROM RCH DRIVER * CONI1 PUSH H SAVE HL LXI H,CONI2 SETUP RETURN POINT XTHL . RETURN ADDRESS NOW ON STACK PUSH H LHLD RCH GET READ CHARACTER ADDRESS XTHL . GET BACK HL TDNGO RET . DISPATCH TO RCH * ********************* * * * RETURN HERE WITH CHARACTER IN A * CONI2 STA CONCH SAVE IT AWAY PUSH B DON'T DISTURB BC CALL UPSH UPSHIFT CHARACTER LDA CONCH BINARY, RELOAD CHAR POP B NON-BINARY RETURN STA INBYT SAVE BYTE FOR POSSIBLE LATER USE RET * ********************* * * * READ SINGLE BYTE * CIRCH CALL CITCH GET THE STATUS JZ CIRCH WAIT IN UDAI READ IT PUSH PSW SAVE FOR SWITCH TEST LDA SWBIO BINARY I/O? RRC JC CIR20 YES! POP PSW NO ANI 127 MASK PARITY RET * * CIR20 POP PSW RET * ******************************************* * * * CONSOLE STATUS TEST DISPATCH POINT * CONST PUSH H SAVE HL LXI H,CONT20 PUSH H SETUP RETURN ADDRESS LHLD SCH PCHL . DISPATCH TO SCH * * * COME HERE AFTER TEST WITH Z/NZ SET * CONT20 POP H RESTORE HL JNZ CONT30 GOT A CHARACTER WAITING, USE IT LDA STFLG NO REAL CHAR, WHAT ABOUT A PSEUDO ONE ORA A RET . GO WITH FLAGS SET * * * A REAL CHAR, CLEAR PSEUDO CHAR FLAG * CONT30 XRA A STA STFLG INR A DON'T FORGET ABOUT THE REAL ONE RET * * * CONSOLE TEST INPUT CHAR * CITCH IN SSTA CMA ANI INRDY RET . FLAGS SET * ******************************************* * * * * CONSOLE OUTPUT CHARACTER ROUTINES * CONOUT STA CONCH SAVE CHARACTER CALL UPSH UPSHIFT CHARACTER JMP CON40 RETURN HERE => BINARY SWITCH SET, JUST OUTPUT STA CONCH SAVE UPDATED CHARACTER * * IF CR, SET CRSEEN FLAG AND OUTPUT NULLS * CPI CR JNZ CON20 NOT A CR STA CRSEEN SET FLAG JMP CON90 OUTPUT THE CHARACTER * * * NOT A CR, SEE ABOUT LF * CON20 CPI LF JZ CON30 YES, IT WAS * * NOT A LF, IF LAST WAS CR, OUTPUT LF AND CLEAR CRSEEN * MOV B,A LDA CRSEEN ORA A MOV A,B JZ CON40 LAST WASN'T A CR, JUST OUTPUT CHAR MVI A,LF OUTPUT A LF TO PREVENT OVERPRINTING CALL CON90 * CON30 XRA A STA CRSEEN CLEAR CRSEEN FLAG * * OUTPUT CHAR IN CONCH * CON40 LDA CONCH CON90 CPI LF LF? JZ CON91 YES, FOLLOW WITH NULLS CONXO MOV B,A PUSH H SETUP CALL TO WCH ROUTINE LHLD WCH -> ROUTINE XTHL RET . GET US THERE * * * SEND NULLS AFTER LF * CON91 CALL CONXO TYPE TH ELF LDA NULLS A=LF BEFORE SO NO NEED TO SAVE PUSH D SAVE DE MOV D,A ORA A JZ CON93 NONE TO DO * CON92 XRA A CALL CONXO SEND NULL DCR D COUNT DOWN JNZ CON92 MORE * CON93 POP D MVI A,LF RETURN WIT LF FOR CONSISTANCY RET . NOW RETURN FOR REAL * * * * THIS DOES THE ACTUAL OUTPUT. CONTROL USUALLY COMES HERE * THROUGH (WCH) BY CON90. * CIWCH IN 0F8H STBYT EQU $-1 DB 0 PATCH ROOM ANI OTRDY JZ CIWCH MOV A,B GET CHR OUT 0F9H DABYT EQU $-1 RET * ******************************************* * * * UPSHIFT ASCII SUBROUTINE * * COME HERE WITH CHAR IN CONCH * * BINARY, NO CHANGE, CHAR IN CONCH (NOT IN A) * OK, POSSIBLY UPDATED CHARACTER IN A * UPSH LDA SWBIO BINARY CONSOLE? RRC RC . YES, SKIP THE WHOLE THING AND LET CON.. KNOW * LDA SWUPS SEE IF UPSHIFT REQUESTED RRC LDA CONCH A=CHAR CC UPSH1 CHECK IT JMP RX2 NO, SKIP IT * * * SEE ABOUT UPSHIFTING CHAR * UPSH1 CPI 123 ="z"+1 RNC . >"z", NO CHANGE CPI 97 ="a" RC . <"a", NO CHANGE SBI 32 UPSHIFT RET . OK * ******************************************* * * CI PROMPT MESSAGE * CIMSG DB CR DB LF DB ASTRC THE ACTUAL PROMPT DB 0 END OF MESSAGE * * * OUTPUT STRING TO CONSOLE * * LIKE OUST BUT COME WITH HL -> STRING * THE STRING TERMINATES WITH A ZERO BYTE AND CONTROL * RETURNS TO CALL+1 * OUSTH MOV A,M ORA A RZ INX H CALL CONOUT PRINT JMP OUSTH * PAGE * * ******************************************* * * * ----------------- TTY DRIVER FOR CONSOLE ----------- * TDWB EQU CONOUT OUTPUT CHARACTER ROUTINE * * WRITE BLOCK * * BUFFER ADDR IN HL, COUNT IN DE * TDWL MOV A,E ORA A TEST COUNT JZ TDW30 ZERO, => DONE MOV A,M GET CHAR CALL TDWB PRINT INX H BUMP POINTER DCR E DEC. COUNT JMP TDWL * * * RETURN A ZERO COUNT * TDW30 LXI H,0 JMP RX2 RETURN CALL+2 * * * READ BLOCK * * COME WITH BUFF IN HL, COUNT IN DE * * PRINT PROMPT * TDRL PUSH H PUSH D SAVE IMPORTANT NUMBERS LHLD TDPRO -> PROMPT MESSAGE CALL OUSTH PRINT IT POP D POP H MVI D,0 INITIALIZE CHAR COUNT * TDRL2 CALL CONIN GET A CHARACTER CPI CTRLX CANCEL? JZ TDRLC YES, DELETE LINE CPI BSP BACKSPACE? JZ TDRLB YES, BACKSPACE MOV B,A MOV A,D ONLY CHECK CTRL-C IF D=0 (1ST CHAR) ORA A JNZ TDRL3 SKIP TEST MOV A,B CPI CTRLC CTRL-C ? JZ TDRLE YES, EOF * TDRL3 MOV A,E ORA A JZ TDRLF BUFFER IS FULL MOV M,B STORE CHAR MOV A,B INX H CALL CONOUT ECHO INR D COUNT UP DCR E COUNT DOWN CPI CR IS IT A CR? JZ TDRLQ CR, QUIT JMP TDRL2 GET NEXT. * * * DELETE ENTIRE LINE * TDRLC MVI A,'!' TYPE !,CR, LF CALL TDWB MVI A,CR CALL TDWB MVI A,LF CALL TDWB * * MOV BUFFER POINTER AND COUNTS BACK TO BEGINNING * TDRL5 MOV A,D ORA A JZ TDRL2 INR E MORE CHARS AVAIL DCX H MOVE BACK BUFFER PTR DCR D COUNT DOWN CHARS JMP TDRL5 * * * BACK SPACE * TDRLB MOV A,D ORA A JZ TDRLF ITS EMPTY, FORGET IT DCX H ADJUST POINTER DCR D AND INR E COUNTS. MVI A,LARO CALL TDWB TYPE BACK ARROW JMP TDRL2 AND GO ON * * * END OF FILE ENCOUNTERED. * * **** THIS ROUTINE USED AS INIT ENTRY POINT *** * WATCH OUT!! * TDRLE RET . THATS IT * * BUFFER IS FULL (OR EMPTY) * TDRLF MVI A,BELL CALL TDWB DING JMP TDRL2 TRY AGAIN * * CARRIAGE RETURN-QUIT. * TDRLQ MOV L,D COUNT IN HL MVI H,0 JMP RX2 * PAGE * * ******************************************* * * * * TTY CONTROL/STATUS OPERATION * * HANDLES STATUS AND PROMPT SET REQUESTS * TDCTL ORA A JNZ TDCT2 NOT STATUS REQUEST * MVI A,PALO+PNAT+PATR+PDEL PROTECT WORD LXI D,SBDUP+SBIAT+SBPRO*256 TYPE WORD RET . THAT'S ALL * * * CHECK IF PROMPT SET OPERATION * TDCT2 CPI 2 JNZ TDCER NO, ERROR SHLD TDPRO YES, SET PROMPT POINTER RET * * TDCER CALL ERRL2 DB ERNCT CAN'T DO THAT CONTROL OPERATION * ******************************************* * * * * HERE ARE SOME USEFUL ASCII CHARACTERS * BSP EQU 127 RUBOUT CTRLC EQU 3 CONTROL-C CTRLX EQU 24 CONTROL-X BELL EQU 7 BELL BSLSH EQU 92 BACK-SLASH LARO EQU 95 LEFT ARROW BLNK EQU 32 SPACE * PAGE * * ******************************************* * * * * * UTILITY OPERATION MANAGER * ***************************** * * * THIS OPERATION RUNS ON THE CALLING STACK * * CALL UTIL * OPERATION * ERROR RETURN * NORMAL RETURN * * THE CALLED OPERATION IS PASSED HL AND A * UTILTY SHLD XHL SAVE HL STA XA AND A * * PICKUP THE OPERATION * POP H MOV A,M INX H MOVE RETURN PAST OPER PUSH H STA XOPER SAVE OPERATION * * REWIND THE FILE * LDA UTIL MVI D,0 CALL SYS REWIND DB SPAOP JMP UER2 * * LOAD UTILITY FILE PREFIX * LXI B,255 BC IS COUNT LXI H,CBUF READ INTO CMD BUFFER XRA A A IS ZERO MOV M,A MAKE SURE A ZERO IS THERE XCHG . DE IS DEST ADDRESS * LDA UTIL UTILITY FILE IS ALWAYS OPEN CALL SYS DB RBLOP MEMORY PROTECT WILL SAY NO NOP NOP . IGNORE NOP . EOF * * CHECK OPERATION * LDA XOPER LXI H,CBUF CMP M COMPARE TO MAX JNC UER1 ERROR, ITS TOO BIG * * FIND OPERATION * INX H MOVE PAST MAX MOV C,A MVI B,0 DAD B + OPERATION DAD B MOV A,M INX H MOV H,M MOV L,A = BRANCH ADDRESS ORA H JZ UER1 IT'S ZERO, FORGET IT * * SETUP FOR CI IMAGE LOAD * LDA UTIL STA CICNT NOTE: B= 0 FROM ABOVE CALL SYS DB SEKOP JMP UER2 * * FINAL SETUP FOR CI LOAD IS DONE * MVI A,1 STA XQFLG FORCE EXECUTION....BANG, BANG...SHOOT, STAB JMP CI75 * * * UER1 MVI A,UTE0 BAD UTILITY OPERATION UER2 RET . JUST RETURN WITH SYS STUFF * * *