; ; ******** SOLOS OPERATING SYSTEM ******** ; For McVideo Module ; Modified: Dec, 1982 ; ; Routine Locations: ; ; PSEUDO PORTS: 0 = KEYBOARD/VIDEO ; 1 = SERIAL PORT ; 2 = PARALLEL PORT ; ; AUTO-STARTUP CODE ; START: DB 0 INIT: JMP STRTA ;SYSTEM RESTART ENTRY POINT RETRN: JMP COMND DB 0C3H ;Required for PTDOS 1.5 ; ; OUTPUT DEVICE TABLE ; OTAB: DW VDMOT ;VDM DRIVER DW SDROT ;SERIAL OUTPUT DW PROUT ;PARALLAL OUTPUT DW RETRN ;CUSTOM DELETED ; ; INPUT DEVICE TABLE ; ITAB: DW KSTAT ;KEYBOARD INPUT ; IF PORTIN DW SSTAT ;SERIAL INPUT DW PASTAT ;PARALLEL INPUT ENDF ; IF CURADR DW RETRN DW RETRN ENDF ; DW RETRN ;CUSTOM DELETED DB 0 ;FILLER ; SOUT: LDA OPORT ;SOUT ENTRY POINT AOUT: JMP OUTPR ;AOUT ENTRY POINT SINP: LDA IPORT ;SINP ENTRY POINT AINP: PUSH H ;THIS IS ACTUALLY AINP LXI H,ITAB ; IOPRC: ANI 3 ;KEEP REGISTER "A" TO FOUR VALUES RLC . ;COMPUTE ENTRY ADDRESS ADD L MOV L,A ;WE HAVE ADDRESS JMP DISPT ;DISPATCH TO IT ; ; KEYBOARD INPUT DRIVER ; KSTAT: IN STAPT ;GET STATUS WORD CMA . ;INVERT IT FOR PROPER RETURN ANI KDR ;TEST KEYBOARD BIT RZ . ;ZERO IS NO CHARACTER RECEIVED IN KDATA ;GET CHARACTER DW 0 ;SPACE FOR ANI 7FH JMP PRINT ;GO CHECK FOR THE CONTROL-P ; ; JMP TABLE OUTPUT ROUTINES ; OUTPR: PUSH H LXI H,OTAB ;POINT TO OUTPUT TABLE JMP IOPRC ;AND DISPATCH TO OUTPUT ROUTINE ; IF PORTIN ; ; SERIAL INPUT DRIVER ; SSTAT: IN SERST ;GET SERIAL STATUS WORD ANI SDR ;TEST FOR SERIAL DATA READY RZ . ;FLAGS ARE SET IN SDATA ;GET DATA BYTE RET . ;WE HAVE IT ; ENDF ; ; SERIAL DATA OUTPUT ; SDROT: IN SERST ;GET PORT STATUS RAL . ;PUT HIGH BIT IN CARRY JNC SDROT ;LOOP UNTIL TBE JMP SDRO2 ;Continue later DB 0 ;This keeps VDMOT at XX54H ; ; VIDEO DISPLAY ROUTINES ; VDMOT: PUSH H ;SAVE MOST REGISTERS PUSH D PUSH B ; CHPCK: LDA FLGBYT ;GET FLAG BYTE MOV C,A LDA PRTOG ;PRINT TOGGLE ON? RRC . JNC CHPC0 MOV A,C ANI SPRFLG ;WHICH PRINTER? PUSH PSW ; IF EPSON CZ PROUT ;OUT PARALLEL PORT POP PSW CNZ SDROT ;OUT SERIAL PORT ENDF ; IF TI810 CZ SDROT POP PSW CNZ PROUT ENDF ; CHPC0: MOV A,B ANI 7FH MOV B,A JZ GOBK ; CHPC4: LXI H,TBL ;POINT TO SPECIAL CHARACTER TABLE CALL TSRCH ;GO PROCESS ; GOBACK: CALL VDADD ;GET SCREEN ADDRESS MOV A,M ORI 80H MOV M,A ;CURSOR IS BACK ON ; 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 ; VDEL0: CALL KSTAT ;CHARACTER WAITING? JZ GOBK ;NOPE ; VDEL1: CPI ESC ;RETURN TO SOLOS ON ESCAPE JZ COMND ; VDEL2: EQU $ VDEL3: CPI '0' ;GO BACK IF NOT 0-9 JC GOBK CPI '9'+1 JNC GOBK ANI 0FH ;KEEP LOWER NIBBLE JZ SESPD MOV C,A MVI A,1 ;SET BIT SPDLP: DCR C JZ SESPD RLC . ;MOVE IT OVER JC STSLO ;9 IS SLOWEST JMP SPDLP STSLO: MVI A,-1 SESPD: STA SPEED ;SET NEW SPEED GOBK: POP B POP D ;RESTORE REGISTERS POP H RET . ;EXIT FROM VDMOT ; NEXT: INX H INX H ; TSRCH: MOV A,M ;GET CHR FROM TABLE ORA A JZ OCHAR ;ZERO IS THE LAST CMP B ;TEST THE CHR INX H ;POINT FORWARD JNZ NEXT PUSH H ;FOUND ONE...SAVE ADDRESS CALL CREM ;REMOVE CURSOR XTHL . ;GET DISPATCH ADDRESS TO HL JMP DISPT ;DISPATCH NOW ; ; THIS ROUTINE READS A COMMAND LINE FROM KEYBOARD ; GCLIN: CALL SINP ;READ INPUT DEVICE JZ GCLIN ANI 7FH ;CLEAR PARITY BIT CPI ESC JZ COMN1 ;ABORT LINE MOV B,A CPI CR ;CARRIAGE RETURN JZ CLINE ;YES--DONE WITH LINE CPI LF ;LINE FEED RZ . ;YES--DONE WITH LINE, LEAVE AS IS CONT: CALL SOUT JMP GCLIN ; ; ROUTINE TO CALCULATE SCREEN ADDRESS ; VDADD: LDA NCHAR ;GET CHARACTER POSITION MOV C,A ;'C' KEEPS IT VDAD2: LDA LINE ;LINE POSITION VDAD: MOV L,A ;INTO 'L' LDA BOT ;GET TEXT OFFSET ADD L ;ADD IT TO THE LINE POSITIIN VDAD0: CPI NLINES JC VDAD1 SUI NLINES JMP VDAD0 VDAD1: PUSH D LXI H,VDMEM-LLGTH LXI D,LLGTH VDAD3: DAD D DCR A JP VDAD3 MOV E,C DAD D POP D RET . ; ; ROUTINE TO BACKSPACE ; PBACK: CALL PLEFT CALL VDADD ;GET SCREEN ADDRESS MVI M,' ' ;PUT A BLANK THERE RET . ; ; ROUTINE TO REMOVE CURSOR ; CREM: CALL VDADD ;GET CURRENT SCREEN ADDRESS MOV A,M ANI 7FH ;STRIP OFF THE CURSOR MOV M,A RET ; ; PUT CHARACTER TO SCREEN ; OCHAR: EQU $ ;ACTUALLY PUT CHAR TO SCREEN NOW CALL VDADD ;GET SCREEN ADDRESS MOV M,B ;PUT CHR ON SCREEN LDA NCHAR ;GET CHARACTER POSITION CPI LLGTH-1 ;END OF LINE? JC OK LDA LINE CPI NLINES-1 ;END OF SCREEN? JNZ OK ; ; END OF SCREEN...ROLL UP ONE LINE ; SCROLL: XRA A STA NCHAR ;BACK TO FIRST CHAR POSITION SROL: MOV C,A CALL VDAD ;CALCULATE LINE TO BE BLANKED LDA BOT ;DO THE HARDWARE SCROLL INR A CPI NLINES JNZ SROLX XRA A SROLX: CALL ERAS3 XRA A ;CLEAR THE LINE JMP CLIN1 ; ; INCREMENT LINE COUNTER IF NECESSARY ; OK: LDA NCHAR ;GET CHR POSITION INR A CPI LLGTH STA NCHAR RNZ . ;DIDN'T HIT END OF LINE, OK XRA A STA NCHAR ; PDOWN: EQU $ ;CURSOR DOWN ONE LINE HERE LDA LINE ;GET THE LINE COUNT INR A CURSC: CPI NLINES JNZ CUR XRA A CUR: STA LINE ;STORE THE NEW COUNT RET ; ; ERASE SCREEN ; PERSE: LXI H,VDMEM ;POINT TO SCREEN MVI M,0A0H ;THIS IS THE CURSOR ; INX H ;BUMP 1ST ERAS1: EQU $ ;LOOPS HERE TO ERASE SCREEN MVI M,' ' ;BLANK IT OUT INX H ;NEXT MOV A,H ;SEE IF END OF SCREEN YET ; IF S64 CPI VDMEM+1024 ENDF ; IF S80 CPI >VDMEM+1920 ENDF ; JNZ ERAS1 STC . ;CARRY WILL SAY COMPLETE ERASE ; PHOME: MVI A,0 ;RESET CURSOR--CARRY=ERASE, ELSE HOME STA LINE ;ZERO LINE STA NCHAR ;LEFT SIDE OF SCREEN RNC . ;IF NO CARRY, WE ARE DONE WITH HOME ; ERAS3: OUT DSTAT ;RESET SCROLL PARAMETERS STA BOT ;BEGINNING OF TEXT OFFSET RET ; CLINE: CALL VDADD ;GET CURRENT SCREEN ADDRESS LDA NCHAR ;CURRENT CURSOR POSITION CLIN1: CPI LLGTH RNC . ;ALL DONE MVI M,' ' ;ALL SPACED OUT INX H INR A JMP CLIN1 ;LOOP TO END OF LINE ; ; ROUTINE TO MOVE THE CURSOR UP ONE LINE ; PUP: LDA LINE ;GET LINE COUNT DCR A JP CURSC MVI A,NLINES-1 JMP CURSC ;MERGE TO HANDLE CURSOR ; ; MOVE CURSOR LEFT ONE POSITION ; PLEFT: LDA NCHAR DCR A JP PCUR MVI A,LLGTH-1 PCUR: EQU $ ;CURSOR ON SAME LINE CPI LLGTH JNZ PCUR1 XRA A PCUR1: STA NCHAR ;UPDATED CURSOR RET . ; ; CURSOR RIGHT ONE POSITION ; PRIT: LDA NCHAR INR A JMP PCUR ; ; ROUTINE TO PROCESS A CARRIAGE RETURN ; PCR: EQU $ CALL CLINE ;CLEAR THE LINE XRA A JMP PCUR ;STORE NEW LINE VALUE ; ; ROUTINE TO PROCESS A LINEFEED ; PLF: LDA FLGBYT ;GET FLAG BYTE MOV C,A ;SAVE IT ANI SPCFLG ;SEE IF SPACE BAR HALT OK JNZ PLF2 ;IF NOT, BYPASS IN KDATA ;LOOK AT KEYBOARD PORT CPI ' ' ;SPACE BAR TYPED? JNZ PLF2 ;NZ SAYS NO PLF1: CALL KSTAT ;WAIT FOR ANOTHER KEY JZ PLF1 LXI H,PLF2 ;SET UP FOR SPEED ROUTINE PUSH H ;THIS WILL GET POPPED BY VDMOT PUSH H PUSH D PUSH B JMP VDEL1 ;GO CHECK FOR SPEED & ESC PLF2: LDA LINE ;GET LINE COUNT INR A CPI NLINES JNZ PLF3 ;NO--NO NEED TO SCROLL XRA A JMP SROL ;YES--THEN SCROLL PLF3: STA LINE JMP PCR ; IF CURADR ; ESCS: CALL CREM ;Remove cursor CALL ESCPR ;Process ESC sequence JMP GOBACK ;Exit ; ESCPR: MOV A,B ;Get next char CPI '=' ;Is it 2nd part? MVI A,'='+80H ;Set flag if so JZ PESC ;Store it LDA FLGESC ;Get ESC flag PUSH PSW ;Save it ANI 7FH ;Strip flag bit CPI '=' ;See if 2nd was sent JZ SETXY ;OK, do X & Y POP PSW ;Opps! A bummer XRA A CALL PESC ;Zero ESC flag JMP CHPCK ;Send char to screen ; SETXY: POP PSW ;Get back flag bit ANI 80H ;See if set JZ SETY ;If not do X X: MOV A,B CALL CURSC MVI A,'=' ;Reset flag bit ; PESC: STA FLGESC RET . ; SETY: STA FLGESC MOV A,B JMP PCUR ; ENDF ; ; Continuation of Serial Data Output ; SDRO2: ANI 40H ;Check CTS bit (after RAL) JZ SDROT ;If missing, go back MOV A,B ;Move in char CPI 7FH ;Deletes get an underline JNZ SDRO3 MVI A,BACKS SDRO3: OUT SDATA ;Send it out RET ; ; ***** START UP SYSTEM ***** ; STRTA XRA A MVI C,16 ;Clear only what's necessary LXI H,SYSRAM ;Point to start of RAM ; CLERA: MOV M,A INX H DCR C JNZ CLERA ; LXI SP,SYSTP ;SET UP THE STACK FOR CALL CALL PERSE COMN1: XRA A STA OPORT STA IPORT ; ; ***** COMMAND MODE ***** ; ; THIS ROUTINE GETS AND PROCESSES COMMANDS ; COMND: LXI SP,SYSTP ;SET STACK POINTER LDA OPORT ;GET PORT PUSH PSW LDA FLGBYT ;GET FLAG BYTE PUSH PSW XRA A STA OPORT ;FORCE SCREEN OPERATIONS INR A STA FLGBYT ;NO SPC/BAR HALT YET CALL PROMPT ;PUT PROMPT ON SCREEN POP PSW STA FLGBYT ;SPC/BAR OK NOW CALL GCLIN ;GET COMMAND LINE POP PSW STA OPORT ;RESTORE DEFAULT PORT CALL COPRC ;PROCESS THE LINE JMP COMND ;OVER AND OVER ; ; FIND AND PROCESS COMMAND ; COPRC: CALL CREM ;REMOVE THE CURSOR MVI C,1 ;SET FOR CHARACTER POSITION CALL VDAD2 ;GET SCREEN ADDRESS XCHG LXI H,START ;MAKE SURE HL PT TO SOLOS START PUSH H ;SAVE IT FOR LATER DISPT CALL SCHR ;SCAN PAST BLANKS JZ ERR1 ;NO COMMAND? XCHG . ;HL HAS FIRST CHR ; LXI D,COMTAB ;POINT TO COMMAND TABLE CALL FDCOM ;SEE IF IN PRIMARY COMMAND TABLE ; DISPO: EQU $ ;HERE TO SEE IF ERROR OR DISP JZ ERR2 ;NOT VALID, ERROR INX D ;BUMP TO PTR OF RTN XCHG . ;HL PT TO RTN ADDR ; ; THIS IS THE DISPATCH ROUTINE ; DISPT: EQU $ ;OFF TO A ROUTINE MOV A,M ;LO ADDR INX H MOV H,M ;HI ADDR MOV L,A ;HL NOW CGMPLETE DISP1: EQU $ ;HERE TO GO OFF TO HL XTHL . ;XCHG HL W/HL ON STACK MOV A,L ;ALSO COPY HERE FOR SETS RET . ;AND GO OFF TO THE RTN ; ; THIS ROUTINE SEARCHES THROUGH A TABLE, POINTED TO ; BY 'DE', FOR A DOUBLE CHARACTER MATCH OF THE 'HL' ; MEMORY CONTENT. IF NO MATCH IS FOUND THE SCAN ENDS ; WITH HL POINTING TO ORIGINAL VALUE AND ZERO FLAG SET. ; FDCOM: LDAX D ORA A ;TEST FOR TABLE END RZ . ;NOT FOUND. COMMAND ERROR PUSH H CMP M INX D JNZ NCOM ;NOT FOUND INX H LDAX D CMP M JNZ NCOM POP H ;RESTORE ORIGINAL SCAN ADDR ORA A ;SET NON-ZERO FLAG SAYING FOUND RET . ;WITH NON-ZERO SET ; NCOM: INX D ;GO TO NEXT ENTRY INX D INX D POP H ;GET BACK ORIGINAL ADDRESS JMP FDCOM ;CONTINUE SEARCH ; ; ***** COMMAND TABLE ***** ; ; THIS TABLE DESCRIBES THE VALID COMMANDS FOR SOLOS ; COMTAB EQU $ ASC 'DU' ;DUMP DW DUMP ASC 'EN' ;ENTER DW ENTER ASC 'EX' ;EXECUTE DW EXEC ASC 'SE' ;SET COMMAND DW CSET ASC 'CM' ;COMPARE MEMORY DW COMPM ; IF HELIOS ASC 'BO' ;PTDOS BOOT DW DOS ENDF ; IF TERM ASC 'TE' DW TERMC ENDF ; ASC 'NS' ;NORTHSTAR BOOT DW 0E800H ASC 'ED' ;EDIT DW EXDEP ASC 'MM' ;MOVE MEMORY DW MOVE ASC 'ZI' ;ZIP OR FILL MEMORY DW ZIP ASC 'SM' ;SEARCH MEMORY DW SERCH ASC 'HM' ;HEX MATH DW HMATH ; IF MEMTST ASC 'TM' ;TEST MEMORY DW MEMT ENDF ; DB 0 ;END OF TABLE MARK ; ; DISPLAY DRIVER COMMAND TABLE ; TBL: DB CLEAR-80H ;CLEAR SCREEN DW PERSE DB UP-80H ;UP CURSOR DW PUP DB DOWN-80H ;DOWN CURSOR DW PDOWN DB LEFT-80H ;LEFT CURSOR DW PLEFT DB RIGHT-80H ;RIGHT CURSOR DW PRIT DB HOME-80H ;HOME CURSOR DW PHOME DB CEOL ;CLEAR TO EOL DW CLINE DB CR ;CARRIAGE RETURN DW PCR DB LF ;LINE FEED DW PLF DB BACKS ;BACKSPACE DW PBACK DB 7FH ;DELETE DW PBACK DB 7 DW BELL ; IF CURADR DB ESC ;ESCAPE DW PESC ENDF ; DB 0 ;END OF TABLE ; ; SECONDARY COMMAND TABLE FOR SET COMMAND ; SETAB: EQU $ ; IF PORTIN ASC 'I=' ;SET INPUT PORT DW SETIN ENDF ; ASC 'O=' ;SET OUTPUT PORT DW SETOT ASC 'M=' ;SET MODE BYTE DW SETMD ASC 'C=' ;SET MOVE COUNT DW SETMOV DB 0 ;END OF TABLE MARK ; DHLOP LDAX D CMP M RNZ DCR B RZ INX H INX D JMP DHLOP ; BELL: MOV A,B OUT KDATA RET . ;