          IDENT     VIKKEY,0#D000
          MACHINE   Z80
          TITLE     KEY UTILITY CONTROLWARE.
          LIST      -R
          SPACE  3
**        Resident RAM addresses and equates.


 ALARM    EQU    #0033       RING THE BELL
 ATRIB    EQU    #E0A9       ATTRIBUTE
 BLDADD   EQU    #003F       RESIDENT ADDRESS ROUTINE
 BDISPN   EQU    #0039       DISPLAY B
 RBDSPN   EQU    #B384       DISPLAY B IN RAM PACK
 CNTRL    EQU    #E0B5       RESIDENT CONTROL FLAG
 DLMENA   EQU    #E0B9       DELIMITER ENABLED
 DSTRNG   EQU    #0063       DELIMITER ENABLED
 FLAG2    EQU    #E0BF       SCROLL DIRECTION FLAG
 KEYT     EQU    #D7E0       KEY TABLE
 LASTLN   EQU    #E0CD       LINES ON SCREEN
 LNCNT    EQU    #E0D1       LINE ON SCREEN
 MNTOR    EQU    #00A5       RESIDENT MONITOR ROUTINE
 RMNTR    EQU    #BAD8       RESIDENT MONITOR ROUTINE IN RAM PACK
 OBYTE2   EQU    #E047       TERMINAL PARAMS
 POPR     EQU    #D8D6       FLAG IN KEYT FOR PUSH ROUTINE
 RMID     EQU    #AF00       TEST WORD FOR RAM PACK IN USE
 SCROLL   EQU    #0081       RESIDENT SCROLL ROUTINE
 SHIFT    EQU    #E0E6       RESIDENT SHIFT FLAG
 SENDB    EQU    #0087       SEND CONTENTS OF B TO HOST
 RSNDB    EQU    #BCC8       SEND CONTENTS OF B TO HOST IN RAM PAK
          SPACE  3
**        Controlware Equates.


 LOHS     EQU    #61         LINES ON HIDDEN SCREENS (100)
 BIKT     EQU    #F3         BYTES IN KEY TABLE
 BTPL     EQU    132*2       BYTES PER LINE
 SCRT     EQU    #4000       MEMORY DISPLAY TABLE
 MEMS     EQU    #40F2       MEMORY SCREEN
          SPACE  3
          LIST   -L
          PURGMAC SET
 SET      MACRO              SET INSTRUCTION SET  2,(HL)
          DATA   #CB,#D6
          ENDM
          LIST   L
          TITLE  PUSH AND POP KEY DEFINITIONS.
          ORG    #D000

**        PKD - PUSH KEY DEFINITIONS.


 PKD      LD     DE,SAVA     DE ==> KEY TABLE SAVE BUFFER
          LD     BC,BIKT     BC = BYTES TO MOVE
          LD     HL,KEYT     HL ==> KEY TABLE
          LDIR               COPY TABLE
          LD     A,(OBYTE2)  SAVE OBYTE2
          LD     (OBS),A
          LD     A,(DLMENA)  SAVE DELIMITER FLAG
          LD     (DLS),A
 SUT      SPACE  3
**        SUT - SET UP TERMINAL


 SUT      XOR    A           CLEAR DELIMITER ENABLED
          LD     (DLMENA),A
          LD     BC,BIKT-1   CLEAR KEY TABLE
          LD     HL,KEYT     HL ==> BEGINNING OF KEY TABLE
          LD     DE,KEYT+1   DE ==> NEXT ADDRESS
          LD     (HL),#30    UNDEFINED
          LDIR
          RET                RETURN
 PKS      SPACE  3
**        PKS - POP KEY DEFINITIONS.


 PKS      LD     HL,SAVA     HL ==> KEY SAVE AREA
          LD     BC,BIKT     BC = BYTES TO MOVE
          LD     DE,KEYT     DE ==> KEY TABLE ADDRESS
          LDIR
          LD     A,(OBS)     RESTORE OBYTE2
          LD     (OBYTE2),A
          LD     A,(DLS)     RESTORE DELIMITER
          LD     (DLMENA),A
          RET
          SPACE  4
**        SAVE AREA FOR PUSH AND POP ROUTINES.


 SAVA     BSS    BIKT        SAVE AREA FOR KEY TABLE
 OBS      BSS    1           SAVE AREA FOR OBYTE
 DLS      BSS    1           SAVE AREA FOR DELIMITER FLAG
 DFLS     BSS    2           SAVE AREA FOR LENGTH OF KEY DEFS
          TITLE  MARK KEY ROUTINES
          ORG    #D138

**        MUL - MARK OR UNMARK LINE.


 MUL      CALL   UML         CLEAR CURRENTLY INVERSE
          LD     A,(CNTRL)   TEST IF CONTROL IS ACTIVE
          AND    A
          JR     NZ,MAL      IF SO

          LD     A,(SHIFT)   TEST FOR SHIFT ACTIVE
          AND    A
          JR     Z,MCL       IF NOT

 CLN      LD     A,#FF       CLEAR LINE NUMBER
          LD     (LNN),A
          RET
 UML      SPACE  3
**        UML - UNMARK LINE


 UML      CALL   TST         TEST LINE NUMBER
          RET    M           IF NONE SET
          CALL   BAS         BUILD ADDRESS TO SCREEN
          DEC    A
          LD     (LNN),A     SAVE NEXT LINE TO LOOK AT
 UML1     INC    HL
          RES    2,(HL)      CLEAR INVERSE FROM CHARACTER
          INC    HL
          DEC    D           DEC COUNTER
          JR     NZ,UML1     UNTIL DONE WITH LINE
          RET
 MCL      SPACE  3
**        MCL - MARK A COMMAND LINE


 MCL      CALL   TST         TEST IF ANY LINE WAS MARKED
          JP     P,MCL1      IF SO

          LD     A,#1D       SET TO BOTTOM OF SCREEN
 MCL1     LD     B,A         PLACE LINE # IN B
 MCL2     CALL   BAS
          XOR    A           A IS A FLAG FOR MODIFIED FOUND
 MCL3     INC    HL          HL ==> ATTRIBUTE BYTE
          BIT    5,(HL)
          JR     Z,MCL4      IF NOT MODIFIED

          SET    2,(HL)      SET INVERSE BIT
          INC    A           SET MODIFIED FOUND
 MCL4     INC    HL          ADVANCE TO NEXT CHARACTER
          DEC    D           DEC BYTE COUNT
          JR     NZ,MCL3     IF NOT DONE WITH LINE

          AND    A
          JR     NZ,MCL5     IF FOUND THEN DONE

          DEC    B           GET SCREEN LINE NUMBER
          LD     A,B
          JP     P,MCL2      IF STILL GOOD

 MCL5     LD     A,B         GET LINE ACTED UPON
          LD     (LNN),A     SAVE LINE NUMBER
          RET
 MAL      SPACE  3
**        MAL - MARK ANY LINE.


 MAL      CALL   TST         TEST IF ANY LINE WAS MARKED
          JP     P,MAL1      IF SO

          LD     A,#1D       ELSE SET TO BOTTOM OF SCREEN
 MAL1     LD     B,A         SAVE LINE TO CHECK
          LD     (LNN),A
          RET    M           IF OFF TOP OF SCREEN

          CALL   BAS         GET ADDRESS TO SCREEN
          CALL   BSA         GO TO END OF LINE
 MAL2     DEC    HL          BACK UP TO CHARACTER
          CP     (HL)        TEST FOR BLANK
          JR     NZ,MAL3     IF SO MARK THE REST OF THE LINE

          DEC    HL
          DEC    D
          JR     NZ,MAL2     UNTIL DONE CHECKING LINE

          LD     A,B
          DEC    A           GO UP ONE LINE
          JR     MAL1        AND TRY IT

 MAL3     INC    HL          ADVANCE TO ATTRIBUTE
 MAL3.1   SET    2,(HL)      SET INVERSE BIT
          DEC    HL          BACK UP TO PREVIOUS ATTRIBUTE
          DEC    HL
          DEC    D           DEC BYTE COUNT
          JR     NZ,MAL3.1   IF NOT DONE WITH LINE
          RET
          TITLE  COPY KEY ROUTINES
**        CMC - COPY MARKED LINE
*
*         INVERSE VIDEO ON MARKED LINE IS FLAG

 CML      LD     A,(SHIFT)   TEST FOR SHIFT ACTIVE
          AND    A
          JR     NZ,CEL      IF SO COPY REST OF MARKED LINE

          LD     A,(CNTRL)   TEST IF CONTROL IS ACTIVE
          AND    A
          JR     NZ,SMC      IF SO SKIP A CHAR ON MARKED LINE

 CMC      CALL   TST         GET LINE NUMBER
          RET    M           IF NONE MARKED

          CALL   BAS         GET ADDRESS TO SCREEN
 CMC1     INC    HL          GET ATTRIBUTE
          BIT    2,(HL)      TEST FOR INVERSE
          JR     NZ,CMC2     IF SET

          INC    HL          MOVE TO NEXT CHARACTER
          DEC    D           DEC COUNTER
          JR     NZ,CMC1     UNTIL DONE WITH LINE
          JP     CLN         CLEAR LINE FLAG IF LAST COPIED

 CMC2     RES    2,(HL)      CLEAR INVERSE
          DEC    HL          BACK UP TO CHARACTER
          LD     B,(HL)      GET THE CHAR TO MOVE INTO B
          PUSH   DE
          LD     A,(ATRIB)   GET CURRENT ATTRIBUTE
          PUSH   AF
          OR     #20         SET MODIFIED
          LD     (ATRIB),A
          PUSH   BC
          CALL   BDISPN      DISPLAY THE CHARACTER
 ALTBD1   EQU    *-2
          POP    BC
          POP    AF
          LD     (ATRIB),A   RESTORE ATTRIBUTE
          CALL   SENDB       SEND THE CHAR TO THE HOST
 ALTSB1   EQU    *-2
          POP    DE
          DEC    D
          JP     Z,CLN       IF END OF LINE
          RET
 CEL      SPACE  3,8
**        CEL - COPY ENTIRE MARKED LINE


 CEL      CALL   CMC         COPY A LETTER
          CALL   TST
          JP     P,CEL       UNTIL NOTHING MARKED ON LINE
          RET
 SMC      SPACE  3
**        SMC - SKIP A MARKED CHARACTER.


 SMC      CALL   TST         GET LINE NUMBER
          RET    M           IF NONE

          CALL   BAS         GET SCREEN ADDRESS
 SMC1     INC    HL          GET ATTRIBUTE
          BIT    2,(HL)      TEST FOR INVERSE
          JR     Z,SMC2      IF NOT SET

          RES    2,(HL)      CLEAR INVERSE
          RET

 SMC2     INC    HL
          DEC    D           DEC COUNTER
          JP     Z,CLN       UNTIL DONE WITH LINE
          JR     SMC1
          TITLE  SUPPORT ROUTINES
**        NXT - ROUTINE FOR THE CARRIAGE RETURN.


 NXT      CALL   UML         CLEAR THE CURRENTLY MARKED LINE IF ANY
          LD     B,#0D
          CALL   SENDB       SEND A CARRIAGE RETURN
 ALTSB2   EQU    *-2
          CALL   BDISPN      DISPLAY A CARRIAGE RETURN
 ALTBD2   EQU    *-2
          RET
 BAS      SPACE  3
**        BAS - BUILD ADDRESS.
*
*         HL <=== ADDRESS TO FIRST CHAR ON SCREEN
*         D  <=== COUNTER FOR CHARS PER LINE


 BAS      LD     L,A         SETUP HL FOR CALL
          LD     H,#E0       HL ==> LINE OF INTEREST IN TABLE
          CALL   BLDADD      DE POINTS TO SCREEN ADDRESS
          EX     DE,HL       HL ==> SCREEN ADDRESS
          LD     D,#84       D IS BYTE COUNTER FOR LINE
          RET
 BSA      SPACE  3
**        BSA - BUILD SPECIAL ADDRESS.


 BSA      PUSH   DE          SAVE BYTE COUNTER
          LD     DE,263
          ADC    HL,DE       HL ==> ONE BYTE BEYOND END OF LINE
          POP    DE          RESTORE BYTE COUNTER
          LD     A,#20       A GETS A BLANK
          RET
 TST      SPACE  3
**        TST - TEST LINE NUMBER
*
*         SETS STATUS FLAGS

 TST      LD     A,(LNN)     GET LINE NUMBER
          AND    A           SET FLAGS
          RET
          SPACE  3
**        SAVE AREA FOR MARK AND COPY ROUTINES.


 LNN      CON    #FF         LINE NUMBER

          ERRNG  #D235-*
          TITLE  SCREEN MONITOR ROUTINE
          ORG    #D235

**        PRE - PRESET HIDDEN SCREEN.
*

 PHS      LD     A,#1C       SELECT HIDDEN BANKS
          CALL   CFR         CHECK FOR RAM PACK
          LD     A,LOHS+1    LINES PER TABLE
          LD     DE,SCRT     DE = ADDRESS OF SCREEN TABLE
          LD     HL,MEMS     HL = ADRRES OF MEMORY SCREEN
          LD     BC,BTPL     BC = TABLE INCREMENT PER LINE
 PHS1     EX     DE,HL
          LD     (HL),E      MOVE LOWER ADDRESS BYTE
          INC    HL
          LD     (HL),D      MOVE UPPER ADDRESS BYTE
          INC    HL
          EX     DE,HL
          ADC    HL,BC       ADD NEXT ADDRESS
          DEC    A
          JR     NZ,PHS1

          LD     DE,MEMS+1   DE ==> SECOND MEMORY POSITION
          LD     HL,MEMS     HL ==> FIST MEMORY POSITION
          LD     BC,BTPL*LOHS  BC = BYTES TO MOVE
          LD     (HL),#20    WITH BLANK,MODIFIED
          LDIR               CLEAR MEMORY SCREEN

 SCR      LD     HL,#E000    GET ADDRESS OF TOP VISIBLE LINE
          CALL   BLDADD
          LD     HL,PTLA     HL = PREVIOUS TOP LINE ADDRESS
          LD     A,E
          CP     (HL)
          JR     Z,SCR1      IF NOT CHANGED

          EX     DE,HL       SAVE NEW TOP ADDRESS
          LD     (PTLA),HL
          CALL   SBM         SAVE OLD TOP LINE
          LD     HL,(PTLA)   HL ==> NEW TOP LINE OF SCREEN
          LD     DE,BUFFER   DE ==> BUFFER
          LD     BC,BTPL     BE = BYTES TO MOVE
          LDIR               SAVE IT IN BUFFER
 SCR1     CALL   MNTOR       RESIDENT MONITOR
 ALTMT    EQU    *-2
          LD     A,(POPR)    GET POP ROUTINE INDICATOR
          AND    A           SET BITS
          JR     NZ,SCR      RETEST TOP LINE
          JP     ALARM       IF ZERO RETURN
 SBM      SPACE  3
**        SBM - SCROLL BACKUP MEMORY
*

 SBM      LD     A,(NXTMLN)  NUMBER OF LINES USED
          CP     LOHS        NUMBER OF HIDDEN LINES
          JR     Z,SBM1      IF LAST LINE

          CALL   GVL         GET LINE TO BE SCRLL OFF VIS
          LD     A,(NXTMLN)
          INC    A           INCREMENT WHERE NEXT HIDDEN
          LD     (NXTMLN),A
          RET

 SBM1     LD     HL,SCRT
          LD     D,H
          LD     E,L         DE ==> FIRST TABLE ENTRY
          LD     C,(HL)
          INC    HL
          LD     B,(HL)
          PUSH   BC          SAVE CONTENTS OF FIRST TABLE ENTRY
          INC    HL          HL ==> SECOND TABLE ENTRY
          LD     BC,LOHS*2   BE = NUMBER OF ENTRIES TO MOVE
          LDIR
          POP    HL
          LD     A,L
          LD     (DE),A
          INC    DE
          LD     A,H
          LD     (DE),A
          EX     DE,HL
          JR     GVL1        MOVE LINE
 GVL      SPACE  3
**        GVL - GET VISIBLE LINE ABOUT TO BE SCROLLED OFF


 GVL      RLCA               DOUBLE FOR TWO BYTE ADDRESSES
          LD     L,A
          LD     H,#40       DE ==> ADDRESS IN HIDDEN SCREEN
          LD     E,(HL)
          INC    HL
          LD     D,(HL)
 GVL1     LD     HL,BUFFER   HL ==> BUFFER
          LD     BC,BTPL     BYTES TO MOVE
          LDIR
          RET
          TITLE  SCROLL SCREEN FORWARD
**        FWD - SCROLL FORWARDS.
*
*         WHEN ACTIVATED BY A KEY THIS ROUTINE WILL SCROLL FORWARDS.


 FWD      LD     A,(NXTMLN)  GET LAST LINE FILLED IN HIDDEN
          CP     LOHS
          RET    Z

          INC    A
          RLCA               DOUBLE FOR TWO BYTE ADDRESSES
          LD     L,A
          LD     H,#40       (HL) = ADDRESS IN HIDDEN SCREEN TABLE
          LD     E,(HL)
          INC    HL
          LD     D,(HL)
          PUSH   DE          SAVE ADDRESS
          LD     HL,#E000    GET TOP LINE OFF SCREEN
          CALL   BLDADD
          EX     DE,HL       HL ==> TOP LINE
          LD     DE,BUFFER   DE ==> BUFFER
          LD     BC,BTPL     BYTES TO MOVE
          LDIR
          CALL   SCROLL      SCROLL VISIBLE
          LD     HL,#E01D    PUT BOTTOM LINE ON SCREEN
          CALL   BLDADD      DE ==> BOTTOM LINE ON SCREEN
          POP    HL          HL ==> ORIGINAL ADDRESS
          PUSH   HL          SAVE IT AGAIN
          LD     BC,BTPL     BYTES TO MOVE
          LDIR
          POP    DE          PUT BUFFER INTO HIDDEN
          CALL   GVL1
          LD     HL,#E000    GET ADDRESS OF TOP VISIBLE LINE
          CALL   BLDADD
          EX     DE,HL       SAVE NEW TOP ADDRESS
          LD     (PTLA),HL
          LD     A,(NXTMLN)  GET LAST LINE FILLED IN HIDDEN
          INC    A
          LD     (NXTMLN),A
          RET
          TITLE  SCROLL SCREEN BACKWARD
**        BKW - SCROLL BACKWARD.
*
*         WHEN ACTIVATED BY A KEY THIS ROUTINE WILL SCROLL BACKWARDS.


 BKW      LD     A,(NXTMLN)  GET LAST LINE FILLED IN HIDDEN
          AND    A
          JP     Z,ALARM     RETURN IF AT TOP

          RLCA               DOUBLE FOR TWO BYTE ADDRESSES
          LD     L,A
          LD     H,#40       (HL) = ADDRESS IN HIDDEN SCREEN TABLE
          LD     E,(HL)
          INC    HL
          LD     D,(HL)
          PUSH   DE          SAVE ADDRESS
          LD     HL,#E01D    GET BOTTOM LINE OFF SCREEN
          CALL   BLDADD
          EX     DE,HL       HL ==> BOTTOM LINE ON SCREEN
          LD     DE,BUFFER   DE ==> BUFFER
          LD     BC,BTPL     BE = BYTES TO MOVE
          LDIR               SAVE IN BUFFER
          LD     A,(FLAG2)   SAVE OLD FLAG
          PUSH   AF
          LD     A,2         SET TO SCROLL DOWN
          LD     (FLAG2),A
          CALL   SCROLL      SCROLL VISIBLE
          POP    AF          RESET TO SCROLL UP
          LD     (FLAG2),A
          LD     HL,#E000    PUT TOP LINE ON SCREEN
          CALL   BLDADD
          EX     DE,HL       SAVE NEW TOP ADDRESS
          LD     (PTLA),HL
          EX     DE,HL       DE ==> TOP LINE ON SCREEN
          POP    HL          HL ==> ORIGINAL ADDRESS
          PUSH   HL          SAVE IT AGAIN
          LD     BC,BTPL     BE = BYTES TO MOVE
          LDIR               MOVE FROM HIDDEN TO VISIBLE
          POP    DE          MOVE BUFFER TO HIDDEN
          LD     A,(NXTMLN)  RESET LAST LINE FILLED IN HIDDEN
          DEC    A
          LD     (NXTMLN),A
          JP     GVL1        RETURN
          SPACE  3
**        SAVE AREA FOR SCROLLING ROUTINES.


 PTLA     CON    #10,#E1     PREVIOUS TOP LINE ADDRESS
 NXTMLN   CON    0           NEXT MEMORY LINE TO BE USED
 BUFFER   BSS    BTPL        PLACE TO SAVE OLD TOP LINE
          ORG    BUFFER
          SPACE  4,10
**        CFR - CHECK FOR RAM PACK.
*
*         ENTRY  (A) = BANKS TO SELECT.
*
*         EXIT   BANKS SELECTED AND CALL ADDRESSES CHANGED IF RAM
*                PACK IS INSTALLED.


 CFR      OUT    (#70),A     DO BANK SELECT
          LD     A,(RMID)    GET ADDRESS OF RAM FLAG
          CP     #C3
          JR     NZ,CFR1     IF NOT THE SAME
          LD     HL,RBDSPN   GET NEW BDISPLAY ADDRESS
          LD     (ALTBD1),HL
          LD     (ALTBD2),HL
          LD     HL,RSNDB    GET NEW SENDB ADDRESS
          LD     (ALTSB1),HL
          LD     (ALTSB2),HL
          LD     HL,RMNTR    GET NEW MONITOR ADDRESS
          LD     (ALTMT),HL
          LD     HL,CFRM     OUTPUT RAM LIGHT
 CFR0     JP     DSTRNG      RETURN

 CFR1     LD     HL,CFRN     OUTPUT NO RAM LIGHT
          JR     CFR0

 CFRM     CON    #1E,#12,#65,#32,#FF
 CFRN     CON    #1E,#12,#65,#31,#FF
          END
/EOR
