home
***
CD-ROM
|
disk
|
FTP
|
other
***
search
/
Between Heaven & Hell 2
/
BetweenHeavenHell.cdr
/
300
/
257
/
msxtipro.asm
< prev
next >
Wrap
Assembly Source File
|
1984-12-07
|
63KB
|
1,572 lines
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 <SCC1_ADAT,SCC1_ACMD,SCC1_BCMD>
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