* * * OUTPUT FILTER #1 * CHARACTER IS IN B * OF1 LDA LEDFG ORA A JZ OF13 TRANSLATE THIS CHARACTER? * XRA A CLEAR LEAD IN FLAG STA LEDFG MOV A,B CPI '\' \\=\ JZ OF2 JUST PRINT IT * MVI A,-64 ADD B TRANSLATE CHARACTER TO CTRL-CHARACTER MOV B,A JMP OF2 PRINT CHARACTER * OF13 MOV A,B CPI '\' LEAD IN CHARACTER? JNZ OF2 NO, PRINT CHARACTER STA LEDFG RET * * * OUTPUT FILTER #2 * ALIAS "CHOUT" * CHARACTER IS IN B * OF2 CALL SYSOT SEND IT OUT MOV A,B SUI CR JZ OF21 MOV A,B CPI ' ' RC . NO PHEAD INC FOR CTRL-CHARACTERS LDA PHEAD INR A * OF21 STA PHEAD RET * CHOUT EQU OF2 * * * CARRIAGE RETURN * IF NEEDED * CCRLF LDA PHEAD ORA A RZ * * CARRIAGE RETURN * ALWAYS * CRLF MVI B,CR CALL CHOUT MVI B,LF JMP CHOUT * * CHECK IF PANIC CHARACTER HAS BEEN HIT * PCHECK CALL SYSTS RZ * * * INPUT FILTER #3 * MASKS OFF PARITY AND CHECKS FOR ESCAPE * CHARACTER RETURNED IN A * PCHK1 CALL SYSIN ANI 7FH DIRTY LITTLE BIT! CPI ESC JNZ SPDCK * * CHECK TO SEE IF PANIC HAPPENED DURING RUN * PCHK2 PUSH B PUSH D PUSH H LDA DIRF ORA A JZ STOP1 MUST HAVE BEEN RUN MVI B,'\' MUST HAVE BEEN INPUT (OR LIST) CALL CHOUT CALL CRLF JMP CMND1 ABORT * * * VDM DRIVER CONTROL * SPDCK CPI ' ' JNZ SPED1 * * TEST SPEED CONTROL BYTE * BIT 1 0 MEANING * 0 0 ALLOW STOPPING AND SEPPD CHANGE * 0 1 DISALLOW STOPPING * 1 0 DISALLOW SPEED CHANGING * 1 1 DISALLOW BOTH * LDA SPDCTRL ANI 1 RNZ . DISALLOW * CALL SYSIN WAIT FOR NEXT KEY ANI 07FH JZ PCHK2 MODE SELECT? * SPED1 CPI '1' RC CPI '9'+1 RNC * * 1-9 IS SPEED CONTROL * SUI '0' MOV B,A XRA A SPED STC . RAL . DCR B JNZ SPED RAR . * * TEST SPEED CONTROL MOV B,A LDA SPDCTRL ANI 2 RNZ . DISALLOW MOV A,B * STA SPEED RET * * * INPUT FILTER #1 * CHARACTER IS IN A AND B * IF1 LDA CTLFG GET CTRL-CHARACTER FLAG ORA A JZ IF12 NO CTRL-CHARACTER EXPANSION MOV B,A XRA A MOV C,A ZERO DISPATCH FLAG STA CTLFG CLEAR CTRL-CHARACTER EXPANTION FLAG MOV A,B RET . NOTE: CARRY IS CLEAR * IF12 CALL IF2 GET CHARACTER * MVI C,SCHRZ SPECIAL CHARACTER TABLE SIZE (IN ENTRIES) LXI H,SCHRT ADDR OF SPECIAL CHARACTER TABLE SCTS CMP M A=M? INX H POINT TO ADDR OF ROUTINE STC . INCASE OF MATCH RZ . A=M, CARRY<>0 MEANS DISPATCH INX H INX H DCR C JNZ SCTS SPECIAL CHARACTRER TABLE SEARCH * CPI ' ' CTRL-CHARACTER? RNC . NO, RETURN CARRY IS 0 * MOV B,A LDA DIRF SEE IF IN DIRECT MODE ORA A MOV A,B RZ . XPANSION IN DIRECT MODE ONLY LDA PHEAD ORA A FIRST CHARACTER? JNZ IF13 CALL SYSOT PUT IT OUT DIRECT JMP IF12 AND GET THE NEXT * * IF13 MOV A,B ADI 64 CONVERT TO NON-CTRL-CHARACTER STA CTLFG SAVE FOR EXPANSION MVI A,'\' MOV B,A RET . NOTE: CARRY IS 0 * * * INPUT FILTER #2 * CHARACTER IN A AND B * IF2 PUSH H PUSH D PUSH B IF20 LXI H,ITIMCONST IF21 CALL SYSTS JNZ IF22 THERE IS A CHARACTER * LDA DIRF ORA A JNZ IF21 NO TIMING IN DIRECT MODE * DCX H TICK...TOCK MOV A,H ORA L JNZ IF21 LHLD ITIM GET INPUT TIME LIMIT MOV A,H ORA L JZ IF20 NOT ACTIVE DCX H SHLD ITIM UPDATE TIME LIMIT MOV A,H ORA L JZ IF23 TIME'S UP SINKER...SINKER JMP IF20 NOT YET * IF22 CALL SYSIN READ CHR, MASK AND TEST FOR ESCAPES ANI 07FH LXI H,IF24 RETURN ADDRESS AFTER 'CONT' PUSH H JZ PCHK2 POP H NOT NEEDED * IF25 POP B RESTORE REGS MOV B,A POP D POP H RET * IF23 MVI A,CR THIS IS WHAT YOU GET FOR TAKING SO LONG JMP IF25 * IF24 CALL CRLF 'CONT' COMES HERE LXI H,IPND CALL PRNT CALL CRLF JMP IF21 * IPND ASC 'INPUT PENDING"' * * * INPUT A LINE FROM THE TERMINAL * PCR EQU $ XCHG . TERMINATE AT END OF LINE (DE) PLF MVI M,CR TERMINATE AT PRESENT POSITION (HL) INR C THERE IS ALWAYS ROOM FOR A CR! (THIS WON'T BE CORRECT!) * MOV B,A LDA EOBUF GET OLD PHEAD ADD C STA PHEAD * LDA DIRF ORA A MOV A,B RNZ . NO TIME/COUNT CLEAR IF IN DIRECT MODE LXI H,0 SHLD ITIM THIS ZEROS ITIM SHLD ITIM+1 THIS ZEROS ICNT RET . RETURN C HAS LINE LENGTH * INL0 CALL CRLF ENTRY THAT RE-GETS A LINE * * THIS IS THE ENTRY TO GET A LINE * INLINE EQU $ LDA PHEAD STA EOBUF SAVE PHEAD CALL READR GET VDM ADDRESS TO 'VDMAD' INL9 LXI H,IBUF1 READ CHARACTRERS INTO IBUF MOV D,H HL=PRESENT POSITION, DE=LAST CHARACTER POSITION MOV E,L INITIALY SAME AT FIRST XRA A MOV C,A C COUNTS THE NUMBER OF CHARACTERS IN THE LINE * INL1 LDA DIRF ORA A JNZ INL1B NO COUNT LIMIT IN DIRECT MODE * LDA ICNT GET INPUT COUNT LIMIT ORA A SET? JZ INL1B NO, CONTINUE CMP C EQUAL? JZ PCR COUNT'S UP....SNIKER...SINKER * INL1B PUSH H GET NEXT CHARACTER PUSH B PUSH D CALL IF1 GET CHARACTER POP D POP B MOV B,A JC INLSD SPECIAL DISPATCH POP H * LDA INSFG TEST INSERT FLAG ORA A JNZ INSRT INSERT ON * CALL HDCMP CMP HL-DE JNZ INL2 DIDN'T PASS DE (POINTER NEXT EMPTY CELL) MOV A,C CPI LINMAX-2 JNC INL1 GREATER THAN OR EQU TO, DONT KEEP IT INX D INR C * INL2 MOV M,B PUT IN BUFFER CALL OF2 PRINT IT INX H JMP INL1 NEXT CHARACTER * * * DISPATCH TO A SPECIAL CHARACTER HANDLER * INLSD CALL LHLI GET ROUTINE ADDRESS TO HL XTHL . SAVED HL TO HL, ROUTINE ADDRESS TO STACK RET . GOTO ROUTINE (NOT A CALL) * * PROCESS BACK SPACEING * PBS CALL HDCMP AT END OF LINE? JNZ PBS0 JMP IF IN MIDDLE XRA A A=0 CMP C IS C = 0 ? JZ INL9 YES, LINE IS EMPTY DCX H DCX D BACK UP BOTH POINTERS DCR C PBS9 MVI B,5FH THIS GOES BACK ON THE SOLOS VDM DRIVER CALL OF2 PRINT IT JMP INL1 CONTINUE * PBS0 DCR C ONE LESS CHARACTER JZ INL9 LINE NOW EMPTY PUSH H * PBS1 INX H SHIFT IT ALL DOWN MOV A,M DCX H MOV M,A INX H CALL HDCMP JNZ PBS1 DCX D EOL ADDR JMP INST2 NEXT CHARACTER * * PROCESS LEFT CURSOR MOVEMENT * PLFT PUSH D LXI D,IBUF1 CALL HDCMP ALL THE WAY LEFT ALREADY? POP D JZ INL1 YES, IGNORE DCX H * PCKEY EQU $ THIS IS THE CONTROL KEY POINT * PECHO CALL OF2 PRINT CHARACTER JMP INL1 CONTINUE * * PROCESS RIGHT MOVEMENT * PRIT CALL HDCMP JNC INL1 ALREADY ALL THE WAY OVER! INX H MOVE JMP PCKEY * * PROCESS INSERT MODE ON/OFF * PIOFF XRA A INSERT MODE OFF PION STA INSFG SET INSERT FLAG JMP INL1 CONTINUE * * INSERT MODE * INSRT MOV A,C CPI LINMAX-2 DOES IT FIT? JNC INL1 NO, IGNORE COMMAND INR C INX H INX D PUSH B SAVE CHARACTER (IN B) MVI B,KRIGHT MOVE CURSOR RIGHT ONE CALL OF2 IF PTDOS, ECHO CHR; ELSE MOVE CURSOR POP B PUSH H DCX H * INST1 MOV A,M SHIFT CHARACTERS UP MOV M,B MOV B,A CALL HDCMP DONE? INX H JC INST1 NO, KEEP LOOPING * INST2 EQU $ LDA XOPORT SEE IF SPECIAL FILE HAS BEEN MADE ORA A JNZ INST4 NOT ON VDM, DON'T CHANGE SCREEN * PUSH D SAVE POINTER TO END OF BUFFER PUSH B SAVE CHARACTER COUNT AND INPUT CHARACTER LXI D,IBUF1 BUFFER POINTER LHLD VDMAD SCREEN POINTER MOV A,C CHARACTER COUNT TO MOVE CPI 128+1 JC INST3 MVI C,128 MAX TO MOVE IS 128 * INST3 XCHG MOV B,M CHARACTER FROM IBUF1 XCHG MOV A,M CHARACTER FROM SCREEN ANI 80H EXTRACT "CURSOR" BIT ORA B ADD "CURSOR" BIT TO B MOV M,A CHARACTER TO VDM SCREN INX H INX D DCR C DONE? JNZ INST3 * MOV A,M FORCE LAST CHARACTER TO BLANK ANI 80H PRESERVE "CURSOR" BIT ORI 20H MAKE LAST CHARACTER BLANK MOV M,A * POP B POP D INST4 EQU $ POP H JMP INL1 DONE INSERTING/DELETING, CONTINUE * * * READ VDM SCREEN ADDRESS * READR XRA A STA INSFG INIT INSFG TO OFF CALL VDADD GET THE CORRESPONDING VDM ADDRESS SHLD VDMAD SAVE ADDRESS RET * CLR2L LDA VLY DCR A STA VLY CALL VDADD CALL CLINE CLEAR BOTH OF THEM * CLINE MVI C,64 CLIN MVI A,' ' CLIN1 MOV M,A ALL SPACED OUT INX H DCR C JNZ CLIN1 LOOP TO END OF LINE RET * * * THE VDM DRIVER * VDMEM EQU 0CC00H SCREEN ADDRESS DSTAT EQU 0FEH * SYSOT PUSH H PUSH B PUSH D PUSH PSW LDA XOPORT SEE IF THERE IS AN OUTPUT FILE ORA A JZ VDMOT NO USE INTERNAL DRIVER CALL WB JMP DKERR GOBK POP PSW POP D POP B POP H RET * * * * VIDEO DISPLAY ROUTINES * * * THESE ROUTINES ALLOW FOR STANDARD VIDEO TERMINAL * OPERATIONS. ON ENTRY, THE CHARACTER FOR OUTPUT IS IN * REGISTER B AND ALL REGISTERS EXCEPT "A" AND FLAGS ARE * UNALTERED ON RETURN. * * * * * * ROUTINE TO REMOVE CURSOR * VDMOT EQU $ * CALL CREM REMOVE CURSOR LDA VLX SEE IF MORE THAN 64 CHARS ON SCREEN CPI 64 JC CHPK1 MOV A,B CPI CR DON'T SCROLL IF A CARRIAGE RETURN JZ CHPK1 CALL PCLF DO A CRLF IF NEEDED * CHPK1 LXI H,TBL POINT TO SPECIAL CHARACTER TABLE CALL TSRCH GO PROCESS * GOBACK CALL VDADD GET SCREEN ADDRESS LDA CURFG GET CURSOR BIT XRA M MOV M,A CURSOR IS BACK ON IF WANTED LHLD SPEED-1 GET DELAY SPEED INR L MAKE SURE IT IS NON-ZERO XRA A DELAY WILL END WHEN H=0 * TIMER DCX H TIMER DELAYS HERE CMP H DONE WITH DELAY YET? JNZ TIMER KEEP DELAYING JMP GOBK * * * REMOVE THE CURSOR * CREM CALL VDADD GET CURRENT SCREEN ADDRESS LDA CURFG ORA A RZ . NO CURSOR HANDELING XRA M MOV M,A CURSOR IS OFF RET * * * * THIS ROUTINE SEARCHES THROUGH A SINGLE CHARACTER * TABLE FOR A MATCH TO THE CHARACTER IN "B". IF FOUND * A DISPATCH IS MADE TO THE ADDRESS FOLLOWING THE MATCHED * CHARACTER. IF NOT FOUND THE CHARACTER IS DISPLAYED ON * THE MONITOR. * * VNEXT INX H INX H * TSRCH MOV A,M GET CHR FROM TABLE ORA A JZ CHAR ZERO IS THE LAST CMP B TEST THE CHR INX H POINT FORWARD JNZ VNEXT PUSH H FOUND ONE...SAVE ADDRESS XTHL . GET DISPATCH ADDRESS TO HL JMP CSET1 IN BASIC * * * PUT CHARACTER TO SCREEN * CHAR MOV A,B ANI 7FH RZ . CPI 7FH IS IT A DEL? RZ . GO BACK IF SO * * * PUT CHARACTER ON SCREEN * CALL VDADD GET SCREEN ADDRESS LDA CHRPO GET CHARACTER POLARITY ORA B ADD IT TO CHARACTER MOV M,A PUT CHR ON SCREEN * * INCREMENT LINE COUNTER * OK LDA VLX GET CHR POSITION INR A STA VLX RET . DON'T TEST FOR END OF LINE HERE * * PDOWN LDA VLY INR A CURSC ANI 0FH MOD 15 INCREMENT CUR STA VLY STORE THE NEW RET * * ERASE SCREEN * PERSE LXI H,VDMEM POINT TO SCREEN MVI B,16 ERAS1 CALL CLINE DCR B JNZ ERAS1 XRA A STC . CARRY WILL SAY COMPLETE ERASE * PHOME MVI A,0 RESET CURSOR--CARRY=ERASE, ELSE HOME STA VLY ZERO LINE STA VLX LEFT SIDE OF SCREEN STA PHEAD RNC . IF NO CARRY, WE ARE DONE WITH HOME * ERAS3 OUT DSTAT RESET SCROLL PARAMETERS OUT 0C8H STA BOT BEGINNING OF TEXT OFFSET RET * * * * MOVE CURSOR LEFT ONE POSITION * PLEFT LDA VLX DCR A STA PHEAD PCUR EQU $ CURSOR ON SAME LINE STA VLX UPDATED CURSOR RP . IF WE DIDN'T WRAP LDA VLY DCR A DECREMENT THE LINE STA VLY MVI A,63 STA VLX RET * * CURSOR RIGHT ONE POSITION * VPRIT LDA VLX INR A JMP PCUR * * ROUTINE TO CALCULATE SCREEN ADDRESS * * ENTRY AT: RETURNS: * * VDADD CURRENT SCREEN ADDRESS * VDAD2 ADDRESS OF CURRENT LINE, CHAR 'C' * VDAD LINE 'A', CHARACTER POSITION 'C' * VDADD LDA VLX GET CHARACTER POSITION ANI 3FH KEEP IT IN PROPORTION MOV C,A 'C' KEEPS IT LDA VLY LINE POSITION * VDAD MOV L,A INTO 'L' LDA BOT GET TEXT OFFSET ADD L ADD IT TO THE LINE POSITION RRC . TIMES TWO RRC . MAKES FOUR MOV L,A L HAS IT ANI 3 MOD THREE FOR LATER ADI CURSOR LDA VLX CMA INR A -VLX ADI 64 -VLX+64=64-VLX=CHARACTERS LEFT ON LINE MOV C,A CNZ CLIN CLEAR C CHARACTER POSITIONS AT HL XRA A JMP PCUR AND STORE THE NEW VALUE * * ROUTINE TO PROCESS LINEFEED * PCLF XRA A STA VLX VPLF LDA VLY GET LINE COUNT INR A ANI 15 SEE IF IT WRAPPED AROUND JNZ CUR NO--NO NEED TO SCROLL * * * END OF SCREEN...ROLL UP ONE LINE * SROL MOV C,A CALL VDAD CALCULATE LINE TO BE BLANKED CALL CLINE CLEAR IT LDA BOT INR A ANI 0FH JMP ERAS3 * * * DISPLAY DRIVER COMMAND TABLE * * THIS TABLE DEFINES THE CHARACTERS FOR SPECIAL * PROCESSING. IF THE CHARACTER IS NOT IN THE TABLE IT * GOES TO THE SCREEN. * TBL DB VCLEAR SCREEN DW PERSE DB KLEFT DW PLEFT DB KRIGHT DW VPRIT DB HOME DW PHOME DB CR CARRIAGE RETURN DW VPCR DB LF LINE FEED DW VPLF DB BACKS BACK SPACE DW PBACK DB 0 END OF TABLE * BACKS EQU 05FH HOME EQU 'N'-40H VCLEAR EQU 'K'-40H * CURFG DB 80H CURSOR FLAG ON CHRPO DB 0H CHARACTER POLARITY NORMAL DB 80H SPEED DB 0 VLY DB 1 VLX DB 0 BOT DB 0 * * * SPECIAL CHARACTER TABLE * SCHRT DB CR DW PCR DB BS DW PBS DB KRIGHT DW PRIT DB KCAN DW INL0 DB KLEFT DW PLFT DB KION DW PION DB KIOFF DW PIOFF DB KLF DW PLF SCHRZ EQU $-SCHRT/3 TABLE LENTH IN ENTRIES * * * * I/O RELATED RAM * XOPORT DB 1 XIPORT DB 0 VDMAD DS 2 FOR EDIT STORAGE WHEN ON INTERNAL VDM ITIM DS 2 INPUT TIME LIMIT ICNT DS 1 INPUT COUNT LIMIT LINLEN DS 1 LENGTH OF A LINE TWIDTH DB 14 WIDTH OF A COMMA TAB FIELD PHEAD DB 0 PRINTER HEAD POSITION SPDCTRL DS 1 SPEED CONTROL BYTE * DS 1 FOR THE '!' OBUF DS WMAX+1 FOR NUMERIC CONVERTIONS EOBUF DS 1 FOR THE '"' * IBCNT DS 1 CURRENT LINE LENGTH (OF INCOMMING LINE) IBLN DS 2 CURRENT LINE NUMBER (OF INCOMMING LINE) IBUF DS LINMAX/2 THE I/O BUFFER IBUF1 DS LINMAX * * * STACK DEFINITION * STKTOP DS SSIZE THE STACK CMNDSP EQU STKTOP+SSIZE-1 ADDR OF TOP OF STACK CSPM1 EQU CMNDSP-1 SPCMND EQU CMNDSP/256*256 TSTKA DS 2 TOP OF ARG STACK POINTER SPTR DS 2 STACK SAVE FOR 'CONTINUE' * *