home
***
CD-ROM
|
disk
|
FTP
|
other
***
search
/
Columbia Kermit
/
kermit.zip
/
archives
/
trs80model4.tar.gz
/
trs80model4.tar
/
m4term.asm
< prev
next >
Wrap
Assembly Source File
|
1986-10-22
|
13KB
|
453 lines
; m4term/asm
;
; This is the connect command
;
CONNECT EQU $
LD A,CMCFM ;Get a confirmation
CALL COMND
JP KERMT3 ;Abort if no <ENTER> pressed
CALL SCRCON ;Swap in the proper screen
LD A,(MAXCNT) ;Select the proper buffer size
LD (SVMAX),A
LD A,80 ;80 characters max are buffered
LD (MAXCNT),A
LD A,(FTIME) ;Is this the VERY FIRST connect?
IFNZ CON_2
STROUT CLRTOP ;Clear the screen
CON_1 STROUT INFMS7 ;Display the message
CALL ESCPR
STROUT INFMS8
LD A,1 ;Set the first time done flag
LD (FTIME),A
CON_2 LD A,14
CALL CONOUT
;
; While in connect mode, at most, 30 characters may be processed
; from the input port, before the keyboard is scaned. We try not
; to scan the keyboard too much, as that will kill screen I/O. This
; is especially true at higher baud rates, where the user might
; not get to type a key because the flow of characters into the
; port is continuous.
;
CHRLUP LD A,30 ;Set the maximum character count
LD (CHCNT),A ;Save it
CALL PRTCHR ;Do input characters
CALL CONCHR ;Get a keyboard character
JP KERMIT ;IF we return here, then abort
JR CHRLUP ;Loop on
;
; Look at the input buffer for a character, and return it, or
; return no input.
;
INPORT PUSH HL ;SAVE HL
LD HL,(NXTCHR) ;Get address of next input char
LD A,(CURCHR) ;Get the LSB of the queue start
IFA L,INOUT ;If A=L, then there is no input.
DI ;Interrupts off, CRITICAL section
LD A,(HL) ;Get the character back
LD (SVCHAR),A ;Save the input character
INC L ;Delete the character
LD (NXTCHR),HL ;Set the new pointer
LD HL,INCNT ;Decrement the count
DEC (HL)
EI ;Interrupts back on
LD A,(FLOFLG) ;Is XON/XOFF in effect?
IFZ INP11 ;Go if not doing flow control
PUSH BC ;Save BC
LD C,(HL) ;Get a copy of the count
LD A,(XFFLG) ;Check if XOFF sent out
IFZ INP10 ;Jump if not
LD A,(MAXCNT) ;It was, so check if time for XON
SRL A ;Use 1/2 of the max as the restart count
IFALT C,INP10 ;If A >= count it is not time yet
PUSH DE ;Save DE
LD E,XON ;Get an XON character
CALL OUTCHR ;Out the port it goes
XOR A ;Reset the XOFF sent flag
LD (XFFLG),A
POP DE ;Restore E
INP10 POP BC ;Restore C
INP11 LD A,0 ;Get the next character
SVCHAR EQU $-1
CP A ;Set Z status for normal return
INOUT1 POP HL ;Restore HL
RET ;Back to caller
;
; No input exit from INPORT
;
INOUT EQU $
XOR A ;Reset the count
LD (INCNT),A ;Zeroed
INC A ;Set NZ (We know A was zero, now it is 1)
POP HL ;Restore HL
RET ;Back to the caller
;
; Input a character, and display it based on the current value
; of EMULATION.
;
PRTCHR CALL INPORT ;Try to get an input character.
RET NZ ;Return if none there
LD E,A ;Get the input character
CALL LOGONE ;Maybe do logging
LD A,(PRTFLG) ;CHECK FOR PRINTER OUTPUT
OR A ;SET THE FLAGS
CALL NZ,PRTIT ;GO PRINT IT
LD A,E ;GET THE CHARACTER AND DISPLAY
CALL TRMOUT ;Send it to the *SO device
LD B,0 ;Get the current count
CHCNT EQU $-1
DJNZ PRTCHR5 ;SKIP RETURN IF NOT LIMIT
RET ;RETURN AFTER LIMIT IS UP
PRTCHR5 LD A,B ;GET THE NEW COUNT
LD (CHCNT),A ;SAVE IT
JP PRTCHR ;LOOP ON
;
; Input a character from the keyboard.
;
CONCHR CALL GETKEY ;Get a keyboard character without
JP NZ,RSKP ;Return if not one
LD E,A ;Is it CONNECT escape character?
LD A,(ESCCHR)
CP E
JP Z,INTCHR ;Go process the next key pressed
CONCHR2 IFANOT 128,CONCHR3 ;BREAK?
CALL DOBRK ;Generate real BREAK
JP RSKP
CONCHR3 LD A,E
CONCHR4 PUSH DE ;SAVE DE
CALL PRTOUT ;SEND IT TO THE PORT
POP DE
LD A,(ECOFLG) ;CHECK FOR LOCAL ECHO
OR A
LD A,E
CALL NZ,TRMOUT ;Echo out terminal device
JP RSKP ;RETURN TO THE CALLER SAY OK
;
; This is the code to process the escape sequences during the
; CONNECT command that do things like return to the KERMIT
; prompt, send a break, turn logging on and off, etc...
;
INTCHR EQU $
CALL GETKEY ;Get a character from translator
JR NZ,INTCHR ;Loop until we get one
INCH00 EQU $
LD B,A ;Put the real character into B
AND 137O ;Convert A to upper case
IFANOT 'C',INCH01 ;Is it connect, if not try other
CALL SCRCMD ;Swap KERMIT screen in
LD A,(SVMAX) ;Restore the old max
LD (MAXCNT),A
RET ;Return to KERMIT
INCH01 LD A,B ;Get the real value
IFANOT '?',INTCH1 ;Is it help, if not try next
LD A,15 ;Turn the cursor off
CALL CONOUT
LD B,4 ;Get the cursor position
CALL XVDCTL
PUSH HL ;Save it
LD HL,2600H ;Save the screen
LD B,6 ;Get screen function
CALL XVDCTL ;Do the move
LD HL,0C00H ;Move to middle
CALL TOSCRPOS ;Move to possition on screen
LD A,31 ;Clear to eos
CALL CONOUT
LD DE,INTHLP ;Get Help message
CALL PRTSTR ;Print message
INCH11 CALL GETKEY ;Get a character
JR NZ,INCH11 ;Jump if no key pressed
POP HL ;Reorder the stack
PUSH AF
PUSH HL
LD HL,2600H ;Get the old screen
LD B,5 ;Put it back into view
CALL XVDCTL
POP HL ;Restore old cursor position
CALL TOSCRPOS ;Position the cursor
LD A,14 ;Turn the cursor back on
CALL CONOUT
POP AF ;Get the character typed back
JR INCH00 ;Loop back to process character
;
INTCH1 AND 137O ;Convert back to uppercase
IFANOT 'B',INTCH2 ;Is it BREAK, if not try next
CALL DOBRK ;Send BREAK out port
JP RSKP ;Return NO error
INTCH2 LD A,B ;Get the real character
IFANOT '0',INTCH3 ;Is it NULL, if not try next
LD E,0 ;Get a NULL
CALL OUTCHR ;Out the port with it
JP RSKP ;Return no error
INTCH3 LD E,B ;Get the real character
LD A,(ESCCHR) ;Get the escape character
IFA E,INTCHZ ;Is it the escape character ?
LD A,B ;Get the real character
AND 137O ;Upper case again
IFANOT 'Q',INTCH4 ;Is it QUIT, if not try next
LD A,(LOGFLG) ;Get the logging flag
IFANOT 2,INTC3A ;Is logging active, jump if not
DEC A ;Turn logging off
LD (LOGFLG),A ;Set the value
JP RSKP ;Return no error
INTC3A LD A,BELL ;Get An error sound
CALL CONOUT ;BEEP AT THEM
JP RSKP ;Return no error
INTCH4 IFANOT 'R',INTCH5 ;Resume logging? Jump if not
LD A,(LOGFLG) ;Check logging status
IFANOT 1,INTC3A ;If not 1, can't resume
INC A ;Turn logging on
LD (LOGFLG),A ;Set the value
JP RSKP ;Return no error
INTCH5 LD A,E ;Get the character typed
CALL PRTOUT ;Send it out the port
JP RSKP ;Return no error
INTCHZ CALL OUTCHR ;Send it out the port
LD A,BELL ;Get a bell
CALL CONOUT ;Send bell to terminal
JP RSKP ;Return no error
;
; Send character to printer
;
PRTIT EQU $
LD A,E ;Get the character
PUSH DE ;Save E for return
CALL XPRT ;Dos printer routine
POP DE ;Restore E
RET ;Return
;
; Generate a real modem break
;
DOBRK LD C,1 ;OPTION 1 OF @CTL
LD DE,(CLDCB) ;Get the *CL DCB
CALL XCTL ;Do @CTL to start Modem break
DI ;Make the pause be exact
LD BC,39000 ;Pause for 200ms
BRKLOOP DEC BC ;Decrement the count
LD A,B
OR C
JR NZ,BRKLOOP ;Loop until done
EI
LD E,0 ;Stop break with any character
JP OUTCHR ;Null is good
;
; Output any none null character to the RS232 port
;
PRTOUT OR A ;Don't send NULLS
RET Z
LD E,A ;Get the character
JP OUTCHR ;Output it
;
; Log a character to the log file
;
LOGONE PUSH AF
PUSH DE
LD E,A
LD A,(LOGFLG)
OR A
LD A,E
CALL NZ,LOGIT
POP DE
POP AF
RET
;
; Output a character to *DO
;
CONOUT PUSH DE ;SAVE THE REGS
PUSH BC
PUSH AF
IFA BELL,BEEPON ;Go if bell
CALL XDSP ;Use the @DSP SVC to display it
CON010 POP BC ;Use BC to get A, and not destroy flags
LD A,B ;Get the old A
POP BC
POP DE
RET ;RETURN TO THE CALLER
;
; Output a character to *SO
;
TRMOUT PUSH DE ;Save the regs
PUSH BC
PUSH AF
LD E,A ;Make a copy of the character
LD A,(EMULFLAG) ;Get the emulation flag
IFZ TRMOUT3 ;Jump if EMULATION set to NONE
;
; Certain control characters are translated on input. In
; particular, the following mappings are in effect.
;
; 8 -> 24 non destructive backspace
; 10 -> 26 non destructive linefeed
; 13 -> 29 True carriage return
;
LD A,E ;Is this a control character?
IFAGE 32,TRMOUT3 ;Jump if not a control character
LD HL,TRTAB ;Get the translation table
LD B,0 ;Make BC an offset into TRTAB
;
; If the character in the translation table is 0, then it is
; ignored. This is handy for blocking out things like cursor
; on/off, and inverse video on/off
;
LD C,A ;Get the character to use as index
ADD HL,BC ;Index to the table
LD A,(HL) ;Get the translated character
IFZ TRMOUT5 ;Return if character is to be ignored
LD E,A ;Make a copy for later
IFANOT 12,TRMOUT1 ;Jump if not a formfeed
CALL CMBLNK ;Clear the screen
JR TRMOUT5
TRMOUT1 IFANOT 7,TRMOUT3 ;Jump if not bell
CALL CONOUT ;DUMB uses BUILTIN Bell
JR TRMOUT5
TRMOUT3 EQU $
LD A,E ;Get the character
LD DE,(TMODCB) ;Get the Device DCB for terminal out
CALL XPUT ;@PUT the character to the device
TRMOUT5 POP BC ;Use BC to get A, and leave Flags alone
LD A,B ;Get A
POP BC ;Restore BC
POP DE ;And the rest
RET
;
; Input a character from *SI
;
TRMIN PUSH DE
PUSH BC
LD DE,(TMIDCB) ;Get the terminal input DCB
CALL XGET ;@GET a character
POP BC ;Restore the regs
POP DE
RET
;
; Sound a bell
;
BEEPON LD A,(BELFLG) ;IS THAT OPTION ON?
IFZ CON010 ;Jump if bell option off
PUSH BC ;Save counter
LD C,50 ;Get the duration
BEEP1 LD A,1 ;Get the value to send out port
OUT (90H),A ;Toggle port high
LD B,130 ;Delay
DJNZ $
DEC A ;Set A to zero
OUT (90H),A ;Toggle port low
LD B,130 ;Delay
DJNZ $
DEC C ;Decrement duration
JR NZ,BEEP1 ;Loop if not done
POP BC ;Restore counter
JR CON010 ;Join return code
;
; Print string pointed to by DE to *DO, EOS is end of string
; NUL characters are thrown out.
;
PRTSTR LD A,(DE) ;GET A CHARACTER
CP EOS ;IS IT THE END?
RET Z ;RETURN TO CALLER IF SO
OR A ;THROW AWAY THE NULL CHARACTER
CALL NZ,CONOUT ;DISPLAY ANYTHING NON-NULL
INC DE ;POINT TO THE NEXT ONE
JR PRTSTR ;LOOP ON
;
; Get a character from *KI
;
CONIN PUSH DE ;SAVE DE
CALL XKBD ;LOOK AT THE KEYBOARD WITHOUT WAITING
POP DE ;RESTORE DE
RET ;RETURN TO THE CALLER
;
; Output a character to *CL. The character is in E.
;
OUTCHR PUSH DE ;SAVE CURRENT DE AND BC
PUSH BC
LD C,E ;Put the character where it should be
OUTCH0 LD A,(XOFREC) ;CHECK TO SEE IF WE CAN TRANSMIT YET!
IFZ OUTCH2
;
; We allow break to force the transmittion of the character that
; is being sent. There are ways that the XON from the host can
; be lost. This allows control to be regained, without rebooting
; which would be the only other choice.
;
OUTCH1 CALL CONIN ;Check the break key
IFANOT 128,OUTCH0 ;Jump if not
XOR A ;Reset the XOF'd flag
LD (XOFREC),A
OUTCH2 LD A,C ;Get the character to send
OUTCH3 LD DE,(CLDCB) ;GET THE DCB OF THE DEVICE TO PUT TO
CALL XPUT ;SEND THE CHARACTER
JR NZ,OUTCH3 ;Transmitter may not be ready, loop if
; needed until character is transmitted
OUTCH4 POP BC ;Restore the regs
POP DE
RET
;
; Character input routine for INPKT. We can timeout on the
; receive by allowing the timer to place a return in the code
; below, at the address RECALRM. Since TRSDOS doesn't allow
; us (neatly, without a hack) to transfer control in a task,
; to some other code, we use the self modifying code. This
; may be considered dirty, but it does work. The RET causes
; the code to behave as though the user had pressed <ENTER> to
; resend the latest packet.
;
INCHR XOR A ;Get a NOP instruction
LD (RECALRM),A ;Remove any stored RET instruction
INCHR1 CALL CONIN ;Check keyboard first to make sure
IFNZ INCHR3
CALL INPORT ;Get a character from the buffer
JP Z,RSKP ;Return if we got one
RECALRM NOP ;Modified by timeout code to be a RET
JR INCHR
INCHR3 IFANOT CR,INCHR4 ;Check which key was pressed
LD A,(TASKSLOT) ;Get the active task
OR A ;See if task aqctive
RET Z ;Return if not
LD C,A ;Get the task slot into c
CALL XRMTSK ;Stop the task
RET ;Return resend status
INCHR4 CHKWKEY 'B'-64 ;Control-B for batch
CHKWKEY 'F'-64 ;Control-F for file
CHKWKEY 'A'-64 ;Control-A for status
CHKWKEY 'E'-64 ;Control-E for send error
CHKWKEY 'D'-64 ;Debug?
CHKWKEY 'H'-64 ;Help?
IFANOT 'C'-64,INCHR1 ;Control-C for abort completely
INCHR5 ADD A,40H ;MAKE IT PRINTABLE
LD (CZSEEN),A
RET
;
; Timer task for receiving a packet. Called every 33.333333333
; milliseconds. We decrement the TIMER counter, and when it
; goes to zero, we write a RET into the above code, and kill
; the task so that is does not return.
;
; Note that we must NOT leave anything on the stack when @KLTSK
; is called or else it will puke.
;
RECTIMOUT EQU $
PUSH HL ;Save the registers used
PUSH AF
LD HL,(TIMER) ;Get the counter
DEC HL ;Decrement it
LD (TIMER),HL ;Store the new value
LD A,H ;Check it for zero
OR L
JR NZ,RECT1
LD A,0C9H ;Get a RET instruction opcode
LD (RECALRM),A ;Write it in
POP AF ;Restore the register
POP HL
JP XKLTSK ;Remove this task, NO RETURN.
;
RECT1 POP AF ;Restore the registers
POP HL
RET ;Return
;
; Move cursor to position on screen
;
TOSCRPOS EQU $
LD B,3
JP XVDCTL
;end of file