; INTELLIGENT TERMINAL PROGRAM VERSION 16.0 ; DATE: 01/18/79 ; OPERATIONAL ON THE INTEL 8080 MICRO COMPUTER ; THIS VERSION COMMUNICATES WITH TERMINAL, DTV, AND 2 TIME ; SHARING COMPUTERS ; TITLE ' INTELLIGENT TERMINAL PROGRAM - IMSAI VERS 16.0' ; I-O CONTROL TABLE ;*************************** EQUATES ***************************** WIDTH EQU 80 ; WIDTH OF LINE LINES EQU 24 ; NUMBER OF LINES SIZE EQU 80 ; WIDTH OF SCREEN SIZEM1 EQU SIZE-1 ; WIDTH MINUS ONE MIO EQU 051H ; MODEM I/O CHANNEL MRSET EQU 52H ; MODEM RESET MINTR EQU 53H ; MODEM INTERRUPTS NEDITB EQU 1 ; NUMBER OF EDIT BUFFER LINES NSCRL EQU LINES-NEDITB-1 MSTAT EQU 050H ; MODEM 1 STATUS IPS EQU 20H ; INTERRUPT PENDING STATUS RDA EQU 040H ; DATA AVAILIABLE FLAG TTYBE EQU 080H ; UART TRANSMISSION BUFFER EMPTY FLAG KEYS EQU 0 KEYI EQU 1 KEYR EQU 2 ; IO PORT RESET KEYP EQU 3 ; INTERRUPT ADDRESS KEYPD EQU 4 ; PARALLEL INPUT PORT BLK EQU 020H WBLK EQU 0A0H TOP EQU 0F000H ; TOP OF TV SCREEN WORDS EQU TOP+(LINES-1)*WIDTH ; BEGINNING OF EDIT BUFFER WORDEN EQU (WORDS+SIZEM1) AND 0FFH ; END OF EDIT BUFFER WORDLO EQU WORDS AND 0FFH SIZED EQU SIZE*NEDITB ; NUMBER OF CHARS IN EDIT BUFFER EOFED EQU WORDS+SIZED-1 ; POINTER TO END OF EDIT BUFFER EOEDLO EQU EOFED AND 0FFH; LOW ORDER EOFED OULINE EQU WORDS-SIZE ; POINTER TO OUTPUT BUFFER CR EQU 13 ; LF EQU 10 ; ORG 100H ;START PROGRAM HERE ; ; TERMINAL CONTROL FUNCTIONS ; JMP BEGIN ; CTAB: DW BREAK ; NULL - (OR BREAK KEY) DW MONTR ; CTL-A 1 DISPLAY/TTY DW SUPS ; CTL-B 2 OUTPUT @@SUPS DW RTCPM ; CTL-C 3 RETURN TO CPM DW CHDEL ; CTL-D DELETE FROM TEXT DW STAT ; CTL-E 5 OUTPUT @@STAT DW LEFT ; CTL-F 6 MOVE CURSOR LEFT DW RIGHT ; CTL-G 7 MOVE CURSOR RIGHT DW CHOME ; CTL-H 8 HOME CURSOR DW MOVE ; CTL-I 9 INSERT BLANK INTO TEXT DW GETM ; CTL-J 10 GET STORED MESSAGE - DW UP ; CTL-K 11 SCROLL UP DW DOWN ; CTL-L 12 SCROLL DOWN DW SAVCR ; CTL-M 13 CARRIAGE RETURN DW GSTAR ; CTL-N 14 1108- TO- BASIC DW RUNST ; CTL-O 15 @RUN STATEMENT DW XFDISK ; CTL-P 20 - DISK TO TSC DW TAB ; CTL-Q 17 TABS DW REPET ; CTL-R 18 REPRINT LINE DW FIND ; CTL-S FIND STRING IN EDIT BUFFER DW GSTAR ; CTL-T 16 - TSC TO DISK DW HELP ; CTL-U 21 - HELP DW GSTAR ; CTL-V GO READ HEX DW SKIP ; CTL-W SKIP OVER WORD DW SENDM ; CTL-X TRANSMIT SAVED IMAGE DW ERASE ; CTL-Y ERASE TO LINE OF LINE DW SAVEM ; CTL-Z 19 SAVE EDIT BUFFER DW REPLACE ; ESC DW FLIP ; 28 FS DW BAUD ; 29-GS 300-1200 BAUD TOGGLE DW GSTAR ; 30 RS - COPY FROM COMPUTER A TO B DW CLEAR ; 31 US - CLEAR SRCREEN ; ;*************************** BEGIN ***************************** BEGIN: LXI SP,STACK ; SET STACK POINTER LXI D,MASK ; INITIALIZE RAM AREA LXI H,EBUF ; POINT TO FIFO RAM MVI B,MASKQ-MASK+2 ; LOOP: LDAX D ; MOV M,A ; INX H ; INX D ; DCR B ; END OF MASK JNZ LOOP ; IF NOT LOOP CALL CRLF ; DO CARRIAGE RETURN LDA 1 ; SET DISPLAY TO SCREEN STA SENFLG JMP RESTAR ; ; CLEAR TV SCREEN CLEAR: LXI H,TOP ; SET POINTER TO BEGINNING MVI B,LINES ; SET UP LINE COUNTER MVI C,WIDTH ; SET WIDTH COUNTER MVI A,BLK ; FILL WITH BLANK CLR1: MOV M,A ; STUFF ONE INX H ; NEXT ADDR DCR C ; ONE LESS TO DO JNZ CLR1 ; MVI C,WIDTH ; NEW LINE DCR B JNZ CLR1 CALL BLANK ; FORM EDIT BUFFER RET ; RESTAR: MVI A,84H ; SET IO PORT BAUD RATE OUT KEYS LDA BRATE ; PICK-UP CURRENT MODEM BAUD RATE OUT MSTAT MVI A,1 OUT KEYR ; RESET IO PORT OUT MRSET ; RESET MODEM CALL CRLF MVI A,08H ; SET MODE 2 FOR DTV STA TOP+7FFH ; INITIALIZE IMSAI BOARD XRA A OUT MINTR ; MASK OUT DEV B INTERRUPTS ; ; BLANK OUT EDIT BUFFER NEWL: CALL BLANK ; BLANK OUT EDIT LINE LXI H,WORDS ; POINT TO BEGINNING OF EDIT BUFFER MVI B,0 ; ZERO OUT CHARACTER COUNT NEW1: SHLD POINT ; SAVE CURSOR POINTER ; ; CHECK FOR MODEM INPUT ; START: CALL MINP ; 0330 CHECK MODEM STATUS JC IN6 ;IF NOT GO CHECK TTY INPUT STATUS JZ START ; REJECT 'EM ST1: CALL OUTC ;OUTPUT TO TV/TTY JMP START ; ; ; MODEM INPUT ROUTINE ; MINP: PUSH H ; SAVE HL LHLD MIBUF ; POINT TO MODEM INPUT BUFFER LDA MIPT ; TOP OF MODEM INPUT FIFO BUFFER CMP L JZ MINP2 ; JUMP, IF NO CHARACTERS MOV L,A ;MOVE TO STARTING ADDRESS INR A ; INCREMENT FIRST CHAR POINTER STA MIPT MOV A,M ; GET THE CHARACTER BACK TO AREG MINP1: POP H JMP MINP4 ; ; NOTHING IN FIFO BUFFER - CHECK MODEM FOR INPUT ; CARRY SET ON RET = NO DATA ; MINP2: POP H MINP3: XRA A IN MSTAT ; CHECK STATUS ANI RDA STC RZ IN MIO ANI 7FH MINP4: STC ; TURN OFF CARRY CMC RET ; CHKMOD: CALL MINP3 ; CHECK FOR INPUT RC ; RETURN, IF NOT PUSH H LHLD MIBUF MOV M,A INR L SHLD MIBUF POP H RET ; ; ANY INPUT FROM PARALLEL KEY BOARD ? ; IN6: MVI A,04H ; GET INT. MASK FOR SENS OUT KEYP ; OUTPUT IT IN KEYS ; GET STATUS STA STATIN ; SAVE STATUS ANI IPS ; ISOLATE INT. PENDING BIT JZ IN61 ; IF NOT, GO CHECK TTY INPUT STATUS IN KEYP ; GET INT. ADDR. IN KEYPD ; GET DATA FROM PARALLEL PORT JMP IN81 IN61: LDA STATIN ; RESTORE STATUS JMP IN8 ; GO CHECK TTY INPUT STATUS ; ; ANY INPUT FROM THE KEYBOARD? ; IN8: IN KEYS ; 0390 INPUT FROM TTY? ANI RDA ; JZ CHKT ;IF NOT, GO CHECK TTY OUTPUT STATUS IN KEYI ; 0420 ACCEPT INPUT FROM TTY IN81: ANI 7FH ;STRIP OFF PARITY BIT CPI BLK ; IS IT CTL CHARACTER? ; ; CHECK CONTROL COMMAND TABLE ; LXI H,START ; SAVE RET ADDR ON STACK PUSH H JNC NOCTL ; IF NOT GO STORE IT LXI H,CTAB ; ADDR OF CMD TABLE ADD A ; MULTIPLY BY 2 ADD L MOV L,A ; AND ADD TO HL MOV A,M ; PICK UP LOWER ADDR INX H MOV H,M ; PICK UP HIGH ADDR MOV L,A ;HL CONTAIN JUMP ADDRESS PCHL ; NOCTL: CPI 94 ;UP ARROW: DELETE LINE JZ DELET ; CPI 127 ;DELETE CHARACTER (RUBOUT) LHLD POINT JNZ SAVE ;GO SAVE CHARACTER IN EDIT BUFFER CALL WOB MOV A,L ; DCX H ;DELETE CHARACTER CPI WORDLO ; AT BEGINNING OF LINE? SHLD POINT MVI M,BLK ;BLANK IT OUT JZ DELET ;IF ZERO, DELETE LINE MVI A,95 ;OUTPUT UNDERSCORE CALL OUTD ;GO OUTPUT CHARACTER RET ; ; ; SAVE CHARACTER ; SAVE: ORI 80H ; MOV M,A ;STORE CHARACTER IN EDIT BUFFER CALL OUTD ; INVRH: INX H ;BUMP MEMORY POINTER ; ; SET UP CURSOR ; INVRC: MOV A,M ;TURN ON CURSOR ANI 7FH ; MOV M,A ; SHLD POINT ; RET ; ; ; TEXT EDITOR COMMAND ; *ESC* - INSERT 'R ' IN FRONT OF IMAGE TO REPLACE CURRENT ; IMAGE WITH CONTENTS OF EDIT BUFFER ; REPLACE: MVI A,'R' CALL OUT7 ; OUTPUT 'R ' MVI A,' ' CALL OUT7 ; ; CTL-M ; COME HERE FOR CRLF ; SAVCR: CALL LENG ;FIND LENGTH MVI M,CR ; ; ; OUTPUT TO 1108 ; OUTI: LXI H,WORDS ;YES, OUTPUT LINE TO BIG COMPUTER OUTX: MOV A,M ;PICK UP CHARACTER ANI 7FH ; CALL OUT7 ;TRANMIT IT CPI CR ; END OF LINE? INX H ;INCREMENT EDIT BUFFER POINTER JNZ OUTX ;LAST CHARACTER? ; ; DELETE LINE ; DELET: CALL CRLF ;CLEAR EDIT BUFFER NEW: POP PSW JMP NEWL ; ; ; CTL-R ; REPRINT THE LINE ; REPET: ;REPRINT LINE WHEN CTL-R IS ENTERED CALL LENG ;GET LENGTH OF LINE MOV A,B ; ORA A ;IS EDIT BUFFER EMPTY? STA COUNT ;NO RZ ;IF SO, GO TO START LXI H,WORDS ;ELSE, POINT TO BEGINNING OF BUFFER CALL CRLF ;OUTPUT CARRIAGE RETURN-LINE FEED REPA: MOV A,M ;REPRINT WHOLE LINE ANI 7FH ; CALL OUTC ; INX H ;BUMP POINTER DCR B ;DECREMENT CHARACTER COUNT JNZ REPA ;LOOP RET ; ; OUTPUT CARRIAGE RETURN -- LINE FEED (AND NULLS) ; CRLF: MVI C,CR ;OUTPUT CARRIAGE RETURN LINE FEED JMP OUTCR ; ; ; OUTPUT TO CONSOLE ; OUTD: MOV C,A ;MORE CRLF KLUDGE LDA SENFLG ; 1040 CHECK SENSE SWITCHES ANI 1 ;IS S/W 8 ON? MOV A,C ; RNZ ;IF NOT, RETURN OUTPUT NO CHARACTER ; ; OUTPUT ONE CHARACTER ; OUTC: ANI 7FH ; CPI 7FH ;DEL? RZ ; MOV C,A ; CPI BLK ;CR? JNC NOCR ;NO CTL BUT COULD BE CR CPI CR ;IS IT CR? RNZ ;NOPE, THEN IGNORE OUTCR: LDA LASTC ;OUTPUT CARRIAGE ROUTINE CMP C ;IF PREVIOUS CHARACTER WAS NOT CARRI RZ ;RETURN IF LAST CHAR WAS CR NOCR: LDA SENFLG ; ANI 1 ;SW-8 ON? MOV A,C ; STA LASTC ;SAVE IN 'LAST' CHARACTER BUFFER JNZ CHOUT CZ TOUT ;IF S-W 8 IS OFF, THEN OUTPUT TO TTY CPI CR ; RNZ ;IF NOT CR, RETURN MVI A,LF ;ELSE, OUTPUT LINE-FEED AND 6 NULLS CALL TOUT1 ; MVI A,0 ;NULL IS ZERO MVI C,5 ;LIKE 6 TIMES NULL: CALL TOUT1 ; DCR C ; JNZ NULL ; MVI A,CR ;RESTORE CR TO A-REG GSTAR: RET ;(JUMP HERE FOR UNDEFINED CMDS) ; ; BUFFER OUTPUT ROUTINE ; TOUT: MOV A,C ; STA LASTC ;SAVE IN 'LAST' CHARACTER BUF TOUT1: ;NOW, OUTPUT TO TTY XCHG LHLD EBUF ;LOAD D-REG WITH POINTER TO LAST CHA MOV M,A ;SAVE CHARACTER IN TTY OUTPUT BUFFER CALL LIMCHK SHLD EBUF XCHG RET ; ; ; CHECK LIMITS OF OUTPUT BUFFER ; VARIES FROM FIFO TO 9FFFH ; LIMCHK: INX H PUSH PSW MOV A,H CPI FIFOM SHR 8 ; DON'T LET IT EXCEED XFFF JNZ LIM1 LXI H,FIFO ; RESET 4096 BYTE CIRCULAR BUFFER LIM1: POP PSW ; RESTORE A RET ; ; IF TBE AND TTY BUFFER NOT EMPTY, THEN OUTPUT A CHARACTER TO TTY ; CHKT: IN KEYS ; 1450 IS TTY TRANSMISSION BUFFER EMPTY ( ANI TTYBE ;(TBE STATUS = 00000010B) JZ MOUT ;NO, THEN GO CHECK MODEM OUTPUT STAT LDA SBUF ;START OF TTY OUTPUT BUF LHLD EBUF ;LOAD H-L REG WITH POINTER TO TTY OU CMP L ;DOES LAST CHAR. POINT TO FIRST CHAR JNZ CHKT1 ;IF SO, THEN THERE IS NO CHAR TO BE LDA SBUF+1 ; CMP H JZ MOUT CHKT1: LHLD SBUF MOV A,M ;PICK UP CHARACTER FROM BUFFER OUT KEYI ;OUTPUT IT TO TTY CALL LIMCHK ;INCREMENT STARTING CHARACTER BUFFER SHLD SBUF JMP START ; ; ; CTL-E ; OUTPUT @@STAT ; STAT: LXI D,SMSG ;OUTPUT CANNED MESSAGE: @@STAT JMP OUTMG ; ; ; SET DISPLAY FLAG MONTR: LDA SENFLG ; LOAD SENSE FLAG ADI 1 CPI 2 JC MONT1 XRA A MONT1: STA SENFLG ; TOGGLE FLAG RET ; ; RETURN TO CPM RTCPM: LXI D,CPMSG PUSH B ; DUMMY PUSH MVI B,1 ; OUTPUT ONE LINE MVI C,WIDTH ; SET WIDTH COUNTER LXI H,WORDS ; OUTPUT IN EDIT BUFFER CALL TVMGA CALL CRLF LHLD JMPCON ; JMP CONOT ADDR MOV A,H CMP L ; CHECK IF ZERO JZ 0 ; RETURN TO CP/M LDA CONINF ; RESTORE JMP CONOT MOV M,A INX H LDA CONINF+1 MOV M,A JMP 0 ; ; CTL-O ; OUTPUT @RUN STATEMENT ; RUNST: LXI D,RMSG ; OUTPUT JMP OUTMG ; ; CTL-B ; OUTPUT SUPS MESSAGE ; SUPS: LXI D,UMSG ;OUTPUT @@SUPS JMP OUTMG ; OUTMG: IN MSTAT ; 1670 ROUTINE TO OUTPUT MESSAGE AT ADDRE ANI TTYBE ;CHECK STATUS JZ OUTMG ;LOOP IF TRANSMISSION BUF NOT EMPTY LDAX D ;PICK UP CHARACTER CALL JOUT ;AND OUTPUT IT ANI 7FH ; CPI CR ;IS IT A CARRIAGE RETURN? INX D ;INCREMENT CHAR POINTER RZ ; JMP OUTMG ;OUTPUT NEXT CHARACTER ; ; SCROLL UP ONE LINE ; SCRL: MVI B,LINES-1-NEDITB ;SCROLL UP ONE LINE SCRLX: LXI H,TOP ;TO ADDRESS LXI D,TOP+SIZE ;FROM ADDRESS CALL SCUP ;SCROLL UP ONE LINE CALL ZERO ;BLANK OUT LINE 3 RET ; ; ; SCROLL UP ; SCUP: MVI C,WIDTH ;SCROLL UP ONE LINE SCUP2: LDAX D ;PICK UP CHARACTER ANI 7FH ;STRIP OFF WHITE BACKGROUND MOV M,A ;STORE IT IN NEW LOCATION INX H ;ADJUST POINTERS INX D ; DCR C ;DECREMENT CHARACTER COUNTER JNZ SCUP2 ;LOOP CALL CHKMOD ; CHECK FOR MODEM INPUT DCR B ;DECREMENT LINE COUNTER JNZ SCUP ; RET ; ; ; SCROLL DOWN ONE LINE ; SCDN: MVI C,WIDTH ;SCROLL DOWN ONE LINE SCDN2: LDAX D ;PICK UP CHARACTER ANI 7FH ;REMOVE WHITE BACKGROUND MOV M,A ;STORE CHARACTER IN NEW LOCATION DCX H ;DECREMENT POINTERS DCX D ; DCR C ;AND CHARACTER COUNTER JNZ SCDN2 ;LOOP FOR ALL WIDTH CHARACTERS DCR B ;DECREMENT LINE COUNTER JNZ SCDN ; RET ; ; ; BLANK OUT ONE LINE ; ZERO: MVI A,BLK ;LOAD A-REG WITH BLANK CHARACTER MVI C,WIDTH ;LINE CHARACTER COUNT SC3: MOV M,A ;STORE BLANK INX H ; DCR C ; JNZ SC3 ;LOOP FOR ALL WIDTH CHARACTERS RET ; ; ; CTL-Y ; ERASE TO END OF LINE ; ERASE: LHLD POINT ; PICK UP POINTER TO CURSOR INX H JMP BLKA ; ; BLANK OUT LINE ; BLANK: LXI H,WORDS ; POINT TO BEGINNING OF EDIT BUF BLKA: MVI A,WBLK ;WHITE BACKGROUND TYPE MVI C,SIZE*NEDITB ;BLANK OUT LOWER TWO LINES JMP SC3 ; ; ; PERFORM IMMEDIATE BREAK FUNCTION ; BREAK: XRA A ; ; SET PARITY EVEN AND OUTPUT TO MODEM ; JOUT: ORA A ; SET 8080 FLAGS JPE JOUTA ; IS PARITY EVEN? ORI 80H ; IF NOT SET PARITY BIT EVEN JOUTA: OUT MIO ; OUTPUT TO MODEM RET ; ; OUTPUT BUFFER TO MODEM ; MOUT: IN MSTAT ; CHECK STATUS BIT ANI TTYBE ; JZ START ;GO CHECK FOR INPUT FROM BIG COMPUTE LDA NBUF ;CURRENT CHARACTER POINTER LHLD MBUF ;LAST CHARACTER OUTPUT POINTER CMP L ; JZ START ; RETURN IF THERE ARE NO CHARACTERS MOV L,A ; 250 TO BE OUTPUT; ELSE OUTPUT CHARACTE MOV A,M ; CALL JOUT ; INR L ;INCREMENT CURRENT CHAR POINTR MOV A,L ; STA NBUF ; JMP START ; 2310 ; ; OUTPUT TO MODEM ; OUT7: ; PUSH H LHLD MBUF ;POINTER TO LAST CHAR OUTPUT ANI 7FH ; MOV M,A ;SAVE CHARACTER IN OUTPUT BUFFER INR L ; SHLD MBUF ; POP H ; CHOUT: PUSH H MOV C,A ; SAVE CHARACTER PUSH B ; LHLD TVBUF ;TV BUFFER CURRNET CHARACTER POINTER ANI 7FH ; CPI CR ;IS IT CR? JZ TVCR ;IF SO, THEN SCROLL UP CPI 95 ;ELSE CHECK FOR DELETE JNZ CH0 ; DCX H ;IF CHAR IS DELETE, MOVE POINTER BA JMP CH2 ; CH0: CPI BLK ;IS CHAR CONTROL TYPE? JC CHEND ;IF NOT, OUTPUT CHARACTER TO TV MOV A,L ;ELSE, RETURN IF NOT CR CPI WORDLO ; AT BEGINNING OF LINE? JNZ CH1 ; PUSH B CALL SCRL POP B LXI H,OULINE ;RESET EDIT BUFFER JMP CH1 TVCR: PUSH B CALL SCRL ;SCROLL UP ONE LINE POP B LXI H,OULINE ;RESET EDIT BUFFER JMP CH2 ; CH1: MOV M,C ;NOW, FINALLY, SAVE CHAR IN INX H ;IN BUFFER AND BUMP POINTER CH2: SHLD TVBUF ;SAVE POINTER CHEND: POP B ; POP H ; RESTORE H AND L MOV A,C ; RET ; ; ; RESET CURRENT CURSOR POSITION WOB: LHLD POINT ; MODIFY CURSOR MOV A,M ;ERASE CURSOR ORI 80H ; MOV M,A ; RET ; ; CTL-G ; MOVE CURSOR RIGHT ; RIGHT: CALL WOB ;MOVE CURSOR RIGHT JMP INVRH ;V7 GO INX H AND TURN ON CURSOR ; ; CTL-F ; MOVE EDIT BUFFER LEFT ; LEFT: CALL WOB ;MOVE LEFT ONE POSITION DCX H MOV A,L ; AT BEGINNING OF LINE? CPI WORDLO JC HOME ; RESET TO BEGINNING OF BUF JMP INVRC ; ; ; CTL-H ; MOVE CURSOR TO BEGINNING OF EDIT BUFFER ; CHOME: CALL WOB HOME: LXI H,WORDS ;HOME CURSOR JMP INVRC ; ; ; ROUTINE TO FIND END OF STRING ; LENG: MVI B,SIZE*NEDITB ;START AT END OF EDIT BUFFER LXI H,EOFED ; END OF EDIT BUFFER LENGA: MOV A,M ; CPI WBLK ;IS IT BLANK? JZ LENGC ; CPI BLK ; JNZ LENGB ; LENGC: DCX H ;LOOK AT NEXT CHARACTER DCR B ; JNZ LENGA ; LENGB: INX H ;END OF IMAGE HAS BEEN FOUND MVI M,BLK ;SET CURSOR RET ; ; ; CTL-I INSERT INTO TEXT ; MOVE: CALL WOB MVI A,EOEDLO-1 ; END OF EDIT LINE ; MVI D,BLK ; MOVEL: MOV C,M ;PICK UP CHARACTER MOV M,D ;STORE PREVIOUS CHARACTER MOV D,C ; INX H ;POINT TO NEXT CHARACTER CMP L ;END OF EDIT BUFFER? RZ ; JMP MOVEL ;IF NOT, THEN CONTINUE ; ; DELETE IN TEXT CTL-D ; CHDEL: LHLD POINT MOV A,L ; MVI D,WBLK ; MVI L,EOEDLO-1 ; CHDHL: MOV C,M ;PICK UP CHARACTER MOV M,D ;STORE LAST CHARACTER MOV D,C ; CMP L ;LAST CHARACTER IN EDIT BUFFER? DCX H ;NO, THEN LOOP JNZ CHDHL ; INX H ;YES, THEN SET CURSOR AND RETURN JMP INVRC ; ; ; CTL-K MOVE CURSOR UP ; UP: MVI B,1 ; LXI D,TOP ;MOVE TOP LINE TO TEMP BUFFER LXI H,XBUF ; CALL SCUP ; MVI B,LINES-NEDITB ;NOW, SCROLL 14 LINES UP ONE CALL SCRLX ; LXI D,XBUF ;MOVE TEMP LINE TO EDIT BUFFER LXI H,WORDS ; MVI B,1 ; CALL SCUP ; ENDSC: MVI C,WIDTH ; LXI H,WORDS ; INVRT: MOV A,M ;TURN ON WHITE BACKGROUND ORI 80H ; MOV M,A ; INX H ; DCR C ; JNZ INVRT ;LOOP FOR ALL CHARACTERS IN LINE CALL LENG ;GO COMPUTE IMAGE LENGTH JMP NEW1 ; ; ; CTL-L MOVE CURSOR DOWN ; DOWN: MVI B,1 ; LXI D,WORDS+SIZEM1 ;3 LXI H,XBUF+SIZEM1 ; CALL SCDN ;MOVE EDIT BUFFER TO TEMPORARY BUFFE LXI D,WORDS-1 ; LXI H,WORDS+SIZEM1 ;3 MVI B,LINES-NEDITB ;NOW, SCROLL 14 LINES CALL SCDN ;NOW, SCROLL DOWN 14 LINES LXI D,XBUF+SIZEM1 ; LXI H,TOP+SIZEM1 ; MVI B,1 ; CALL SCDN ;NOW MOVE TEMPORARY BUFFER TO TOP LI JMP ENDSC ; ; ; CTL-V ; READ HEX INPUT INTO MEMORY ; ; ; LOAD INTEL HEX OBJECT FROM TSC TO MEMORY ; READ: LXI H,0 ;SET BIAS ADDRESS TO ZERO PUSH H READ0: POP H PUSH H CALL MOINP ; INPUT CHARACTER FROM TSC MVI B,':' ; IS IT A COLON? SUB B JNZ READ0 ;SEARCH FOR COLON MOV D,A ;ZERO OUT CHECKSUM CALL BYTE JZ RED2 ;ZERO RECORD LENGTH, ALL DONE MOV E,A ;E (- RECORD LENGTH CALL BYTE ;GET MSB OF LOAD ADDRESS PUSH PSW ;SAVE IT CALL BYTE ;GET LSB OF LOAD ADDRESS POP B ;RETRIEVE MSB, PUT IN B MOV C,A DAD B ;BIAS ADDRESS + LOAD ADDRESS -) HL CALL BYTE ;RECORD TYPE RED1: CALL BYTE ;READ DATA MOV M,A ;PUT IN MEMORY INX H DCR E JNZ RED1 ;LOOP UNTIL DONE CALL BYTE ;READ CHECKSUM JNZ CHKERR ;CHECKSUM ERROR JMP READ0 ;GET ANOTHER RECORD RED2: CALL BYTE ;GET MSB OF TRANSFER ADDRESS MOV H,A CALL BYTE MOV L,A ORA H JZ RED3 ;IF TRANSFER ADDRESS = 0, RETURN TO KB PCHL RED3: POP H JMP READ4 ; BYTE: CALL MOINP ;READ CHAR FROM TAPE CALL DIGIT ;CONVERT ASCII TO HEX RLC RLC RLC RLC ;SHIFT FOUR PLACES MOV C,A CALL MOINP CALL DIGIT ;GET LOWER NIBBLE ORA C MOV C,A ADD D ;UPDATE CHECKSUM MOV D,A MOV A,C RET ;RETURN ; ; CONVERT ASCII CHARACTER TO HEX DIGIT ; DIGIT: SUI '0' RC ; FILTER OUT 0-2FH ADI 0E9H RC ; FILTER OUT 47H-0FFH ADI 6 JP NI0 ; TAKE BRANCH FOR A-F ADI 7 RC ; FILTER OUT 3AH-40H NI0: ADI 10 ORA A ; ZERO OUT ERROR FLAG RET ; RETURN ; ; OUTPUT FINISHED MESSAGE ; READ4: LXI D,FINMSG JMP READ5 ; ; OUTPUT ERROR MESSAGE ; CHKERR: LXI D,CKMSG READ5: CALL TVMSG LXI SP,STACK JMP NEWL ; ; MODEM TO INPUT ROUTINE ; MOINP: IN MSTAT ; ANI 1 ; JZ KEYIN ; GO CHECK KEYBOARD IN MIO ; ANI 7FH ; STRIP OFF PARITY RET ; KEYIN: ; CHECK FOR KEYIN IN KEYS ANI 1 ; JZ MOINP ; NO INPUT -- GO CHECK MODEM IN KEYI ; ANI 7FH ; STRIP OFF PARITY CPI 1 ; CHECK FOR CTL-A JNZ MOINP JMP BEGIN ; ; CTL-S ; FIND VALUE ON SCREEN ; FIND: CALL LENG ; GET IMAGE LENGTH LXI H,TOP ; SHLD XBUF ; XBUF CONTAINS ADDRESS OF TV SCREEN FINDA: MOV C,B ; SAVE CHARACTER COUNT LXI D,WORDS ; POINT D-REG TO START OF EDIT BUF FINDB: LDAX D ; COMPARE EB STRING CHARACTER ANI 7FH ; CMP M ; WITH CHARACTER ON SCREEN JNZ FINDC ; IF NOT FOUND, LOOK AT NEXT TV BUF C INX H ; ELSE, COMPARE NEXT TWO CHARACTERS INX D ; DCR C ; IF LAST CHAR IN EB, THEN SEARCH SU JZ FOUND ; AND JUMP TO FOUND JMP FINDB ; ELSE, COMPARE NEXT TWO CHARACTERS FINDC: LHLD XBUF ; CONTINUE SEARCH INX H ; SHLD XBUF ; MOV A,H ; CPI WORDS SHR 8 ; JC FINDA ; MOV A,L ; CPI WORDLO ; AT BEGINNING OF THE LINE? JC FINDA ; JMP NEW ; FOUND: XCHG ; SEARCH SUCCESSFUL. MOVE LINE LXI H,TOP ; POINT HL TO TOP OF CRT LXI B,WIDTH ; BC WILL CONTAIN LINE WIDTH FOUN1: DAD B ; POINT TO NEXT LINE MOV A,H ; DOES HL POINT PAST LOCATED TEXT? CMP D JC FOUN1 ; IF NOT, CONTINUE LOOP MOV A,L ; NOW CHECK LOWER ORDER ADDRESS CMP E JC FOUN1 ; IF NOT , LOOP LXI B,-WIDTH ; MOVE TO BEGINNING OF LINE DAD H XCHG ; FOUN2: LXI H,WORDS ; MVI B,1 ; CALL SCUP ; JMP ENDSC ; ; ; CTL-J ; GET STORED MESSAGE ; ; GETM: LXI D,TBUF ; POINT DE TO STORED LINE JMP FOUN2 ; SEND TBUF MESSAGE TO MODEM ; CTL-X ; SENDM: LXI D,TBUF ; JMP OUTMG ; ; ; CTL-Z SAVE EDIT BUFFER SAVEM: LXI H,TBUF ; LXI D,WORDS ; MVI B,1 ; CALL SCUP ; MVI M,CR ; JMP LENG ; ; ; CTL-W = SKIP TO NEXT WORD ; SKIP: LHLD POINT SKIPA: MOV A,M ; ORI 80H ; MOV M,A ; INX H ; ; TOP OF CRT PUSH H PUSH D LXI D,0-WORDS DAD D ; CARRY AFFECTED POP D POP H JNC HOME ; MOV A,M ; CPI BLK ; JZ INVRC ; CPI WBLK ; JNZ SKIPA ; JMP INVRC ; ; ; DO TAB THING (CTL-Q) ; TAB: CALL WOB ; LOAD CURSOR POINTER MOV A,L ; NEXT COL MOD 8 ADI 08H ; OVER 8 ANI 0F8H ; AND BACK TO LAST MOD 8 CPI WORDEN ; END OF EDIT BUFFER JC TABA MVI A,WORDEN+1 ; MAX LENGTH TABA: MOV L,A ; SET CURSOR POINTER JMP INVRC ; TURN-ON CURSOR ; ; FS - CHANGE OUTPUT PORT FLIP-FLOP ; FLIP: LXI D,MODA ; PORT A LDA MFLIP ; LOAD MODEM FLAG CMA ; INVERT A-REG STA MFLIP ; SAVE IT ORA A ; SET 8080 FLAGS MVI A,MSTAT ; SET FOR MODEM A JZ SETPORT ;TURN ON OUTPUT TO MODEM A DCR A DCR A ; SET TO OUTPUT TO MODEM B LXI D,MODB ; POINT TO PORT B MESSAGE ; ; SET PORT FOR COMPUTER A OR B COMMUNICATION ; A-REG POINTS TO PORT; DE POINT TO TV MSG ADDRESS ; SETPORT:STA JOUT+1 ; SET STATUS PORT INR A ; POINT TO DATA PORT STA JOUTA+1 ; SET DATA OUTPUT PORT JMP TVMSG ; ; GS - FLIP BAUD RATE TO EITHER 1200 OR 300 BAUD ; BAUD: LDA BRATE ; PICK UP CURRENT SIO CTL WORD CPI 08H ; IS IT 1200 BAUD 8-DATA BITS; 2-STOP BIT JZ BAUD1 ; YES, CHANGE TO 12 MVI A,08H LXI D,M1200 ; 1200-BAUD MSG JMP BAUD2 ; BAUD1: MVI A,84H ; MAKE 300-BAUD; ETC LXI D,M300 ; 300-BAUD MSG BAUD2: STA BRATE OUT MSTAT ; SET BAUD RATE CALL TVMSG ; OUTPUT MSG TO TV JMP RESTAR ; ; CTL-U GIVE USER HELP ; HELP: LXI D,HMSG ; OUTPUT TO TV USER MSG TVMSG: LXI H,TOP ; POINT TO TOP OF TV BUFFER TVMGA: LDAX D ; PICK UP CHAR TO BE OUTPUT CPI '$' ; ENDING? RZ ; FINISHED WHEN $ ENCOUNTERED MOV M,A ; OUTPUT IT INX H INX D JMP TVMGA ; ; CTL-P OUTPUT CP/M DISK TO 1108 ; ; SET CP/M OUTPUT ADDR XFDISK: CALL SIOAD ; PICK UP OUTPUT ADDRESS LXI D,PMSG ; SEND @@PTI CALL OUTMG ; TO MODEM JMP 0 ; GO TO CP/M DISK OPERATING SYS ; ; SET CP/M OUTPUT ADDR SIOAD: LHLD 1 ; ADDR OF WBOOTE: JMP WBOOT LXI D,10 ; OFFSET TO JMP CONOT DAD D SHLD JMPCON ; SAVE JMP CONOT ADDR XCHG ; DE ADDR OF LO BYTE LXI H,DTOU LDAX D STA CONINF MOV A,L STAX D INX D LDAX D STA CONINF+1 MOV A,H STAX D RET ; DTOU: IN MSTAT ; CHECK MODEM STATUS ANI TTYBE ; UART BUF EMPTY BIT JZ DTOU ; LOOP IF NOT EMPTY MOV A,C OUT MIO ; AND OUTPUT CHARACTER PUSH D CALL CHOUT POP D RET ; ; STORAGE ALLOCATION ; MASK: DW FIFO ; DW FIFO DB 0 ; COUNT DB 0 ; MFLIP DB 0 ; LASTC DB 08H ; BRATE DB 0 ; NBUF DW WORDS ; POINTER TO BEGINNING OF EDIT BUFFER DW WORDS-WIDTH ;TVBUF LOCATION FOR OUTPUT MASKQ: DW MOBU1 ; RMSG: DB '@RUN CHINA, ,38130,50,500,,125-1' DB CR UMSG: DB '@@SUPS' DB CR SMSG: DB '@@STAT' DB CR PMSG: DB '@@PTI' DB CR CPMSG: DB ' ** RETURN TO CP/M ** $' M300: DB '****** BAUD RATE 300 ********$' M1200: DB '****** BAUD RATE 1200 ********$' FINMSG: DB '***** HEX OBJECT IS LOADED ****$' CKMSG: DB '***** CHECK SUM ERROR *****$' MODA: DB '** OUTPUT TO PORT 51 **$' MODB: DB '** OUTPUT TO PORT 71 **$' HMSG: DB '*** TERMINAL CONTROL FUNCTIONS CTL-(?) *** ' DB ' ' DB '(A) DISPLAY/TTY TOGGLE (B) SEND @@SUPS ' DB '(C) RETURN TO CP/M ' DB '(D) DELETE IN TEXT (E) SEND @@STAT ' DB ' ' DB '(F) CURSOR LEFT (G) CURSOR RIGHT ' DB '(H) CURSOR HOME ' DB '(I) INSERT IN TEXT (J) GET STORED MESSAGE ' DB ' ' DB '(K) SCROLL UP (L) SCROLL DOWN ' DB ' ' DB '(P) DISK TO TSC (Q) TAB ' DB '(R) REPRINT ' DB '(U) HELP (W) WORD SKIP OVER ' DB '(X) SEND BUF ' DB '(Y) ERASE TO EOL (Z) STORE IN BUF ' DB '(GS) 300/1200 BAUD TOGGLE ' DB '(US) CLEAR SCREEN $ ' ******** FROM THIS POINT TO END MUST BE IN RAM ******** MIBUF: DW MIBU1 ; MODEM INPUT BUFFER MIPT: DB 0 ; TOP OF INPUT FIFO BUFFER ; COPIED FROM MASK EBUF: DW FIFO SBUF: DW FIFO COUNT: DB 0 MFLIP: DB 0 ; MODEM OUTPUT FLAG LASTC: DB 0 ; ST CHARACTER OUTPUT BRATE: DB 08H ; 1200-300 BAUD TOGGLE NBUF: DB 0 ; POINTER TO BEGINNING OF FIFO FO POINT: DW WORDS ; CURSOR POINTER TVBUF: DW WORDS-WIDTH ; LINE 14 MBUF: DW MOBU1 ; MODEM OUTPUT BUFFER ADDRESS ; END OF COPY SENFLG: DB 0 ; DISPLAY FLAG STATIN: DB 0 ; KEYBOARD STATUS XBUF: DS WIDTH ; TEMPORARY LINE BUFFER TBUF: DS WIDTH ; BUFFER FOR SAVING EDIT BUFFER CONTENTS (CTL- JMPCON DW 0 ; ADDR OF JMP CONOT CONINF DW 0 ; CONTENT OF JMP CONOT DS 128 ; PROGRAM STACK AREA STACK: DS 2 ; ********BUFFERS ******** PREND: DS 1 ; MUST BE AT PROGRAM END FIFO EQU (PREND+0FFFH) AND 0F000H ; X000H TO XFFFH FIFOM EQU FIFO+1000H MIBU1 EQU FIFOM ; MODEM INPUT BUFFER XX00-XXFF MOBU1 EQU MIBU1+100H ; MODEM OUTPUT BUFFER XX00-XXFF END