PAGE 60,132 ;60 lines, 132 columns TITLE MSXTIPRO - Texas Instruments "Professional" code for KERMIT REVLVL EQU 3 ;Revision level for this module, 29-Nov-84 ;************ REVISION HISTORY for MSXTIPRO.ASM ********************** ; ; REVLVL=1 29-Oct-84 First version to be able to transfer files ; REVLVL=2 14-Nov-84 Fixed bugs in version 1 ; REVLVL=3 27-Nov-84 Added Tektronix-4010 emulation in CONNECT mode ; ; -- CHANGES -- ; ; MSXTIPRO has been tested with the Sync/Async Comm Card at all speeds from ; 110 to 9600 baud using SET PORT 1 thru SET PORT 4, and a 300-baud ; internal modem in port 3. ; ; To use the internal modem, SET PORT 3, SET BAUD 300, CONNECT. ; With external phone, type "O" to go into manual original mode. ; Or type "T1(617)467-7437X" to use the built-in dialer. Capital T ; means to use touch-tones, capital X marks the end of the number. ; ; Terminal emulation works fine at 1200 baud, reasonably OK at 2400 baud ; if you use ".SET TERMINAL TYPE VT100 FILL 3" on TOPS-10. ; ; Can transfer file-packets at 9600 baud (but not 19.2 kbaud). ; ; The VT52 "identify yourself" sequence of ESC,'Z' triggers a response of ; ESC,'[?1;4c' which is a VT100 with graphics (but no STP, no printer). ; ; -- BUGS -- ; ; No known bugs at this time (28-Nov-84). ; ; -- DEFICIENCIES -- ; ; The STATUS command is wrong if you select port 2, 3, or 4. ;**** According to the MSXSYS.DOC, flags.comflg is supposed to be 0 ;**** when using port 2. This makes it difficult to use ports 3 and 4. extrn port3:byte, port4:byte ;******** ;**** MSCOMM.ASM must be edited to define PORT3 and PORT4 like PORT1 and 2. ;**** You MUST edit MSCOMM.ASM, and add the following at line 17: ; port3 prtinfo <0FFFH,0,defpar,1,0,defhand,floxon> ; port4 prtinfo <0FFFH,0,defpar,1,0,defhand,floxon> ; ; The SET HEATH-19 ON/OFF command needs to be replaced by a new command, ; SET TERMINAL-EMULATION ON/OFF/HEATH-19/VT52/VT100/VT102/ADM3A/TVI910/etc. ; In REVLVL=3, this command changes only the ID sequence for ESC-Z. ; ; ANSI.SYS is a part of the TI-BIOS, but it does not fully emulate a VT100. ; FIX: Add more features to MSTEKTRM.ASM, rename it to MSVT241.ASM. ; [I am working on this for version 4. /Joe] ; ; Looses the 4th character after LF at 2400 baud when scrolling because DOS ; is so slow at outputing characters to the screen. Looses even more at 9600 ; baud. (Although you can type "KERMIT SERVER" at transfer files at 9600.) ; FIX: Use interrupt handling instead of polling USART, with XON/XOFF. ; (Received a listing from Charlie Lindahl, not yet implemented) ; [Feel free to add this, I will be working on MSVT241. /Joe] ; ;************************************************************************* ;Credits: ; Joe Smith, Systems Programmer for DECsystem-10, CSM Computing Center ; Dan Smith, Microcomputer Programmer, CSM Computing Center ; Colorado School of Mines, Golden CO 80401 (303)273-3448,273-3396 ; Charlie Lindahl, Rusty Haddock, Steve Krueger, Larry Kroeker of TI ; Texas Instruments Computer Science Laboratory ; P.O. Box 226015 - MS 238, Dallas, TX 75266 (214)995-0376 public serini, serrst, clrbuf, outchr, coms, vts, dodel, public ctlu, cmblnk, locate, lclini, prtchr, dobaud, clearl, public dodisk, getbaud, beep public count, xofsnt, puthlp, putmod, clrmod, poscur public sendbr, term, machnam, setktab, setkhlp, showkey include msdefs.h SUBTTL Constants used by Zilog Z-8530 Serial Communications Controller ;Taken from page 3-12 of the TI-PRO Technical Reference Manual 2223216-0001 SCC1_INTA EQU 0E0h ;Port 1 interrupt acknowledge SCC1_BCMD EQU 0E4h ;Port 1 channel B command SCC1_BDAT EQU 0E5h ;Port 1 channel B data (not used) SCC1_ACMD EQU 0E6h ;Port 1 channel A command SCC1_ADAT EQU 0E7h ;Port 1 channel A data SCC2_INTA EQU 0E8h ;Port 2 interrupt acknowledge SCC2_BCMD EQU 0ECh ;Port 2 channel B command SCC2_BDAT EQU 0EDh ;Port 2 channel B data (not used) SCC2_ACMD EQU 0EEh ;Port 2 channel A command SCC2_ADAT EQU 0EFh ;Port 2 channel A data SCC3_INTA EQU 0F0h ;Port 3 interrupt acknowledge SCC3_BCMD EQU 0F4h ;Port 3 channel B command SCC3_BDAT EQU 0F5h ;Port 3 channel B data (not used) SCC3_ACMD EQU 0F6h ;Port 3 channel A command SCC3_ADAT EQU 0F7h ;Port 3 channel A data SCC4_INTA EQU 0F8h ;Port 4 interrupt acknowledge SCC4_BCMD EQU 0FCh ;Port 4 channel B command SCC4_BDAT EQU 0FDh ;Port 4 channel B data (not used) SCC4_ACMD EQU 0FEh ;Port 4 channel A command SCC4_ADAT EQU 0FFh ;Port 4 channel A data ;To send the INTACK signal to the Z8530, write anything to SCCx_INTA and then ;immdiately read from SCCx_INTA. The 8-bit interrupt vector is returned. ;------------------------------------------------------------------------------- ;From ZILOG's Z8030/Z8050 SCC Serial Communications Controller Technical Manual ;Bits for WR0 - set by writing to SC1ACMD or SC1BCMD SW0_SREG EQU 00001111b ;Set register pointer (if hi 4 bits all zero) ;;;_CMD1 --XXX---b ;Command bits 1 SW0_RESET EQU 010b*8 ;Reset EXT/STATUS (must be done twice) SW0_ABORT EQU 011b*8 ;Send ABORT (SDLC mode only) SW0_INTEN EQU 100b*8 ;Enable INT on next Rx character SW0_TXINT EQU 101b*8 ;Reset TxINT pending SW0_ERROR EQU 110b*8 ;Error reset (unlock FIFO) SW0_RHIUS EQU 111b*8 ;Reset highest IUS (interrupt under service) ;;;_CMD2 XX------b ;Command bits 2 SW0_RRCRC EQU 01b*64 ;Reset Rx CRC checker (SYNC) SW0_RTCRC EQU 10b*64 ;Reset Tx CRC generator (SYNC) SW0_RTEOM EQU 11b*64 ;Reset Tx underrun/EOM latch (SYNC) ;Bits for WR1 - Rx/Tx Interrupt and Data Transfer Mode SW1_NOINT EQU 00000000b ;Disable interrupts SW1_EXINT EQU 00000001b ;External/Status interrupt enable SW1_TXINT EQU 00000010b ;Transmit interrupt enable SW1_PAREN EQU 00000100b ;Parity error activates special condition ;;;_CMD ---XX---b ;Receive Interrupt Modes SW1_NORI EQU 00b*16 ;Receive Interrupts Disabled SW1_I1ST EQU 01b*16 ;Interrupt on 1st character or special condition SW1_IALL EQU 10b*16 ;Interrupt on all character or special condition SW1_ISPC EQU 11b*16 ;Interrupt on special condition only SW1_REC EQU 00100000b ;Activate receive request (1 for transmit) SW1_WAIT EQU 01000000b ;Activate the DMA request (0 for WAIT request) SW1_DMAEN EQU 10000000b ;Enable WAIT/DMA as selected by bits 5 & 6 ;Bits for WR2 - Interrupt vector SW2_VECT EQU 11111111b ;8-bits of interrupt vector ;Bits for WR3 - Receive Parameters and Control SW3_RXEN EQU 00000001b ;Rx Enable (set only after all other parameters) SW3_NSYNC EQU 00000010b ;Sync character load inhibit (SYNC only) SW3_ADDR EQU 00000100b ;Address search mode (SDLC only) SW3_RXCRC EQU 00001000b ;Enable Rx CRC (SDLC only) SW3_HUNT EQU 00010000b ;Enter hunt mode (SYNC) SW3_AUTOE EQU 00100000b ;Autoenable, CTS for Tx, DCD for Rx enable ;;;_BITS XX------b ;Receive bits per character SW3_5BITS EQU 00b*64 ;5 bits per character SW3_6BITS EQU 01b*64 ;6 bits per character SW3_7BITS EQU 10b*64 ;7 bits per character SW3_8BITS EQU 11b*64 ;8 bits per character ;Bits for WR4 - Tx/Rx misc parameters and modes SW4_PAREN EQU 00000001b ;Parity enable (transmit and receive both) SW4_EVENP EQU 00000010b ;Even Parity (0 for Odd) ;;;_STOPB ----XX--b ;Number of stop bits SW4_SYNC EQU 00b*4 ;Synchronous mode enable SW4_1STOP EQU 01b*4 ;1 stop bit SW4_1HALF EQU 10b*4 ;1.5 stop bits SW4_2STOP EQU 11b*4 ;2 stop bits ;;;_SYNCM --XX----b ;Sync modes SW4_8BIT EQU 00b*16 ;8-bit sync character SW4_16BIT EQU 01b*16 ;16-bit sync character SW4_SDLC EQU 10b*16 ;SDLC mode (pattern 01111110) SW4_EXTS EQU 11b*16 ;External sync mode ;;;_CLOCK XX------b ;Clock rate SW4_X1 EQU 00b*64 ;Clock rate = data rate SW4_X16 EQU 01b*64 ;Clock rate = 16 times the data rate SW4_X32 EQU 10b*64 ;Clock rate = 32 times the data rate SW4_X64 EQU 11b*64 ;Clock rate = 64 times the data rate ;Bits for WR5 - Transmit parameters and control SW5_TCRC EQU 00000001b ;Calculate and transmit CRC (SYNC only) SW5_RTS EQU 00000010b ;Raise RTS (set RCNTL for B) SW5_CRC16 EQU 00000100b ;CRC-16 polynomial (0 for SDLC) (SYNC only) SW5_TXEN EQU 00001000b ;Tx Enable (set only after all other parameters) SW5_BREAK EQU 00010000b ;Send a BREAK condition ;;;_BITS -XX-----b ;Transmit bits per character SW5_5BITS EQU 00b*32 ;5 or fewer bits per character SW5_6BITS EQU 01b*32 ;6 bits per character SW5_7BITS EQU 10b*32 ;7 bits per character SW5_8BITS EQU 11b*32 ;8 bits per character SW5_DTR EQU 10000000b ;Raise DTR (set speed indicator for B) ;Bits for WR6 - SYNC character 0 SW6_SYNC EQU 11111111b ;Sync character ;Bits for WR7 - SYNC character 1 SW7_SYNC EQU 11111111b ;Sync character ;Bits for WR8 - Transmit data SW8_DATA EQU 11111111b ;Same as writing to SCCx_xDAT ;Bits for WR9 - Master interrupt control SW9_VSTAT EQU 00000001b ;Int vector modified depending on status SW9_NOVEC EQU 00000010b ;No vector during interrupt acknowledge SW9_IEOL EQU 00000100b ;Force Interrupt Enable Out low SW9_MIEN EQU 00001000b ;Master Interrupt Enable SW9_VEC16 EQU 00010000b ;Int vector multiple of 16 (0 for mult of 2) ;;;_BIT5 EQU 00100000b ;Unused, must be 0 ;;;_RESET XX------b ;Reset channel commands SW9_CBR EQU 01b*64 ;Channel A reset SW9_CAR EQU 10b*64 ;Channel B reset SW9_RESET EQU 11b*64 ;Force hardware reset ;Bits for WR10 - Miscellaneous Transmit/Receive control bits SWA_6BIT EQU 00000001b ;Use only 6 of 8 bits to detect sync character SWA_LOOP EQU 00000010b ;Synchronous loop-back mode SWA_ABORT EQU 00000100b ;Sent abort on transmit underrun SWA_MARK EQU 00001000b ;Send mark when idle (0 to send flag) SWA_GAOP EQU 00010000b ;Go active on poll (SYNC only) ;;;_CODE -XX-----b ;Data encoding SWA_NRZ EQU 00b*32 ;NRZ (1=1, 0=0) (ASYNC) SWA_NRZI EQU 01b*32 ;NRZI (1=no change, 0=invert) SWA_FM1 EQU 10b*32 ;FM1 (1=high frequency, 0=low frequency) SWA_FM0 EQU 11b*32 ;FM0 (1=low frequency, 1=high frequency) SWA_PCRC EQU 10000000b ;Preset CRC to all ones (0 for all zeros) ;Bits for WR11 - Clock mode control ;;;_TRXC ------XXb ;TRxC output control SWB_XTALO EQU 00b ;TRxC output same as XTAL oscillator SWB_TRANS EQU 01b ;TRxC output same as transmitter clock SWB_BRGO EQU 10b ;TRxC output same as baud rate generator SWB_DPLLO EQU 11b ;TRxC output same as digital phase-locked-loop SWB_TRXCO EQU 00000100b ;TRxC pin is an output (0=TRxC is an input) ;;;_TXC ---XX---b ;Transmit clock SWB_TRTXC EQU 00b*8 ;Transmit clock = RTxC pin SWB_TTRXC EQU 01b*8 ;Transmit clock = TRxC pin SWB_TBRG EQU 10b*8 ;Transmit clock = baud rate generator output SWB_TDPLL EQU 11b*8 ;Transmit clock = digital phase-locked-loop ;;;_RXC -XX-----b ;Receive clock SWB_RRTXC EQU 00b*32 ;Receive clock = RTxC pin SWB_RTRXC EQU 01b*32 ;Receive clock = TRxC pin SWB_RBRG EQU 10b*32 ;Receive clock = baud rate generator output SWB_RDPLL EQU 11b*32 ;Receive clock = digital phase-locked-loop SWB_XTAL EQU 10000000b ;Crystal is connected between RTxC and SYNC pins ;Bits for WR12 (low byte of divisor) and WR13 (high byte) in decimal. SWC_BAUD EQU 11111111b ;Low byte SWD_BAUD EQU 11111111b ;High byte ;Taken from page 3-10 of the TI-PRO Technical Reference Manual 2223216-0001 SCC_0045 EQU 1686 ; 45.5 baud SCC_0050 EQU 1534 ; 50 baud SCC_0075 EQU 1022 ; 75 baud SCC_0100 EQU 0696 ; 110 baud (+0.03%) SCC_0134 EQU 0569 ; 134.5 baud (Selectric) SCC_0150 EQU 0510 ; 150 baud SCC_0200 EQU 0382 ; 200 baud SCC_0300 EQU 0254 ; 300 baud SCC_0600 EQU 0126 ; 600 baud SCC_1200 EQU 0062 ;1200 baud SCC_1800 EQU 0041 ;1800 baud (-0.78%) SCC_2000 EQU 0036 ;2000 baud (+1.05%) SCC_2400 EQU 0030 ;2400 baud SCC_3600 EQU 0019 ;3600 baud (+1.59%) SCC_4800 EQU 0014 ;4800 baud SCC_7200 EQU 0009 ;7200 baud (-3.03%) SCC_9600 EQU 0006 ;9600 baud SCC_19K2 EQU 0002 ;19.2 kbaud ;Divisor = (256*300/BAUD)-2 for 16x async clock with 4.9152 MHz crystal ;Bits for WR14 - Miscellaneous control bits SWE_BRENA EQU 00000001b ;Baud Rate Generator enable SWE_PCLK EQU 00000010b ;BRG source is PCLK pin (1 for RTxC/XTAL) SWE_DTREQ EQU 00000100b ;DTR/REQ pin triggers DMA output cycle SWE_AECHO EQU 00001000b ;Auto Echo, TxD connected to RxD SWE_LLOOP EQU 00010000b ;Local Loopback on the digital side ;;;_DPLL XXX-----b ;Command field SWE_NUL EQU 000b*32 ;Null command SWE_SEA EQU 001b*32 ;DPLL enters search mode SWE_RMC EQU 010b*32 ;Reset Missing Clock in FM mode SWE_DPL EQU 011b*32 ;Disable DPLL SWE_SBR EQU 100b*32 ;Set DPLL source = BRG clock SWE_STC EQU 101b*32 ;Set DPLL source = RTxC clock SWE_SFM EQU 110b*32 ;Set DPLL to FM mode SWE_SNR EQU 111b*32 ;Set DPLL to NRZI mode ;Bits for WR15 - External/Status Interrupt Control SWF_NOINT EQU 00000000b ;Disable interrupts ;;;_BIT0 EQU 00000001b ;Not used, must be 0 SWF_ZEROC EQU 00000010b ;Interrupt when BRG count goes to zero ;;;_BIT2 EQU 00000100b ;Not used, must be 0 SWF_DCD EQU 00001000b ;Interrupt when DCD changes state SWF_SYNC EQU 00010000b ;Interrupt when SYNC changes state SWF_CTS EQU 00100000b ;Interrupt when CTS changes state SWF_EOM EQU 01000000b ;Interrupt when transmit underrun or EOM SWF_BREAK EQU 10000000b ;Interrupt when BREAK or ABORT condition ;------------------------------------------------------------------------------- ;Bits for RR0 - available by reading SC1ACMD or SC1BCMD SR0_RBUFA EQU 00000001b ;Receive buffer has character(s) available SR0_ZEROC EQU 00000010b ;Baud Rate Generator count is zero SR0_TBUFE EQU 00000100b ;Transmitter buffer empty (double-buffered) SR0_DCD EQU 00001000b ;DCD is on (channel-B DCD connected to DSR) SR0_SYNC EQU 00010000b ;SYNC in on (ACNTL or modem detected hi speed) SR0_CTS EQU 00100000b ;CTS in on (channel-B CTS connected to RING) SR0_EOM EQU 01000000b ;Transmitter underrun or EOM (SYNC only) SR0_BREAK EQU 10000000b ;BREAK (async) or ABORT (sync) condition ;Bits for RR1 - Special receive conditions SR1_SENT EQU 00000001b ;Last transmit bit has left TxD pin SR1_RES EQU 00001110b ;Residue from I-field (SDLC only) SR1_PAR EQU 00010000b ;Parity error SR1_OVER EQU 00100000b ;Receive overrun (FIFO overflowed) SR1_FRAME EQU 01000000b ;CRC or framing error SR1_EOF EQU 10000000b ;End of Frame (SDLC only) ;Bits for RR3 - Interrupt Pending SR3_BEXT EQU 00000001b ;Channel B external/status SR3_BTX EQU 00000010b ;Channel B transmitter empty SR3_BRX EQU 00000100b ;Channel B receiver full SR3_AEXT EQU 00001000b ;Channel A external/status SR3_ATX EQU 00010000b ;Channel A transmitter empty SR3_ARX EQU 00100000b ;Channel A receiver full ;;;_BIT6 EQU 01000000b ;Not used, always zero ;;;_BIT7 EQU 10000000b ;Not used, always zero ;Bits for RR8 - Receive data SR8_DATA EQU SW8_DATA ;Same as writing to SCCx_xDAT ;Bits for RR10 - Miscellaneous status bits ;;;_BIT0 EQU 00000001b ;Not used, always zero SRA_LOOP EQU 00000010b ;On-loop condition (SDLC only) ;;;_BIT2 EQU 00000100b ;Not used, always zero ;;;_BIT3 EQU 00001000b ;Not used, always zero SRA_SEND EQU 00010000b ;SCC is actively on-loop and sending now ;;;_BIT5 EQU 00100000b ;Not used, always zero SRA_2MISS EQU 01000000b ;FM mode, 2 clocks missing SRA_1MISS EQU 10000000b ;FM mode, 1 clock missing ;Bits for RR12 - Low divisor SRC_BAUD EQU SWC_BAUD ;Returns current baud rate divisor ;Bits for RR13 - High divisor SRD_BAUD EQU SWD_BAUD ;Returns current baud rate divisor ;Bits for RR15 - Interrupt enable bits ;RR15 returns the bits written to WR15 SRF_NOINT EQU SWF_NOINT ;Interrupts are disabled SRF_ZEROC EQU SWF_ZEROC ;Interrupt when BRG count is zero SRF_DCD EQU SWF_DCD ;Interrupt when DCD changes state SRF_SYNC EQU SWF_SYNC ;Interrupt when SYNC changes state SRF_CTS EQU SWF_CTS ;Interrupt when CTS changes state SRF_EOM EQU SWF_EOM ;Interrupt when transmit underrun or EOM ;------------------------------------------------------------------------------- ;Output to RS-232 connector (pin 2 has channel A transmit data) SCC_RTS EQU SW5_RTS ;Pin 4, A-WR5 bit 1, Request To Send SCC_RCNTL EQU SW5_RTS ;(RTSB) B-WR5 bit 1 (internal modem, request control) SCC_DTR EQU SW5_DTR ;Pin 20, A-WR5 bit 7, Data Terminal Ready SCC_SPDO EQU SW5_DTR ;Pin 11, B-WR5 bit 7, Speed select out (also Pin 23) ;Input from RS-232 connector (pin 3 has channel A receive data) SCC_DCD EQU SR0_DCD ;Pin 8, A-RR0 bit 3, Data Carrier Detect SCC_DSR EQU SR0_DCD ;Pin 6, B-RR0 bit 3, Data Set Ready, pin 6 SCC_ACNTL EQU SR0_SYNC ;(SYNCA) A-RR0 bit 4 (internal modem, ack control) SCC_SPDI EQU SR0_SYNC ;Pin 12, B-RR0 bit 4, Speed select in, pin 12 SCC_CTS EQU SR0_CTS ;Pin 5, A-RR0 bit 5, Clear To Send, pin 5 SCC_RI EQU SR0_CTS ;Pin 22, B-RR0 bit 5, Ring Indicator, pin 22 ;Taken from page E-1 of the TI-PRO Technical Reference Manual 2223216-0001 ;End if TI-Professional Sync/Async Comm Card definitions SUBTTL Configuration info ;To get the system configuration, execute an INT 4Fh. The number returned ;in BX is the size of contiguous RAM (in paragraphs). The bits returned ;in AX are: SYS_INT EQU 4Fh ;INT number SYS_DSKA EQU 0001h ;Diskette A (internal) installed SYS_DSKB EQU 0002h ;Diskette B (internal) installed SYS_DSKC EQU 0004h ;Diskette C (external) installed SYS_DSKD EQU 0008h ;Diskette D (external) installed SYS_1SID EQU 0010h ;E1-E2 jumper (0 indicates drive A is double sided) SYS_40TK EQU 0020h ;E3-E4 jumper (0 indicates drive A has 80 tracks) SYS_60HZ EQU 0040h ;E5-E6 jumper (0 indicates 50 Hz system) SYS_HARD EQU 0080h ;Winchester disk controller installed SYS_PRT1 EQU 0100h ;Serial port 1 installed SYS_PRT2 EQU 0200h ;Serial port 2 installed SYS_PRT3 EQU 0400h ;Serial port 3 installed SYS_PRT4 EQU 0800h ;Serial port 4 installed SYS_GRFA EQU 1000h ;Graphics RAM bank A installed SYS_GRFB EQU 2000h ;Graphics RAM bank B installed SYS_GRFC EQU 4000h ;Graphics RAM bank C installed SYS_RSVD EQU 8000h ;Reserved ;Speaker control - Put code in AH and execute INT 48h SPK_INT EQU 48h ;INT number SPK_BEEP EQU 0h ;Sound speaker, AL has number of 25ms ticks (40=1 sec) SPK_STAT EQU 1h ;Get speaker status, Z-flag is set if enabled SPK_FREQ EQU 2h ;Set speaker frequency from CX (1563 = 800 Hz) SPK_ON EQU 3h ;Turn on speaker until SPK_OFF or SKP_BEEP SPK_OFF EQU 4h ;Turn off speaker SUBTTL Data segment ; external variables used: ; drives - # of disk drives on system ; flags - global flags as per flginfo structure defined in pcdefs ; trans - global transmission parameters, trinfo struct defined in pcdefs ; portval - pointer to current portinfo structure (currently either port1 ; or port2) ; port1, port2 - portinfo structures for the corresponding ports ; global variables defined in this module: ; xofsnt, xofrcv - tell whether we saw or sent an xoff. datas segment public 'datas' extrn drives:byte,flags:byte, trans:byte extrn portval:word, port1:byte, port2:byte false equ 0 true equ 1 machnam db 'TI-PRO (rev ',REVLVL+'0',')$' badbd db cr,lf,'Unimplemented baud rate$' noimp db cr,lf,'Command not implemented.$' shkmsg db 'Not implemented.' shklen equ $-shkmsg setktab db 0 setkhlp db 0 crlf db cr,lf,'$' delstr db BS,' ',BS,'$' ; Delete string. clrlin db cr ; Must be at clreol-1 clreol db esc,'[K$' ; Clear line. homeras db esc,'[H',esc,'[J$' ;Home and erase posseq db esc,'[00;00H$' ; Escape sequence to position cursor rowhi equ posseq+2 rowlo equ posseq+3 colhi equ posseq+5 ; Modified by POSCUR routine collo equ posseq+6 invvid db esc,'[0;7m($' ; Inverse video norvid db ')',esc,'[0;1m$'; Normal video (WHITE=BOLD, as opposed to GREEN) ;For IBM-PC, numbers are 12,20,5,20,199 for coordinates to 613,194 xmult dw 9 ; Scale TEK to TI by 9/13 xdiv dw 13 ; so that 0-1023 converts to 0-708 ymult dw 5 ; Scale TEK to TI by 5/13 ydiv dw 13 ; so that 0-779 converts to 299-0 ybot dw 299 ; Bottom of screen is Y=299 oldx dw 0 ; Previous scaled coordinates oldy dw 0 palnorm db 0,1,2,3,4,5,6,7 ;Normal colors pal1pln db 0,7,2,3,4,5,6,1 ;For single-plane machines, 0=Black,1=White pal3pln db 0,4,2,3,1,5,6,7 ;For three-plane machines, 0=Black,1=Green sysdata dw 0 ;AX from SYS_INT syssize dw 0 ;BX from SYS_INT xofsnt db 0 ; Say if we sent an XOFF. xofrcv db 0 ; Say if we received an XOFF. count dw 0 ; Number of chars in int buffer. portin db 0 ; Non-zero if port is initialized porttab db 04h ; 4 entries db 01h,'1$' dw 01h db 01h,'2$' dw 02h ;*** NOTE: This is 2, not 0 **** db 01h,'3$' dw 03h db 01h,'4$' dw 04h termtab db 11 ;Number of entries db 05h,'ADM3A$' dw tty_adm3a db 04h,'GIGI$' dw tty_gigi db 08h,'HEATH-19$' dw tty_heath db 03h,'OFF$' dw tty_dos db 02h,'ON$' dw tty_heath ;Same as HEATH-19 db 06h,'TI-PRO$' dw tty_tipro db 06h,'TVI910$' dw tty_tvi910 db 05h,'VT100$' dw tty_vt100 db 05h,'VT102$' dw tty_vt102 db 05h,'VT125$' dw tty_vt125 db 04h,'VT52$' dw tty_vt52 tty_heath dw ctl_vt52 ;Control table db 01h,'HEATH19' ;Type, name db esc,'/K',0 ;VT52 superset tty_vt52 dw ctl_vt52 db 02h,'VT52 ' db esc,'/Z',0 ;ANSI terminal in VT52 mode tty_tipro label word tty_dos dw ctl_none ;Use ANSI.SYS that is build into the BIOS db 03h,'TIPRO ' db esc,'[?1;4c',0 ;Like a VT100 with graphics but no STP tty_gigi dw ctl_ansi db 04h,'GIGI ' db esc,'[?5c',0 tty_vt100 dw ctl_ansi db 05h,'VT100 ' db esc,'[?1;0c',0 tty_vt102 dw ctl_ansi db 06h,'VT102 ' db esc,'[?6c',0 tty_vt125 dw ctl_ansi db 07h,'VT125 ' db esc,'[?12;7;0;102c',0 tty_adm3a dw ctl_adm db 08h,'ADM3A ' db esc,']3',0 ; Something I made up tty_tvi910 dw ctl_adm db 09h,'TVI910 ' db esc,']0',0 ; Something I made up IDSEQ dw tty_dos+10 ; Public pointer to string CTLTAB dw ctl_none ; Public pointer to control table ctl_vt52 dw 0 ctl_ansi dw 0 ctl_none dw 0 ctl_adm dw 0 modem mdminfo tmp db ?,'$' temp dw 0 temp1 dw ? ; Temporary storage. temp2 dw ? ; Temporary storage. rdbuf db 20 dup(?) ; Buffer for input. ourarg termarg <> SUBTTL Data to init Serial Controller PARMTA DB 09h ;Select WR9 DB SW9_RESET ;Reset 8530 DB 0Bh ;Select WR11 DB SWB_RBRG+SWB_TBRG+0 ;No XTAL, RxC=BRG=TxC, TRxC pin is an input DB 0Eh ;Select WR14 DB SWE_PCLK+SWE_BRENA ;BRG source is PCLK pin, enable BRG DB 0Fh ;Select WR15 DB SWF_NOINT ;Disable external status interrupts DB 01h ;Select WR1 DB SW1_NOINT ;Disable all other interupts DB 03h ;Select WR3 DB SW3_8BITS+SW3_RXEN ;8 bits, enable receiver DB 04h ;Select WR4 DB SW4_X16+SW4_1STOP+0 ;x16 clock, 1 stop bit, no parity DB 05h ;Select WR5 DB SW5_DTR+SW5_8BITS+SW5_TXEN+SW5_RTS ;Raise DTR+RTS, 8 bits, Tx enable PARMAS EQU $-PARMTA ;The baud rate is set via GETBAUD and/or DOBAUD ;Channel B parameters PARMTB DB 0Fh ;Select WR15 DB SWF_NOINT ;Disable external status interrupts DB 01h ;Select WR1 DB SW1_NOINT ;Disable all other interrupts DB 05H ;Select WR5 DB SW5_RTS ;Raise RTSB (RCNTL) for internal modem PARMBS EQU $-PARMTB BAUDAT LABEL WORD ;Divisors for Z-8530 with 4.9152-MHz oscillator DW 0696h ; 0 45.5 baud DW 05FEh ; 1 50 baud DW 03FEh ; 2 75 baud DW 02B8h ; 3 110 baud (+0.03%) DW 0239h ; 4 134.5 baud (Selectric) DW 01FEh ; 5 150 baud DW 00FEh ; 6 300 baud DW 007Eh ; 7 600 baud DW 003Eh ; 8 1200 baud DW 0029h ; 9 1800 baud (-0.78%) DW 0024h ;10 2000 baud (+1.05%) DW 001Eh ;11 2400 baud DW 000Eh ;12 4800 baud DW 0006h ;13 9600 baud DW 0002h ;14 19.2 kbaud DW 0000h ;15 38.4 kbaud - not supported BAUDLEN EQU $-BAUDAT ;Size of table in bytes ;End of init data datas ends SUBTTL Serial port routines -- Initialize code segment public extrn comnd:near, dopar:near, prserr:near, atoi:near, prompt:near extrn nout:near extrn TERMEMU:near ;Terminal emulator for TEK and VT100 public CLS,TEKDRAW,CROSHAIR ;Graphics routines public INMODEM,OUTMODEM ;I/O to communications port public INKEYB,OUTSCRN ;I/O to console public IDSEQ,CTLTAB ;Used by TERMEMU routine assume cs:code,ds:datas ;============================================================================ ; Serial-port routines - talks to the Async COMM card. ;============================================================================ ; Initialization for using serial port. Returns normally. ; This is called for by SEND, RECEIVE, and CONNECT commands. SERINI PROC NEAR cld ; Do increments in string operations cmp portin,0 ; Is it initialized already? jne serinc ; Yes, skip all this mov si,offset PARMTA ; Addr of port A parameter table mov dx,modem.mdstat ; Port A command/status addr in al,dx ; Make sure it's pointing to WR0 mov cx,PARMAS ; Table size serina: lods PARMTA ; Get a byte out dx,al ; Send it to 8530 loop serina ; Do all of port A mov si,offset PARMTB ; Addr of port-B parameter table mov dx,modem.mdcom ; Port B command/status addr in al,dx ; Make sure it's pointing to WR0 mov cx,PARMBS serinb: lods PARMTB ; Get a byte out dx,al ; Send it to 8530 loop serinb serinc: mov portin,0FFh ; Flag that port is set up ret SERINI ENDP ; Reset the serial port. This is the opposite of SERINI. Calling ; this twice without intervening calls to SERINI should be harmless. ; Returns normally. SERRST PROC NEAR mov portin,00h ; Port is not set up ret ; All done. SERRST ENDP ; Clear the input buffer. This throws away all the characters in the ; serial interrupt buffer. This is particularly important when ; talking to servers, since NAKs can accumulate in the buffer. ; Do nothing since we are not interrupt driven. Returns normally. CLRBUF PROC NEAR mov cx,8 mov dx,modem.mddat ; Address channel-A data register clrbf1: in al,dx ; Clear out anything in the receive FIFO loop clrbf1 mov count,cx ; Set count to zero ret CLRBUF ENDP SUBTTL Serial port routines -- Output to the port ; Put the char in AH to the serial port. This assumes the ; port has been initialized. Should honor xon/xoff. Skip returns on ; success, returns normally if the character cannot be written. OUTCHR PROC NEAR push bx push cx push dx mov bx,portval cmp [bx].floflg,0 ; Are we doing flow control. je outch2 ; No, just continue. xor cx,cx ; clear counter outch1: cmp xofrcv,true ; Are we being held? jne outch2 ; No - it's OK to go on. loop outch1 ; held, try for a while mov xofrcv,false ; timed out, force it off and fall thru. outch2: mov al,ah ; Parity routine works on AL. call dopar ; Set parity appropriately. mov ah,al ; Preserve character for a bit xor cx,cx ; Set loop counter to max mov dx,modem.mdstat ; Port 1 channel A command/status address outch3: in al,dx ; Get RR0 contents and al,SR0_TBUFE ; Transmit buffer empty? jnz outch4 ; Yes, output char loop outch3 ; No, try again jmp outch5 ; Loop counter expired, give up outch4: mov dx,modem.mddat ; Get port 1 channel A data address mov al,ah ; Get the character out dx,al ; Send it pop dx pop cx pop bx jmp RSKP ; Skip return for OK outch5: pop dx pop cx pop bx ret ; Non-skip return due to timeout OUTCHR ENDP SUBTTL Serial port routines -- Input from port ; Port read character. Check the port status. If no data, skip ; return. Else, read in a char and return. PRTCHR PROC NEAR push bx push dx call chkxon mov dx,modem.mdstat ; Port 1 channel A command address prtch1: in al,dx ; Read RR0 contents and al,SR0_RBUFA ; Any characters in receive FIFO? jz prtch4 ; No, exit without waiting mov dx,modem.mddat ; Yes, get port 1 channel A data address in al,dx ; Get the character mov bx,portval cmp [bx].parflg,PARNON ; no parity? je prtch3 ; then don't strip and al,7fh ; else turn off parity prtch3: pop dx pop bx ret prtch4: pop dx ; Here when no character is available pop bx jmp RSKP ; no chars... PRTCHR ENDP ; Local routine to see if we have to transmit an xon CHKXON PROC NEAR push bx mov bx,portval cmp [bx].floflg,0 ; doing flow control? je chkxo1 ; no, skip all this cmp xofsnt,false ; have we sent an xoff? je chkxo1 ; no, forget it mov ax,[bx].flowc ; ah gets xon call outchr ; send it nop nop nop ; in case it skips mov xofsnt,false ; remember we've sent the xon. chkxo1: pop bx ; restore register ret ; and return CHKXON ENDP SUBTTL Serial port routines -- Send a break ; Send a break out the current serial port. Returns normally. SENDBR PROC NEAR push cx push dx push ax xor cx,cx ; Clear loop counter. mov dx,modem.mdstat ; Address channel-A command port mov al,5 ; Point to register 5 out dx,al jmp short $+2 in al,dx ; Get current setting. mov ah,al ; Copy the bits mov al,5 ; Point back to register 5 out dx,al mov al,ah ; Get old bits or al,SW5_BREAK ; Set send-break bit out dx,al ; Start the break pause: loop pause ; Wait a while. mov al,5 ; Point to register 5 out dx,al jmp short $+2 mov al,ah ; Clear send-break bit out dx,al ; Stop the break pop ax pop dx pop cx ret ; And return. ret SENDBR ENDP SUBTTL Serial port routines -- Change baud rate ; Set the baud rate for the current port, based on the value ; in the portinfo structure. Returns normally. ; Called from SET BAUD command with new index in PORT.BAUD, previous in AX DOBAUD PROC NEAR push bx mov bx,portval ;Get pointer mov bx,[bx].baud ;Get new baud-rate index shl bx,1 ;Multiply by 2 cmp BAUDAT[bx],0 ;Test for zero jne dobod1 ;Nonzero is OK mov bx,portval ;Error, get back to data structure mov [bx].baud,ax ;Restore previous baud rate number mov ah,prstr mov dx,offset badbd ;Bad baud rate int dos pop bx ret dobod1: mov ax,BAUDAT[bx] ;Get BRG divisor call SETBAUD ;Send AX to baud-rate-divisor pop bx ret DOBAUD ENDP ;Routine to send AX to the Baud Rate Generator. Preserves all regs SETBAUD PROC NEAR push dx push ax ;Save rate mov dx,modem.mdstat ;Address the channel-A command port mov al,13 ;Point to register 13 out dx,al jmp short $+2 ;Slight delay to let hardware respond mov al,ah ;High-order part of divisor out dx,al jmp short $+2 mov al,12 ;Point to register 12 out dx,al jmp short $+2 pop ax out dx,al ;Low-order part of divisor pop dx ret SETBAUD ENDP ; Get the current baud rate from the serial card and set it ; in the portinfo structure for the current port. Returns normally. ; This is used during initialization. GETBAUD PROC NEAR mov dx,modem.mdstat ;Address channel-A command port mov al,13 ;Point to register 13 out dx,al jmp short $+2 ;Small delay in al,dx ;Read RR13 mov ah,al ;Save high-order part mov al,12 ;Point to register 12 out dx,al jmp short $+2 in al,dx ;Read RR12 ;Baud rate = (300*256)/(AX+2) mov bx,0 ;Index value getbd1: cmp ax,BAUDAT[bx] ;See if known value je getbd2 ;Found it add bx,2 ;Point to next word cmp bl,BAUDLEN ;End of table? jl getbd1 ;No, keep looking mov bx,B1200*2 ;Yes, force it to 1200 baud mov ax,BAUDAT[bx] call SETBAUD getbd2: mov ax,bx ;Get the byte index shr ax,1 ;Reduce to number from 0 to 15 mov bx,portval ;Point to structure mov [bx].baud,ax ;Store where SHOW processor can see it ret GETBAUD ENDP SUBTTL Machine-dependent screen update routines ;============================================================================ ; Screen handling routines ;============================================================================ ; Delete a character from the terminal. This works by printing ; backspaces and spaces. Returns normally. DODEL PROC NEAR mov ah,prstr mov dx,offset delstr ; Backspace-space-backspace int dos ret DODEL ENDP ; Move the cursor to the left margin, then clear to end of line. ; Returns normally. CTLU PROC NEAR mov ah,prstr mov dx,offset clrlin ;Output CR, then clear to end of line int dos ret CTLU ENDP ; Clear to the end of the current line. Returns normally. CLEARL PROC NEAR mov ah,prstr mov dx,offset clreol ;Erase from cursor position to end of line int dos ret CLEARL ENDP ; This routine blanks the screen. Returns normally. CMBLNK PROC NEAR mov ah,13h ;Function 13h of INT 49h clears the screen int 49h ret CMBLNK ENDP ; Produce a short beep. The PC DOS bell is long enough to cause a loss ; of data at the port. Returns normally. BEEP1 PROC NEAR mov ah,SPK_FREQ ; Set speaker frequency mov cx,1000 ; Approx 1.5 kHz int SPK_INT ret BEEP1 ENDP BEEP PROC NEAR call BEEP1 ; Set the frequency mov ah,SPK_BEEP ; Timed beep function mov al,5 ; 5/40 = 1/8 second int SPK_INT ret BEEP ENDP ; Homes the cursor. Returns normally. LOCATE PROC NEAR mov dx,0 ; Go to top left corner of screen. jmp poscur LOCATE ENDP ; Write a line at the bottom of the screen... ; the line is passed in dx, terminated by a $. Returns normally. PUTMOD PROC NEAR push dx ; preserve message mov dx,24*100h ; now address line 24 call poscur mov dx,offset invvid mov ah,prstr int dos ;Set inverse video pop dx ; get message back mov ah,prstr int dos ; write it out mov dx,offset norvid mov ah,prstr int dos ;Normal video ret ; and return PUTMOD ENDP ; Clear the mode line written by PUTMOD. Returns normally. CLRMOD PROC NEAR mov dx,1800h call poscur ; Go to bottom row. call clearl ; Clear to end of line. ret CLRMOD ENDP ; Put a help message on the screen. ; Pass the message in ax, terminated by a null. Returns normally. PUTHLP PROC NEAR push ax ; preserve this mov ah,prstr mov dx,offset crlf int dos pop si ; point to string again puthl3: lodsb ; get a byte cmp al,0 ; end of string? je puthl4 ; yes, stop mov dl,al mov ah,dconio int dos ; else write to screen jmp puthl3 ; and keep going puthl4: mov ah,prstr mov dx,offset crlf int dos ret PUTHLP ENDP ; Position the cursor according to contents of DX: ; DH contains row, DL contains column. Returns normally. POSCUR PROC NEAR mov al,dh ;Get row inc al ;Top row is row #1, not zero aam ;ah gets tens, al gets units add ax,'00' ;Convert to ASCII mov rowhi,ah ;Store in ESCape sequence mov rowlo,al mov al,dl ;Get column inc al aam add ax,'00' mov colhi,ah mov collo,al mov ah,prstr mov dx,offset posseq ;Output ESC,'[',row,';',col,'H' int dos ret POSCUR ENDP SUBTTL TEKTRONIX-4010 emulation ;**** NOTE: This version of TERM really belongs in MSCOMM.ASM **** TERM PROC NEAR mov si,ax ; this is source mov di,offset ourarg ; place to store arguments mov ax,ds mov es,ax ; address destination segment mov cx,size termarg rep movsb ; copy into our arg blk call TERMINI ; Set 25th line, graphics bright ; Get a character from the modem, send it to the screen term1: call INMODEM ; Input from modem jmp short term2 ; No input available nop ; 3rd byte push ax call TERMEMU ; Call terminal emulation routines pop ax test ourarg.flgs,capt ; capturing output? jz term2 ; no, forget it call ourarg.captr ; else call the routine ; Get character from the keyboard, send it to the modem port term2: call INKEYB ; Get char from keyboard (with translation) jmp short term1 ; No input available nop ; 3rd byte cmp al,ourarg.escc ; Match our escape character? je term3 ; yes, exit call OUTMODEM ; output the character test ourarg.flgs,lclecho ; echoing? jz term1 ; no, continue loop push ax call TERMEMU pop ax and al,7Fh ; Ignore parity cmp al,CR ; Was the RETURN key pressed? jne term1 mov al,LF ; Yes, echo a linefeed to the screen call TERMEMU jmp term1 term3: call TERMEND ; Undo line 25 or graphics ret TERM ENDP ;**** NOTE: This version of TERM really belongs in MSCOMM.ASM **** ;Routine to make graphics more visible. ;For a 1-plane monochrome display, draw bright lines on a black background ;For a 3-plane color display, draw green lines on a black background ;(It is better to use only one color on a color monitor, so as to avoid ;any problems if the convergence is not exact.) ;Line 25 is not given any special treatment. TERMINI PROC NEAR mov si,offset pal3pln ;New palette if 3 planes test sysdata,SYS_GRFC ;Graphics plane C installed ? jnz termin1 ;Yes mov si,offset pal1pln ;No, only single plane graphics termin1:call palette ;Set up so that color 1 is more visible ret TERMINI ENDP ;Routine to make graphics dimmer. ;For a 1-plane monochrome display, graphics will be very dim ;For a 3-plane color display, graphics will be blue (text will be white) ;Line 25 is not given any special treatment TERMEND PROC NEAR mov si,offset palnorm ;Reset to normal palette call palette ret TERMEND ENDP ;Routine to input a character from the keyboard with translation. ;Skip return if input was available, character in AL. INKEYB PROC NEAR ;Input from the keyboard mov ah,dconio mov dl,0ffh int dos jc inkey1 ;Carry set if no character available and al,7Fh ;No meta characters (yet) je inkey1 ;*HACK* No char if null jmp RSKP ;Skip return of char is available inkey1: ret ;Error return if no input INKEYB ENDP ;Routine to output character in AL to the screen. OUTSCRN PROC NEAR ;Output one character to the screen mov dl,al mov ah,conout int dos ; go print it ret OUTSCRN ENDP ;Routine to input a character from the modem port. ;Skip return if input was available, character in AL. INMODEM PROC NEAR ;Input from the modem call PRTCHR jmp RSKP ;Skip return if char is available ret INMODEM ENDP ;Routine to output character in AL to the modem port. OUTMODEM PROC NEAR ;Output one character to the modem push ax ;Preserve character in AL mov ah,al call OUTCHR ;Output char in AH nop ;Ignore non-skip return nop nop pop ax ret OUTMODEM ENDP ;Routine to draw a line on the screen, using TEKTRONIX coordinates. ;X coordinate in AX, 0=left edge of screen, 1023=right edge of screen. ;Y coordinate in BX, 0=bottom of screen, 779=top of screen. ;Visiblity flag in CL, 0=move invisible, 1=draw a line. ;The TI-PRO has (719,299) as the coordinate of the lower-right corner. ;Calculate endpoint X=(9/13)*(HIX*32+LOX), Y=299-(5/13)*(HIY*32+LOY) ;The IBM-PC has (639,199) as the coordinate of the lower-right corner. ;Calculate endpoint X=(12/20)*(HIX*32+LOX), Y=199-(5/20)*(HIY*32+LOY) TEKDRAW PROC NEAR imul xmult ; Multiply by 9 idiv xdiv ; Divide by 13 push ax ; X is now between 0 and 708 mov ax,bx imul ymult ; Multiply by 5 idiv ydiv ; Divide by 13 mov bx,ybot ; Y is now between 0 and 299 sub bx,ax ; Put new Y in right reg pop ax ; Put new X in right reg mov si,oldx ; Previous position mov di,oldy mov dl,cl ; Draw a line in 1 plane if DL=1 or dl,80h ; Use fast line drawing routine call LINE mov oldx,si ; Update position mov oldy,di ret TEKDRAW ENDP ;Routine to trigger the crosshairs, wait for a key to be struck, and send ;5 byte out the modem port. CROSHAIR PROC NEAR ret CROSHAIR ENDP SUBTTL Screen routines -- Graphics ;Note: All arguments to these 3 routines are passed in the registers. public CLS, PALETTE, LINE ;============================================================================== ; CLS Subroutine to clear the screen. Call with 0 in AL to clear both, ; 1 to clear graphics only, 2 to clear text only. ;============================================================================== CLS PROC NEAR ;0=both, 1=graphics, 2=text push ax test al,1 ;CLS 1 does not clear text jnz cls1 mov ah,13h ;CLS 0 or CLS 2 clears text screen int 49h cls1: pop ax test al,2 ;CLS 2 does not clear graphics jnz cls2 mov ah,14h ;CLS 0 or CLS 1 clears graphics screen int 49h cls2: ret CLS ENDP ; Colors 0=Black, 1=Blue, 2=Red, 3=Magenta, 4=Green, 5=Cyan, 6=Yellow, 7=White planea equ 0C000h ;1st graphics plane (blue) planeb equ 0C800h ;2nd graphics plane (red) planec equ 0D000h ;3rd graphics plane (green) ; The colors listed above are assuming that the PALETTE is not changed. latchs equ 0DF00h ;Segment number of color latches latchb equ 00010h ;Blue output latch latchg equ 00020h ;Green output latch latchr equ 00030h ;Red output latch palblue equ 10101010b ;Default blue latch palgren equ 11001100b ;Default green latch palred equ 11110000b ;Default red latch ;============================================================================== ; PALETTE Subroutine to change the color palette (ala BASIC) ; Call with DS:SI pointing to 8 bytes defining the new colors ; Preserves all but AX,SI. ;============================================================================== PALETTE PROC NEAR push bx push cx mov bx,0 ;Start at 1st byte mov ah,0 ;Code for blue latch mov cx,0 ;Code for red and green latches palet1: mov al,CS:PALBITS[bx] ;Bit to be set test byte ptr [bx+si],01h ;Check blue component of this color jz palet2 or ah,al ;Set the bit palet2: test byte ptr [bx+si],02h ;Check red component jz palet3 or ch,al ;Set the bit palet3: test byte ptr [bx+si],04h ;Check the green component jz palet4 or cl,al palet4: shl al,1 ;Do next bit add bx,1 ;Point to next input data byte cmp bl,8 ;Done all 8? jl palet1 push ds mov bx,latchs ;Address the latch segment mov ds,bx mov DS:[latchb],ah ;Set the hardware latches mov DS:[latchg],cl mov DS:[latchr],ch pop ds pop cx pop bx ret PALBITS db 01h,02h,10h,20h,04h,08h,40h,80h ;Red & Green bits swapped PALETTE ENDP ;============================================================================== ; LINE Subroutine to plot a line with endpoints in BX,CX and SI,DI. The method ; used is an adaptation of the octantal dynamic differential analyzer(DDA). ; ; Registers at CALL Registers on return ; ----------------- ------------------- ; SI=Start X coord SI=End X coord (start for next time) ; DI=Start Y coord DI=End Y coord ; AX=End X coord AX=garbage ; BX=End Y coord BX=garbage ; CX=anything CX=unchanged (for loop counter) ; DX=Color code, 0-7 or 80-87 DX=unchanged ; BP,SP,CS,DS,ES,SS are all unchanged ; ; I considered returning meaningful data in AX and BX (such as the last bit ; and word address drawn), but that is complicated by the fact that the lines ; are always drawn left to right. ;============================================================================== LINE proc near push ax ;End coords in (AX,BX) will be returned push bx ; in (SI,DI) push cx ;Preserve CX,BP,DS push bp push ds ; call clip ;Clip line to fit in screen bounds ; jnz done ;Jump if line is on screen cmp ax,si ;Compare X1 to X2 jl plusx ;Jump if X1 is to left of X2 xchg ax,si ;Swap points so point 1 is to left xchg bx,di ; This mirrors quadrants 2,3 to 1,4 plusx: sub si,ax ;Get delta X into SI sub di,bx ;Get delta Y into DI ; Left-hand coordinate in (AX,BX), delta movement in (SI,DI) ; Map X1,Y1 in AX,BX to an offset into the video buffer in BX and bit pos in AX shl bx,1 ;2*Y shl bx,1 ;4*Y mov bp,bx ;Save 4*Y shl bx,1 ;8*Y shl bx,1 ;16*Y shl bx,1 ;32*Y add bp,bx ;DX = 36*Y shl bx,1 ;64*Y shl bx,1 ;128*Y sub bx,bp ;128Y - 36Y = 92*Y mov cl,al ;Low 4 bits of X position and cl,0Fh shr ax,1 ;Divide by 8 bits per byte shr ax,1 shr ax,1 and ax,0fffeh ;Truncate down to word boundary add bx,ax mov ax,8000h ;Start with set bit on left edge shr ax,cl ;Shift it over the correct amount ;AX has bit in position, BX has word address, SI has delta-X, DI has delta-Y mov bp,92 ;Offset from 1 pixel to one below it or di,di ;See if delta y is below zero jg quad3 ;Yes, already on quadrant 3 neg di ;Get absolute value of delta y neg bp ;Move toward top of screen quad3: test dl,1 ;Want color 1? jz try2 ;No mov cx,planea ;Yes, do BLUE call line1 try2: test dl,2 ;Want color 2? jz try3 ;No mov cx,planeb ;Yes, do RED call line1 try3: test dl,4 ;Want color with this bit on? jz lindone ;No mov cx,planec ;Yes, do GREEN call line1 lindone:pop ds pop bp pop cx pop di ;Return end points (formerly in AX,BX) pop si ; in (SI,DI) ret ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; line1: mov ds,cx ;Segment for video buffer push ax ;Starting bit position push bx ;Starting address push dx ;Color bits (SI and DI not modified) cmp di,si ;Compare delta-Y with delta-X jg line1a ;Greater than +/- 45 degrees call line2 ;Flat line, count with delta-X jmp short line1b line1a: call line3 ;Steep line, count with delta-Y line1b: pop dx pop bx pop ax ret ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; ; Here when slop is less than +/- 45 degrees line2: mov cx,si ;Number of pixels to plot = delta x inc cx ; + 1 mov dx,si ;Initialize line error to -(deltax)/2 shr dx,1 ; neg dx ; line2a: or [bx],ax ;Turn on pixel pointed to by BX and Al ror ax,1 ;Increment X direction jnc line2b ; add bx,2 ; line2b: add dx,di ;Add delta y to line error jl line2c ;Jump for next pixel if error < 0 add bx,bp ;Go up (or down) one pixel sub dx,si ;Subtract delta x from line error line2c: loop line2a ;Set next pixel ret ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; ; Here when slope is greater than +/- 45 degrees line3: mov cx,di ;Number of pixels to plot = delta y inc cx ; + 1 (Delta Y was negated above) mov dx,di ;Initialize line error to -(deltay)/2 shr dx,1 ; neg dx ; line3a: or [bx],ax ;Turn on pixel pointed to by BX and Al add bx,bp ;Move up (or down) 1 pixel add dx,si ;Add delta x to line error jl line3c ;Jump for next pixel if error < 0 ror ax,1 ;Time to increment X direction jnc line3b ; add bx,2 ; line3b: sub dx,di ;Subtract delta y from line error line3c: loop line3a ;Set next pixel ret LINE endp SUBTTL Interface to KERMIT's command parser ;============================================================================ ; General KERMIT or MS-DOS routines. ;============================================================================ ; this is called by Kermit initialization. It checks the ; number of disks on the system, sets the drives variable ; appropriately. Returns normally. DODISK PROC NEAR mov ah,gcurdsk ; Current disk value to AL. int dos mov dl,al ; Put current disk in DL. mov ah,seldsk ; Select current disk. int dos ; Get number of drives in AL. mov drives,al ret DODISK ENDP ; Initialize variables to values used by the TI PROFESSIONAL version. LCLINI PROC NEAR int SYS_INT ;Get system configuration info mov sysdata,ax ;Bit mask of installed devices mov syssize,bx ;Size of RAM call BEEP1 ;In case BASIC left the speaker messed up mov flags.vtflg,0 ;HEATH-19 emulation is off ret LCLINI ENDP ; Get a file handle for the communications port. Use DOS call to get the ; next available handle. If it fails, ask user what value to use (there ; should be a predefined handle for the port, generally 3). The open ; will fail if the system uses names other than "COM1" or "COM2". OPNPRT PROC NEAR ret OPNPRT ENDP SHOWKEY PROC NEAR mov ax,offset shkmsg mov cx,shklen ret SHOWKEY ENDP ; Set heath emulation on/off. Called from SET TERMINAL-EMULATION command VTS PROC NEAR mov dx,offset termtab mov bx,0 mov ah,cmkey call comnd ;Keyword, HEATH-19, VT102, ADM3A, or OFF jmp r push bx mov ah,cmcfm call comnd jmp short vt0 nop pop bx mov ax,0[bx] ; Get the control table address mov CTLTAB,ax mov al,2[bx] ; Get terminal type mov flags.vtflg,al add bx,2+8 ; Get addr of ID sequence mov IDSEQ,bx ret vt0: pop bx ret VTS ENDP notimp: mov ah,prstr mov dx,offset noimp int dos jmp prserr ; Set the current port. Called from SET PORT command COMS PROC NEAR mov dx,offset porttab mov bx,0 mov ah,cmkey call comnd jmp r push bx mov ah,cmcfm call comnd ; Get a confirm. jmp comx ; Didn't get a confirm. nop call SERRST ; Reset previous serial port pop bx mov flags.comflg,bl ; Set the comm port flag. ;**** According to the MSXSYS.DOC, flags.comflg is supposed to be 0 ;**** when using port 2. This makes it difficult to use ports 3 and 4. cmp flags.comflg,1 ;Port 1? jne coms2 mov ax,offset port1 mov portval,ax mov modem.mddat,SCC1_ADAT ;Data reg mov modem.mdstat,SCC1_ACMD ;Channel A command/status mov modem.mdcom,SCC1_BCMD ;Channel B command/status call SERINI ret coms2: cmp flags.comflg,2 ;Port 2? jne coms3 mov ax,offset port2 mov portval,ax mov modem.mddat,SCC2_ADAT ;Data reg mov modem.mdstat,SCC2_ACMD ;Channel A command/status mov modem.mdcom,SCC2_BCMD ;Channel B command/status call SERINI ret coms3: cmp flags.comflg,3 ;Port 3? jne coms4 mov ax,offset port3 mov portval,ax mov modem.mddat,SCC3_ADAT ;Data reg mov modem.mdstat,SCC3_ACMD ;Channel A command/status mov modem.mdcom,SCC3_BCMD ;Channel B command/status call SERINI ret coms4: mov ax,offset port4 ;Port 4 mov portval,ax mov modem.mddat,SCC4_ADAT ;Data reg mov modem.mdstat,SCC4_ACMD ;Channel A command/status mov modem.mdcom,SCC4_BCMD ;Channel B command/status call SERINI ret comx: pop bx ret COMS ENDP ; Jumping to this location is like retskp. It assumes the instruction ; after the call is a jmp addr. RSKP PROC NEAR pop bp add bp,3 push bp ret RSKP ENDP ; Jumping here is the same as a ret. R PROC NEAR ret R ENDP code ends end