;REMSCRN.ASM ; ;WRITTEN 2/28/86 BY JOHN GOTSCHALL ; ; ; ; ; GENERIC SCREEN CONTROL STRING FILTER ; REPLACES OUTBOUND SCREEN COMMAND STRINGS WITH ; STRINGS THAT PERFORM IDENTICLE FUNCTIONS ON A ; REMOTE CONSOLE, THIS PROGRAM WAS DEVELOPED FOR ; USE IN AN APPLICATION WHERE A BUSINESS HAD A CP/M ; MACHINE RUNNING DBASE II, THEY DID NOT WANT TO ; GET A MULTI-USER MACHINE, BUT THEY DID WANT ; SIMULTANEOUS I/O TO A REMOTE HAZELTINE 1500, SO ; THAT WHEN ONE TERMINAL WAS NOT IN USE THE OTHER COULD ; BE USED, VERY SIMILAR IN FUNCTION TO A BYE PROGRAM, ; WITH THE EXCEPTION THAT THERE WAS NO MODEM INVOLVED. ; THE REMOTE IN THIS CASE HAD A DIFFERENT SET OF SCREEN COMMAND ; SEQUENCES THAN THE LOCAL, NECESSITATING CONVERSION ; OF THE LOCAL'S NATIVE COMMAND STRINGS INTO THE REMOTES ; NATIVE TONGUE. THIS MODULE PERFORMS THAT FUNCTION, ; RATHER NICELY. ; ; I WROTE THIS LITTLE THING, AND AS IT IS MY VERY FIRST ; 100% SUCCESSFUL ASSEMBLY PROGRAM WITH PRACTICAL APPLICATION, ; I HAVE MADE IT AVAILABLE TO THE GENERAL PUBLIC AND THUS ; MAY BE USED BY ANY PERSON FOR NON-PROFIT USE. IF YOU ; DO USE IT FOR PROFIT, YOU OWE ME ONE U.S. DOLLAR FOR ; EVERY PERSON THAT USES IT. (PRETTY CHEAP HUH?, THAT'S NOT ; ASKING A HECK OF A LOT.) ; ; IF YOU OWE ME A BUCK SEND IT TO: ; ; JOHN GOTSCHALL ; PO BOX 2475 ; SEATTLE WA 98111 ; ; ANYWAY, IMPLEMENTATION OF THIS CODE SHOULD BE PRETTY ; OBVIOUS, JUST PATCH THE FIRST TABLE WITH THE VALUES ; FOR YOUR LOCAL TERMINAL, THEN PLACE THE APPROPRIATE ; REPLACEMENT VALUES INTO THE SECOND TABLE, WHEN OUTPUTTING ; TO THE REMOTE, IF THE STRING THAT APPEARS IN THE FIRST ; FOUR BYTES OF THE FIRST TABLE GETS SENT TO THE LOCAL, ; THE CONTENTS OF THE FIRST FOUR BYTES OF THE SECOND ; TABLE WILL BE SENT TO THE REMOTE IN PLACE OF WHAT WAS SENT ; TO THE LOCAL. IF YOU ARE USING A BYE PROGRAM, ALL YOU ; NEED TO DO IS ADD THIS CODE TO YOUR BYE PROGRAM SOURCE ; CODE (MAKING SURE TO FIX ANY DUPLICATED LABELS), THEN HAVE ; YOUR BBS PROGRAM POKE THE VALUES FOR THE REMOTE'S ; COMMAND STRINGS INTO THE SECOND TABLE, THEN YOUR BYE ; MERGED WITH THIS PROGRAM WILL TAKE CARE OF MAKING ; SURE THE REMOTE GETS SCREEN CONTROL SEQUENCES THAT IT CAN ; UNDERSTAND, YET YOUR BBS PROGRAM NEED NOT DO ANYMORE ; THAN PRETEND THAT YOUR LOCAL AND THE REMOTE HAVE THE ; SAME SCREEN COMMAND SET. WORKS PERFECT WITH THE ; BUILT IN COMMANDS LIKE IN DBASE II AND TURBO PASCAL, ; IT EVEN WORKED PERFECT WITH WORDSTAR IN MY APPLICATION. ; WELL, IF YOU HAVE READ ALL OF THIS, I CERTAINLY HOPE YOU ; CAN MAKE USE OF THIS PROGRAM, AS YOU ALREADY HAVE SOME ; TIME INTO IT. ; ; BE FORWARNED, WHILE THIS CODE NEVER USES A STACK, ; IT WILL, WITHOUT A DOUBT DESTROY THE CONTENTS OF ; THE CPU REGISTERS, SO SAVE ANYTHING YOU WANT TO KEEP ; BEFORE CALLING THIS SUBROUTINE!!!!! ; ; DELIVER OUTBOUND CHARACTERS TO THIS ROUTINE IN BOTH ; THE A AND C REGISTERS !! ; ; ;======================================================= ;The following section of code filters the output to the remote, ;checking for the presence of screen command sequences, and when ;encountered, replaces the strings that are native to the local ;with strings that are native to the remote. This is done ;through the use of two look-up tables. The first of the two ;tables contains all of the sequences that are expected to be ;sent out, and are in code that is native to the local screen. ;the second table is where we patch in the corresponding strings, ;but there they are the strings that the remote will recognize ;as they are native to the remote. ;======================================================= ; ;****************************************************** ;There are many calls to a routine labeled 'REMOUT', ;you will not find remout in this listing, whenever this ;code calls remout, it thinks that it is delivering a ;single character to the remote... all waiting for status ;for the remote must take place in remout, your version ;of bye should already have a routine to output characters ;to the remote..... THAT routine is the one that this code ;refers to when it calls remout. The character to be sent to the ;renote from this code will be found in the C register whenever remout ;is called. ;******************************************************** ; ; ;THE FOLLOWING TWO TABLES ARE 60 BYTES LONG, THEY ARE ;ORGANIZED SO THERE ARE 15 STRINGS OF 4 BYTES. THE FIRST ;TABLE IS SCANNED PRIOR TO ANY OUTPUT TO THE REMOTE, IF ;THE CURRENT OUTBOUND CHARACTER MATCHES ANY OF THE CHARACTERS ;IN THE FIRST POSITIONS OF THE FIRST TABLE, THE CHARACTER IS ;BUFFERED, WHEN THE NEXT CHARACTER COMES THROUGH, A TEST IS ;MADE TO FIND ANY WHOLE MATCHING STRINGS, IF THERE IS A ;POSSIBILITY OF A MATCH ON THE THIRD CHARACTER, THE SECOND ;CHARACTER IS BUFFERED, AND THE ROUTINE WAITS UNTIL THE ;THIRD CHARACTER COMES THROUGH, IT THEN TESTS TO SEE IF ;THERE IS A POSSIBILITY OF A COMPLETE MATCH. ON CHARACTERS ;2, AND 3, CHECKS ARE MADE FOR BOTH PENDING MATCHES, AND ;COMPLETE MATCHES, ANY COMPLETE MATCHES WIN AND ARE IMMEDIATLY ;CONVERTED TO THE REMOTE'S COMMAND SET, AND ARE IMMEDIATLY SENT OUT ;TO THE REMOTE. ; ;IF THERE IS A MATCH IN ANY OF THE STRINGS IN THE FIRST TABLE ;THE STRING IS REPLACED WITH THE CONTENTS OF THE SAME POSITIONS ;IN THE SECOND TABLE... ANY STRINGS MAY BE PUT IN ANY LOCATIONS, ;WITH THE EXCEPTION THAT THE LAST STRING OF 4 IN EACH TABLE IS ;RESERVED FOR THE CURSOR POSITIONING LEAD IN STRINGS, THE ;FOLLOWING THREE BYTES ARE FOR THE X AND Y COORDINATES AND ;THERE IS A FLAG THAT DENOTES WHICH COORDINATE COMES FIRST. ; ;THE MAXIMUM LENGTH FOR ANY COMMAND STRING IS FOUR BYTES! ; INSTNG EQU $+OFFSET DB 01BH,045H,01BH,048H ;CLEAR AND HOME CURSOR DB 01BH,05AH,0,0 ;CLEAR TO EOL DB 01BH,04AH,0,0 ;CLEAR TO EOS DB 27,69,0,0 ;ANOTHER STRING THAT IS CL & HME DB 01BH,048H,01BH,045H ;YET ANOTHER CL & HOME STRING DB 01BH,'K',0,0 ;IF LESS THAN 4 BYTES LONG, DB 0,0,0,0 ;LEAVE 0'S TO FILL THE EXTRAS, DB 0,0,0,0 ;THE ZEROS WON'T BE SENT OUT DB 0,0,0,0 DB 0,0,0,0 DB 0,0,0,0 DB 0,0,0,0 DB 0,0,0,0 DB 0,0,0,0 DB 27,70,0,0 ;**LEAD-IN** CHARACTERS FOR THE ;LOCAL CONSOLE'S CURSOR POSITIONING ;STRING, IF LESS THAN 4 BYTES LONG, ;LEAVE A '0' TO FILL THE EXTRAS ; ICCC EQU $+OFFSET DB 2 ;WHICH COORDINATE CARRIES THE COLUMN DATA? ;THE FIRST OR THE SECOND ; ICCO EQU $+OFFSET DB 32 ;VALUE OF COLUMN OFFSET FOR LOCAL ; ICRO EQU $+OFFSET DB 32 ;VALUE OF ROW OFFSET FOR LOCAL ; ; OUTSTNG EQU $+OFFSET DB 07EH,01CH,0A0H,0 ;REPLACEMENT COMMAND STRINGS DB 07EH,0FH,0,0 ;THAT ARE TO BE INSERTED IN THE DB 07EH,018H,0,0 ;DATA FLOW TO THE REMOTE IN DB 07EH,01CH,0A0H,0 ;IN PLACE OF THE COMMAND STRINGS DB 07EH,01CH,0A0H,0 ;FOUND IN THE ABOVE TABLE. THE DB 07EH,0FH,0,0 ;STRINGS IN THE TABLE ABOVE MUST DB 0,0,0,0 ;MATCH THE STRINGS THAT WILL BE DB 0,0,0,0 ;SENT TO THE LOCAL CONSOLE, WHILE DB 0,0,0,0 ;THESE MUST CARRY THE STRINGS FOR DB 0,0,0,0 ;THE SAME FUNCTIONS, BUT IN THE DB 0,0,0,0 ;REMOTE'S NATIVE TONGUE. DB 0,0,0,0 ;IF LESS THAN 4 BYTES LONG, DB 0,0,0,0 ;LEAVE 0'S TO FILL THE EXTRAS, DB 0,0,0,0 ;THE ZEROS WON'T BE SENT OUT DB 07EH,011H,0,0 ;**LEAD-IN** CHARACTERS FOR THE ;REMOTE CONSOLE'S CURSOR POSITIONING ;STRING, IF LESS THAN 4 BYTES LONG, ;LEAVE 0'S TO FILL THE EXTRAS, ; ;THE ZEROS WON'T BE SENT OUT ; OCCC EQU $+OFFSET DB 1 ;POSITION IN CURSOR POSITIONING ;STRING THAT CARRIES THE COLUMN ;FOR REMOTE ; OCCO EQU $+OFFSET DB 0 ;VALUE OF COLUMN OFFSET FOR REMOTE ; OCRO EQU $+OFFSET DB 0 ;VALUE OF ROW OFFSET FOR REMOTE ; ; ;MOVE (HL) TO (DE) LENGTH IN (B) ; ;THE FOLLOWING IS COMMENTED OUT, THIS ROUTINE IS DUPLICATED EXACTLY ;IN MY VERSION OF BYE.COM, SO I DON'T NEED THIS AGAIN, BUT IF YOUR ;VERSION OF BYE.COM DOES NOT HAVE THIS ROUTINE IN IT, USE THIS ONE ;OR IF YOU MAKE AN OVERLAY OF THIS FILE YOU WILL NEED IT ; ; ;MOVE EQU $+OFFSET ; MOV A,M ;GET A BYTE ; STAX D ;PUT IT IN NEW HOME ; INX D ;BUMP POINTERS ; INX H ; DCR B ;DEC BYTE COUNT ; JNZ MOVE ;IF MORE, DO IT ; RET ;IF NOT, RETURN ; ;************************************************** ;************************************************** ;* MAIN PROGRAM SECTION, THIS IS THE PART THAT * ;* DOES ALL THE FILTERING OF CURSOR COMMAND * ;* SEQUENCES....... * ;************************************************** ; ; ;the call to vconout below calls the routine that is already ;in my version of bye. I replaced the call for vconout in ;my version of bye with a call for 'OUTPUT' below, so that the ;program comes here just prior to outputing to the local. ; OUTPUT EQU $+OFFSET CALL STRT ;STORE CHAR IN FIRST EMPTY BUFFER LOC CALL VCONOUT ;SEND IT TO THE LOCAL ; MT1 EQU $+OFFSET LDA CLCF ;POINT TO CURSOR LOCATION COMMAND FLG CPI 1 ;ARE WE AWAITING A CURSOR COMMAND? JZ CPF ;YES, GOTO CURSOR POS.FILTER MT2 EQU $+OFFSET LDA MTSTR ;POINT TO MATCHSTRING CPI 01H ;IS IT A 1? JZ MMF ;THERE WAS A PRIVIOUS MATCH, AND NOT A CURSOR ;COMMAND, SO ;LETS TAKE THIS CHAR TO THE MAIN ;MATCH FINDER MT3 EQU $+OFFSET JMP QCHK ;NOTHING MATCHED LAST TIME ;WE OUTPUTTED, AND WER'E NOT LOOKIN ;FOR A CURSOR COORDINATE, SO LET'S JUST ;QUICKLY SCAN FOR A FIRST ;CHAR MATCH ; QCHK EQU $+OFFSET LXI H,BUFLOC ;GET THE ADDRESS OF THE BUFFER SHLD BUFPTR ;PUT IT IN THE BUFFERPOINTER LXI H,INSTNG ;GET THE ADDRESS OF INSTING SHLD INSPTR ;PUT IT IN THE POINTER MOV B,C ;SAVE THE CHAR IN B MVI A,0 STA COUNT STA COUNT1 LXI H,INSTNG ;POINT TO THE BEGINNING OF THE INSTING QCHCK1 EQU $+OFFSET MOV A,M ;GET THE CONTENTS CMP C ;IS IT THE SAME AS OUR CHAR? JZ ST1MT ;IT'S A MATCH QCHK2 EQU $+OFFSET INX H ;BUMP INX H ;UP TO THE INX H ;BEGINNING OF THE NEXT INX H ;STRING OF FOUR BYTES LDA COUNT INR A STA COUNT ;KEEP TRACK OF WHICH GROUP OF FOUR WERE' ON CPI 0FH ;PAST 15 YET?, IF SO, THEN THERE IS NO POSSIBLE JZ DONE ;MATCH SO GO DUMP THE CHARACTER FROM THE BUFFER JMP QCHCK1 ST1MT EQU $+OFFSET LXI H,MTSTR ;THERE IS A MATCH IN ONE OF THE FIRST MVI A,1 ;POSITIONS OF THE INSTRING LINES MOV M,A ;LEAVE NOTE OF THIS IN THE MTSTR GROUP. RET ;TO CP/M, WE'LL SEND OUT THIS CHAR LATER.. ; ; ;########################### ; ; MMF (MAIN MATCH FINDER, ; ROUTINE CHECKS ENTIRE INSTRING, COMPARES TO THE CONTENTS OF THE ; BUFFER TO THE INSTNG TABLE, MAKES NOTATION TO SHOW POSSIBLE ; PENDING MATCHES, OR PARTIAL BUT IMPOSSIBLE MATCHES, AND MAKES ; THE FINAL DECISION ON WHETHER OR NOT THERE IS A MATCH OF ; AN ENTIRE STRING. ; ; ; MMF EQU $+OFFSET LXI H,INSTNG ;GET ADDRESS OF INSTNG INTO (D,E) SHLD INSPTR ;RESET POINTER LXI H,BUFLOC ;POINT TO FIRST BUFFER POSITION SHLD BUFPTR ;RESET BUFPTR MVI A,0 ;GET A 0 STA POSMTCH ;RESET POSSIBLE MATCH FLAG STA COUNT ;RESET COUNT FLAG STA COUNT1 ENT EQU $+OFFSET LDA COUNT1 ;REACHED END OF INSTNG? CPI 15 JZ ANT1 ;YEP...GO AND CHECK FOR A PENDING MATCH... ;IT MAY BE THAT WE NEED TO WAIT FOR MORE ;CHARACTERS TO COME THROUGH... LHLD BUFPTR ;POINT TO THE CURRENT BUFFER ADDRESS ; ;COME INTO ENT1 WITH THE CURRENT BUFFER ADDR IN HL ; ENT1 EQU $+OFFSET MOV A,M ;GET VALUE OF CHAR AT BUFFER LHLD INSPTR ;POINT TO TABLE CMP M ;DOES BUFFER CHAR MATCH TABLE CHAR? JNZ ENT7 ;NOPE... ENT2 EQU $+OFFSET LDA COUNT ;IF WE ARE AT THE FIRST OF 4, CPI 0 ;COUNT WILL BE 0 JNZ ENT6 ;NOPE... ENT3 EQU $+OFFSET MVI A,1 ;SINCE THERE IS A MATCH IN THE STA POSMTCH ;FIRST OF 4 IN THE TABLE, MAKE ;A NOTE OF IT ENT4 EQU $+OFFSET LXI H,MTSTR ;POINT TO MATCHSTRING LDA COUNT ;ALSO MAKE NOTE IN THE MATCHSTRING MOV B,A ;ADD COUNT TO MATCHSTR LOCATION ENT4A EQU $+OFFSET MOV A,B ;MAKE SURE WE STILL HAVE IT CPI 0 ;MATCHING LOCATIONS YET? JZ ENT4B ;YEP INX H ;BUMP POINTER DCR B ;COUNTDOWN JMP ENT4A ENT4B EQU $+OFFSET MVI A,1 ;GET A ONE MOV M,A ;PUT THE FLAG INTO THE MATCHSTRING ENT5 EQU $+OFFSET LDA COUNT ;CECK TO SEE IF THIS IS THE CPI 3 ;4TH CHAR IN THE STRING JNZ ENT8 ;NOPE, GO DO SOME MORE.... JMP WHM ;WE HAVE A FULL MATCH FOR A WHOLE ;STRING OF FOUR !!!!!!! ENT6 EQU $+OFFSET LDA POSMTCH ;IS THERE A POSSIBLE MATCH? CPI 1 ; JZ ENT4 JMP ENT8 ENT7 EQU $+OFFSET LXI H,POSMTCH ;POINT TO POSMTCH MVI A,0 ;GET A 0 MOV M,A ;RESET POSMTCH ENT8 EQU $+OFFSET LHLD BUFPTR ;GET THE ADDRESS IN THE BUFFER POINTER INX H ;INCREMENT IT SHLD BUFPTR ;PUT IT BACK LHLD INSPTR ;GET THE ADDRESS IN THE INSTRING POINTER INX H ;INCREMENT IT SHLD INSPTR ;PUT IT BACK LDA COUNT ;GET THE COUNT INR A ;INCREMENT IT STA COUNT ;PUT IT BACK ENT9 EQU $+OFFSET LDA COUNT ;MAKE SURE WE HAVE THE COUNT CPI 4 ;PAST THE 4TH CHAR YET? JNZ ENT ;NOPE , GO DO MORE ENT10 EQU $+OFFSET MVI A,0 ;WE'RE AT HE 4TH, SO STA COUNT ;RESET COUNT LDA COUNT1 ;WERE LOOKING AT THE NEXT INR A ;STRING IN THE TABLE, SO STA COUNT1 ;MAKE NOTE OF THAT LXI H,BUFLOC ;ALSO, ON THE NEXT PASS, SHLD BUFPTR ;WE WANT TO POINT TO ;THE FIRST CHAR IN THE BUFFER JMP ENT ;################################################ ; ;END OF MATCH FINDER, IF THERE WAS NO EXACT MATCH, ;WE MAY JUST NOT HAVE ALL THE CHARACTERS YET, SO NOW WE CHECK TO ;SEE IF ANY PARTIAL MATCH IS A POSSIBLE MATCH ; ANT1 EQU $+OFFSET LXI H,MTSTR ;POINT TO THE FIRST POS OF MTSTR MOV A,M ;GET THE CONTENTS CPI 1 ;IS IT A ONE? JNZ DONE ;NOPE, GO EMPTY BUFFER TO REMOTE, ;THERE IS NO CHANCE OF A MATCH.. ANT2 EQU $+OFFSET INX H ;POINT TO NEXT LOCATION IN MTSTR MOV A,M ;IS IT A ONE? CPI 1 ;NOPE, JNZ BZ ;GO CHECK BUFFER STRING ANT3 EQU $+OFFSET INX H ;POINT TO NEXT LOCATION MOV A,M ;GET CONTENTS CPI 1 JNZ BZ1 ;GO CHECK BUFFER STRING JMP BZ2 BZ EQU $+OFFSET LXI H,BUFLOC ;POINT TO BUFFER INX H ;POINT TO 2ND CHAR MOV A,M ;GET THE CHAR CPI 0 ;IS THE POSITION IN THE BUFFER EMPTY? RZ ;YES, THEN RETURN TO CP/M, LEAVE ALL AS IT ;IS, THERE MAY BE MORE CHARACTERS NEEDE TO ;MAKE A MATCHING STRING JMP DONE ;THERE IS NO POSSIBILITY OF A MATCH, ;SO GO DUMP THE BUFFER BZ1 EQU $+OFFSET LXI H,BUFLOC ;POINT TO THE INX H ;3RD CHAR IN BUFFER INX H ;THERE WE ARE..... MOV A,M ;GET THE CHAR, IS IT EMPTY? CPI 0 RZ ;YEP, SAME AS IN BZ.... JMP DONE BZ2 EQU $+OFFSET LXI H,BUFLOC ;SAME AS BZ & BZ1, INX H INX H INX H ;BUT CHECK THE LAST CHAR IN BUFFER MOV A,M ;GET THE CHAR.. CPI 0 ;IS THE POSITION EMPTY? RZ ;STILL EMPTY,GO TO CP/M AND TO IT AGIN, JMP DONE ;BUFFER IS FULL AND NO MATCHES, SO GO EMPTY ;THE BUFFER. ;***************************************** ;END OF MAIN MATCH FINDER..... ;**************************************** ; ; ; ;**************************************** ;THIS IS WHERE WE GO WHEN WE HAVE A MATCH ;WE NEED TO SEND OUT THE STRING THAT CORRESPONDS TO ;THE STRING THAT MATCHED IN THE TABLE, IF IT WAS THE ;CURSOR POSITIONING STRING, WE WILL HAVE TO HANDLE THAT HERE ALSO. ; WHM EQU $+OFFSET LXI H,BUFLOC ;POINT TO BUFFER XCHG ;MOVE TO DE WHM1 EQU $+OFFSET LXI H,COUNT1 MOV B,M ;PUT THE VALUE INTO B: LXI H,OUTSTNG ;GET THE ADDRESS OF THE TABLE WHM2 EQU $+OFFSET MOV A,B ;PUT B INTO A CPI 0 ;POINTING TO THE CORRECT SUBSTRING? JZ WHM3 ;YEP INX H ;MOVE POINTER UP INX H ;BYE FOUR, THUS INX H ;POINTING AT INX H ;THE NEXT SUBSTRING IN THE OUTSTNG DCR B ;BUMP B DOWN JMP WHM2 ;LOOP SOME MORE WHM3 EQU $+OFFSET MVI B,4 ;4 BYTES TO MOVE CALL MOVE ;MOVE THE CONTENTS TO THE BUFFER ;****************************** ;DONE MOVING THE NEW STRING INTO THE BUFFER, NOW LET'S ;SEE IF IT IS A CURSOR POSITIONING STRING.... ; LDA COUNT1 ;GET THE TABLE STRING POINTER CPI 14 ;IS IT A CURSOR COMMAND? JNZ DONE ;NOPE, SO GO EMPTY BUFFER & RESET ALL MVI A,1 ;GET A 1 STA CLCF ;SET CURSOR COMMAND FLAG TO TRUE JMP DONE ;GO EMPTY THE BUFFER TO THE REMOTE.... ;******************************** ;SINCE WE JUST SET THE CLCF, WE WILL COME HERE ON ;THE NEXT 2 CONSOLE OUTPUT CALLS.... ;OUR VALUE IS IN THE BUFFER, BUT IF THE SECOND BUFFER POSITION ;IS EMPTY, THEN WE NEED ONE MORE CHARACTER... ;ALSO, SINCE ONE OR BOTH OF OUR CURSOR AND ROW VALUES ;MAY BE A 0, WE'LL DUMP THE BUFFER HERE INSTEAD OF USING ;THE 'DONE ' ROUTINE.... ;WE ARE COUNTING ON GETTING AN OFFSET OF >0 FROM THE LOCAL ;FOR THE FIRST POSITION... CPF EQU $+OFFSET LXI H,BUFLOC ;POINT TO THE BUFFER'S INX H ;SECOND POSITION MOV A,M ;GET THE CHAR CPI 0 ;IS THERE A CHAR THERE? RZ ;NOPE, GOTO CP/M AND AWAIT ANOTHER CPF1 EQU $+OFFSET ;NOW WE HAVE THE TWO CHARACTERS WE WANT LXI H,OCCC ;POINT TO THE FIRST BUFFER LOCATION MOV B,M ;GET THE VALUE INTO B LDA ICCC ;GET THE OTHER ONE CMP B ;DO THEY MATCH? JZ CPF2 ;YEP,DON'T NEED TO REVERSE THE BUFFER CONTENTS LDA BUFLOC ;GET THE FIRST CHAR MOV B,A ;SAVE IT IN B LDA BUFLOC+1 ;GET THE NEXT ONE STA BUFLOC ;PUT IT WHERE THE FIRST ONE WAS MOV A,B ;GET THE ONE THAT WAS THE FIRST STA BUFLOC+1 ;AND PUT IT IN THE SECOND POSITION ; ;NOW MODIFY THE X,Y COORDINATE VALUES ;BY STRIPPING THEM OF THEIR ORIGINAL OFFSET(S) ; CPF2 EQU $+OFFSET LXI H,ICCO ;POINT TO VAL OF LOCAL OFFSET LDA BUFLOC ;GET THE FIRST CHAR SUB M ;SUBTRACT THE OFFSET STA BUFLOC ;PUT IT BACK LXI H,ICRO ;POINT TO VAL OF 2ND LOCAL OFFSET LDA BUFLOC+1 ;GET 2ND VAL FROM BUFFER SUB M ;SUBTRACT THE OFFSET STA BUFLOC +1 ;PUT IT BACK ; ;NOW ADD THE NEW OFFSETS TO THEM ; CPF3 EQU $+OFFSET LXI H,OCCO ;POINT TO THE OUTSTNG VALUE LDA BUFLOC ;GET THE VALUE OF THE 1ST CHAR ADD M ;ADD THE NEW OFFSET STA BUFLOC LXI H,OCRO ;POINT TO THE OTHER ONE LDA BUFLOC+1 ;GET THE SECOND VAL FROM BUFFER ADD M ;ADD THE NEW OFFSET STA BUFLOC+1 ;PUT IT BACK LDA BUFLOC ;GET 1ST CHAR MOV C,A ;PUT IT IN C CALL REMOUT ;SEND IT OUT LDA BUFLOC+1 ;GET SECOND MOV C,A ;PUT IT IN C CALL REMOUT ;SEND IT OUT MVI A,0 ;NOW KILL THE CHARS IN THE BUFFER STA BUFLOC STA BUFLOC+1 CALL DONE2 ;USE DONE'S ROUTINES TO CLEAR THINGS INIT9 EQU $+OFFSET LXI H,CLCF ;POINT TO THE FIRST OF THE FLAGS AND BUFFERS LXI B,BUFPTR-CLCF ;# OF VARIABLES TO CLEAR MVI A,0 ;GET A ZERO INIT10 EQU $+OFFSET MOV M,A ;PUT IT IN THE VAR OR FLAG DCX B ;BUMP COUNTER MOV B,A CPI 0 RZ ;ALLDONE, BACK TO CP/M INX H ;POINT TO NEXT BYTE MVI A,0 ;GET THE ZERO BACK JMP INIT10 ;******************************************** ;DONE OUTPUTTING ANYTHING THAT COMES ALONG, CONVERTED AS NECESSARY ;****************************************** ; ;COME HERE WITH A NEW CHARACTER, BEFORE OUTPUTING IT TO ;THE LOCAL ; STRT EQU $+OFFSET MVI A,0 STA COUNT ;ZERO THE COUNTER LXI H,BUFLOC ;POINT TO THE BUFFER STRT1 EQU $+OFFSET MOV A,M ;GET THE CONTENTS CPI 0 ;IS THERE A 0 THERE? JZ STRT2 ;YES, BUFFER IS EMPTY LDA COUNT ;NO? THEN HOW MANY CHAR IN IT? INR A ;LETS LOOK AT THEM AND COUNT STA COUNT ;THE CHARACTERS CPI 6 ;BETTER NOT BE MORE THAN 6 JZ ERRXIT ;OOPS, GOT A PROBLEM INX H ;POINT TO NEXT POSITION JMP STRT1 ;MORE CHARS TO CHECK STRT2 EQU $+OFFSET MOV M,C ;PUT OUTBOUND CHAR INTO BUFFER RET ;************************************** ; ;DONE... THIS IS WERE WE END UP WHEN WE WANT TO DUMP THE BUFFER TO ; THE REMOTE..... ; DONE EQU $+OFFSET MVI B,0 ;SET COUNT TO 0 LXI H,BUFLOC ;POINT TO THE BUFFER DONE1 EQU $+OFFSET MOV A,M ;GET THE CHAR CPI 0 ;IS IT A 0? JZ DONE2 ;RETURN IF 0 MOV C,M ;NOT A 0 SO GET THE CHAR CALL REMOUT ;GO OUTPUT IT MVI A,0 MOV M,A ;KILL THE BUFFER CHAR INX H ;POINT TO NEXT CHAR JMP DONE1 DONE2 EQU $+OFFSET LXI H,POSMTCH ;POINT TO POSMTCH FLAG MOV M,A ;PUT A ZERO THERE LXI H,MTSTR ;POINT TO MATCH STR MVI B,5 ;SET COUNT DONE3 EQU $+OFFSET MOV M,A ;ZERO THE MTSTR ALSO DCR B CMP B ;IS B A 0 YET? JZ DONE4 ;ALL DONE INX H ;POINT TO NEXT MVI A,0 ;GET A 0 JMP DONE3 ; DONE4 EQU $+OFFSET RET ; CLCF EQU $+OFFSET DB 0 POSMTCH EQU $+OFFSET DB 0 OSPTR EQU $+OFFSET DB 0,0 INSPTR EQU $+OFFSET DB 0,0 MTSTR EQU $+OFFSET DB 0,0,0,0,0,0 COUNT EQU $+OFFSET DB 0 COUNT1 EQU $+OFFSET DB 0 BUFLOC EQU $+OFFSET ;LOCATION OF OUTBOUND BUFFERED STRING DB 0,0,0,0,0,0,0 BUFPTR EQU $+OFFSET DB 0,0 ;========================================================== ;END OF SCREEN COMMAND STRING FILTER SECTION. ;==========================================================