home
***
CD-ROM
|
disk
|
FTP
|
other
***
search
/
Columbia Kermit
/
kermit.zip
/
bbcmicro
/
bbcker.asm
< prev
next >
Wrap
Assembly Source File
|
2020-01-01
|
284KB
|
15,368 lines
*******************************************************************************
*
* Kermit for BBC Micros version 1.45
* ----------------------------------
*
* This file is a concatenation of the separate source file for BBC Kermit. In
* order to assemble the source, you will need to split it into its separate
* files: the split points are marked in this file with lines of the form
*
* ****** File <name> *******************
*
* See file BBCKERMIT.DOC for details of how to arrange the separate files on
* disc ready for assembly.
*
* This release can be assembled with either the commercially available ADE
* assembler, or, for preference, the free assembler supplied with BBC Kermit.
* See file BBCASM.ANN for details of this.
*
*****************************************************************************
****** File BBCMIT *************************************************************
SKP H
* BBCMIT: Updated 24/02/87 @ 1200
OFF EQU 0 ;these are defined in case the Lancaster 65C02
ON EQU 1 ;assembler is used rather than ADE
MARK EQU 1 ;mark number
VERSION EQU 45 ;version number
LEVEL EQU -1 ;development level (-1 for release version)
LST OFF
Y EQU -1 ;flags for IF
N EQU 0
D EQU -1
G EQU -1
S EQU 0
ADE QUERY 'Using ADE (Y/N)'
IF ~ADE
SFCOND
FI
ROM QUERY 'Build ROM version (Y/N)'
RAM EQU ~ROM
ONEDRV QUERY 'All files on one disc surface (Y/N)'
IF ~ONEDRV
DSDRIV QUERY '1 D/S drive (D) or 2 S/S (S)'
FI
LIST QUERY 'Listing required (Y/N)'
IF LIST
LFULL QUERY 'Global or selective (G/S)'
LST ON
IF ADE
PAGE 88
ELSE
PAGE 88,132
FI
SYSVDU 1,15,1,27,1,48
IF ROM
TTL 'BBC Kermit (ROM)'
ELSE
TTL 'BBC Kermit (RAM)'
FI
ELSE
LFULL EQU N
FI
IF ~LFULL
LST OFF
FI
*******************************************************************************
*
* KERMIT FOR BBC MICRO
* ====================
*
* This program implements the KERMIT protocol for an Acorn BBC microcomputer,
* and is compatible with models B, B+, B+128, Master 128 and Master Compact.
* It is not Tube compatible, and any second processor attached must be turned
* off.
*
* The source is written to be assembled with the Lancaster 65C02 Assembler,
* supplied free with the Kermit files on disc or from the Lancaster Distribution
* service. It can also be assembled with the commercially-available ADE system
* (version 2.02 or later) which can be bought from SYSTEM, Collegiate Crescent,
* Sheffield, UK (See Acorn User magazine for adverts). The User Guide gives
* full details of the assembly process for both assemblers.
*
* This implementation, begun in February 1985, is by Alan Phillips of the
* Department of Computing, Lancaster University. Copyright is retained on the
* program, but it is of course freely available under the standard terms for
* distributing Kermit. You are encouraged to pass the source and compiled forms
* on to others, but they must not be sold (other than to cover media and moderate
* handling charges)
*
* We are always pleased to receive comments, suggestions and bug reports, and
* we will produce bug-fix releases when necessary. The contact addresses are
* given below.
*
* Lancaster University Computing Department also run the UK Kermit Distribution
* Service, through which you can obtain copies of Kermit for over 200 different
* machine/system combinations. Enquiries are welcome, but please note that,
* apart from this BBC implementation, we do not supply any Kermits outside the
* UK and Eire.
*
* Postal Address : Kermit Distribution,
* Department of Computing,
* Computer Centre,
* Lancaster University,
* Lancaster LA1 4YW
*
* Telephone : (0524) 65201 x 4881
*
* Electronic mail : SYSKERMIT @ LANCS.VAX1
* (JANET address 000010404000.FTP.MAIL,
* PSS address 234252400101.000010404000.FTP.MAIL)
*
* (Note that these addresses use Grey Book X25 mail: we
* have no Telecom Gold or Prestel mailboxes. We also
* cannot respond to Telex messages)
*
*
* Thanks are due to:
*
* Dave Osborne University of Nottingham
* Derek Dongray University of Manchester
* Alwyn Breame AFRC Computer Centre
* Bertil Schou Loughborough University
* Peter O'Kane University College, Galway
* Dave Morriss Heriot-Watt University
* Colin Allison
* Mike Whitehead Dundee University
* Mario Palencia
* Chris Kennington University College London
* Brian Robinson
* Dan Shapiro
* Barry Forde Lancaster University
* Neil Mercer Lancaster ITEC
* Andrew Cole Leeds University
* Tim Green Warwick University
* John Linn Aberdeen University
* Tom Wilson UMRCC
* Peter Hearne Online Computer Supplies Ltd
* Thomas Sippel-Dau Imperial College
* Icarus Sparry Bath University
* Ian O'Brien Central London Polytechnic
* Bob Dixon Beaumont Hospital Lancaster
* Peter Vince BBC Telesoftware
* Alan Baker Viewfax Ramlink
* Peter Vince BBC Telesoftware
* Mike Brudenell Newcastle University
*
* and others for comments, contributions and suggestions. Apologies to those
* whose names I have omitted.
*
* The KERMIT protocol is Copyright (C) The Trustees of Columbia University 1987
*
*
* VERSION HISTORY
* ---------------
*
* 1.45 Bug fixed to allow talking to servers when 8-bit-prefix is not in use
* ASCII version number placed in ROM header
* 1.44 B7 stripped before terminal mode bytes displayed
* 8th-bit-prefixing and quoting done correctly in C and G packets
* Wildcard search no longer sends sub-directories as files
* Command screen banner title altered to "BBC Micro Kermit"
* Password sent correctly in REM CWD
* 1.43 Handles quote char correctly on 8 bit data path
* 1.42 RAM version uses shadow mode on B+ and Master
* VT52 supported in RAM version on B+ and Master as default
* Master 128 keypad used in VT52 mode
* Code added for support of Terminal Extension ROM
* RAM version ORG moved to $1F00 for ADFS on B and B+
* DFS 2.24 "close all files" bug avoided
* VT52 graphics chars set with VDU 23 rather than block move
* File renaming adjusted for ADFS compatibility
* ROM header adjusted to be correct on Master
* Parallel printer no longer forced
* SET TERMINAL replaces SET VT52 and SET VDU-WIDTH
* Entry no longer closes all files, allowing !BOOT usage
* CLOSE command now closes all open files
* C introduced as explicit synonym for CONNECT
* Code adjusted to allow *EXEC files to be used cleanly
* User vectors removed
* Minor code corrections and compactions made
* CONTROL-BREAK now exits RAM version
* RAM version changes restart mode to 7 to stop self-corruption
* Received EOF(D) and ACK(X/Z) packets correctly handled
* File name generation uses length to suit current FS
* OSHWM set to point above RAM version image
* File name sent by remote can be used untranslated
* *HELP handling tidied up
* Code for sending line break rewritten
* TRANSMIT command allows raw upload of files to host
* Default timeouts changed to 15 seconds for MULTICS sites
* Long break function added in terminal mode
* Talks to servers that don't support I packets
* Table-size bug in FIX command cleared
* Sources made compatible with Lancaster 65C02 Assembler
* OSBYTE 3 calls for printer select/deselect corrected
* 1.33 OS1.20 bug in reverse screen scroll circumvented
* VT52 ESCAPE codes echoed correctly in half-duplex mode
* Function keys reset correctly on OS command or EXIT
* Pad chars ignored before end-of-packet marker
* 1.30 Conditionals added to build RAM-based version
* All VT52 keypad keys correctly emulated
* WIDTH command selects 40/80 byte command screen
* Status line added in 80 character teminal modes
* Function keys generate strings in terminal and command mode
* Cursor editing allowed in command mode
* Compilation facilities enhanced
* Messages tokenised and improved
* Command analyser error handling improved
* Pause key added in terminal mode
* Cursor edit mode added in terminal handler
* Code for talking to servers rewritten
* Init-info packets sent to servers
* REMOTE command added
* SET HANDSHAKE added to allow use with IBM systems
* Code extensively tidied up
* VT52 graphics characters supported
* SET RETRIES command added
* SET LOCAL-ESCAPE removed as obsolete
* Timer code rewritten
* File transfers can now be routed to printer
* Local filenames no longer forced to upper case
* Printmaster interaction with events catered for
* Non-shadow mode selected if run on a B+
* 1.02 CTS/RTS flow control now works
* FIX command added to save defaults in sideways RAM
* Help trigger character configurable with SET HELP-TRIGGER
* SET MUX-WAIT command added
* Comms routines directed via vectors
* VDU mode may ignore one specified character
* LF in terminal mode correctly sent to printer
* Terminal mode redesigned to use lower 24 lines for VT52
* *TV done before entering terminal mode, configurably
* VT52 escape handling tidied up
* Command tables re-ordered for neater autohelp display
* Wait-for-XON now does not stop IRQ
* Wildcard file search now works with NFS
* Error trapping changed in initialisation phase
* WAIT and DISPLAY commands added
* Text colour configurable for terminal mode
* Improved ways out of TAKE files
* Number of timeouts displayed
* Comms not lost when ESCAPE in OS command
* 0.53 Initial release
*
* For up-to-the-minute news on BBC KERMIT see the bulletin files on the
* Lancaster VAX 11/780. Bug reports and news of further releases will
* be maintained there, as well as a total set of all
* known KERMIT implementations. Contact the above for details.
*
****************************************************************************
***************************************
*
* MACRO DEFINITIONS
* =================
*
***************************************
* Macro to build entries in command/parameter tables
IF ADE
CMD MACRO
DFB @1
ASC @2
ENDM
ELSE
CMD MACRO
DFB @1
ASC '@2'
ENDM
FI
* Macro to chain to next source. Note that ADE bugs cause the
* filename to be shown twice when this is used,
* and the technique to fail if NOT in a macro!
* It's OK on the Lancaster assembler.
NEXT MACRO
IF ONEDRV
CHN @1
ELSE
IF DSDRIVE
CHN :2.@1
ELSE
CHN :1.@1
FI
FI
ENDM
* Macro to start each file and set list level up
* First parameter must be the last 3 characters of the filename
START MACRO
IF LFULL!LST@1&LIST
LST ON
SKP H
ELSE
LST OFF
FI
ENDM
* Macro to build table for the high bytes
* of message addresses. This exists as a
* list of message numbers, each being the
* first message in a new page, relative to
* the page message 0 starts in. For
* message n the call will be
* MTHE n-1,n
MTHE MACRO
IF (<M@2)>(<M@1)
DFB @2
FI
ENDM
***************************************
*
* LISTING CONTROL FLAGS
* =====================
*
* For each file there must be one flag
* of name "LST" followed by the last 3 bytes of
* the filename. If selective listing is
* selected, only those files with flags
* set to 'Y' will be listed. Those with flags
* set to 'N' will not be listed. Global
* listing overrides all flags.
*
***************************************
LSTDEF EQU N
LSTWKS EQU N
LSTMAI EQU N
LSTCPR EQU N
LSTCMD EQU N
LSTGEN EQU N
LSTST1 EQU N
LSTST2 EQU N
LSTSHW EQU N
LSTREC EQU N
LSTSND EQU N
LSTCOM EQU N
LSTTM1 EQU N
LSTTM2 EQU N
LSTPM1 EQU N
LSTPM2 EQU N
LSTPM3 EQU N
LSTFIL EQU N
LSTSB1 EQU N
LSTSB2 EQU N
LSTSB3 EQU N
LSTSB4 EQU N
LSTTX1 EQU N
LSTTX2 EQU N
LSTXXX EQU N ;for symbol table
CHN BBCDEF
****** File BBCCMD *************************************************************
START CMD
* BBCCMD: Updated 24/06/86 @ 1530
***************************************
*
* RECEIVE
* =======
*
* Waits for remote to give us a file
*
***************************************
RECEIVE EQU *
*
* Note this is RECEIVE and not GET
*
LDA #0
STA WORK9
*
* Assume for a bit that no local name is given
*
K1RECV EQU *
LDA #0
STA LFGIVEN ;assume not there for now
STA WAY ;set direction to RECEIVE
*
* Is destination FILE, MEMORY or PRINTER here?
*
LDA DESTIN
BEQ REC100 ;j if FILE
JSR LFDUMMY ;else we fake local name
JMP REC400 ;and no params allowed
*
* Here destination is FILE, so param 1 is optional local name
*
REC100 LDA #33 ;select help text
JSR GETFN ;get param and check size
BCS REC400 ;j if param not there
*
* User has given a local filename so copy to a buffer, adding a CR at the end
*
INC LFGIVEN ;note local name given
LDY #0
REC200 LDA (CURPAR),Y ;get a byte
STA LFNAME,Y ;store it
INY
CPY CURLEN
BNE REC200
LDA #$0D ;add a CR
STA LFNAME,Y
*
* Make sure no more params given
*
REC400 JSR CONFIRM
*
* Now put up the status screen and display the remote filename if we have one
*
JSR STATUS ;also clears counts
LDA #49
JSR MESS ;option is 'receive'
BIT WORK9 ;are we RECEIVE?
BPL REC420 ;j if so - no remote name yet
JSR DISRFN ;else display it
*
* And display the local name if we have one
*
REC420 LDA LFGIVEN
BEQ REC600 ;j if not given
JSR DISLFN ;else display it
*
* Then note no file is yet open
*
LDA #0
STA FHAND
*
* Now we branch, depending on whether we're RECEIVE or GET
*
REC600 BIT WORK9
BPL REC620 ;j if RECEIVE - we just wait
*
* Here we're a GET command, so we send an R command to the server
*
LDA #'R' ;packet type is R
JSR INSCMD ;prepare server command
LDA WORK6 ;and set the real packet data legth up
STA TXDLEN ;as set by GET command processor
SEC ;we want an 'I' packet exchange
JSR SRV100 ;and fire it
JMP REPORT ;then report success
*
* Now the receive state switcher takes over to do the hard bits
*
REC620 LDA #'R' ;initial state is REC_INIT
JSR RECSW ;into the state handler
JMP REPORT ;and report success
*
* Here user gave no filename parameters, so he's not talking to a server.
* The other end will be sending us a S command shortly
*
REC700 JSR STATUS ;put up status screen and clear counts
JMP REC620 ;and enter state switcher
*
*
* Side entries
* ------------
*
RCVST EQU K1RECV
***************************************
*
* SEND
* ====
*
* Transmits a file to the remote system
*
***************************************
SEND LDA #1
STA WAY ;note direction is SEND
IF ROM
*
* Is the source FILE or MEMORY here?
*
LDA SOURCE
BEQ SND020 ;j if FILE
*
* Source is MEMORY, so param 1 is mandatory remote name
*
JSR LFDUMMY ;fake matching local name as <MEMORY>
LDA #32 ;select help text
JSR GETMPAR ;get the parameter
JMP SND280
FI
*
* Source is FILE here, so param 1 is mandatory local name
*
SND020 LDA #33 ;select help text
JSR GETMFN ;get param and check size
*
* We have a name, so copy it to a buffer and add a CR to the end, watching for wildcards
*
SND060 LDY #0
STY WCLEN ;assume no wildcards
SND100 LDA (CURPAR),Y ;get a byte
STA LFNAME,Y ;note it
INY
CMP #'*' ;is it a multichar wildcard?
BEQ SND110 ;j if it is
CMP #'#' ;is it a singlechar wildcard?
BNE SND120 ;j if not
SND110 STY WCLEN ;else note position
SND120 CPY CURLEN ;have we reached end?
BNE SND100 ;j if not
LDA #$0D ;else add a CR
STA LFNAME,Y
*
* Note the length for later use
*
LDA CURLEN
STA LFNLEN
*
* If name was wildcarded, we'll take another copy for the catalog scanning
* later on
*
LDY WCLEN
BEQ SND250 ;j if no wildcards
SND190 STA WCLEN ;else save length of name
LDY #0
SND200 LDA LFNAME,Y ;else copy over
STA WCNAME,Y
INY
CPY WCLEN
BNE SND200
*
* Then set up the control block for the OSGBPB call to scan the
* catalog
*
LDA #0
STA GNXBLK
STA GNXBLK+9
STA GNXBLK+10
STA GNXBLK+11
STA GNXBLK+12
*
* And see if we can find at least one file to match the wildcard name
*
JSR GNXTFIL
BCS SND920 ;j if none - can't do a send
*
* Parameter 2 is optional and is the remote filename
*
SND250 LDA #32 ;select help text
JSR GETFN ;get param and check size
BCS SND400 ;j if absent
*
* Here the user has supplied a remote filename. Copy to our buffer and add a CR
*
SND280 LDY #0
SND300 LDA (CURPAR),Y ;get a byte
STA RFNAME,Y ;store it
INY
CPY CURLEN
BNE SND300
LDA #$0D ;and add a CR
STA RFNAME,Y
*
* Then we go to do the display
*
JSR CONFIRM ;no more parameters
JMP SND500
*
* Here user didn't give a remote name, so we generate one.
*
SND400 LDY LFNLEN ;offset to final CR
JSR MKRNAME
*
* Now put up the status screen and display the local filename
*
SND500 JSR STATUS ;also clears counts
LDA #50
JSR MESS ;option is 'send'
JSR DISLFN ;display local file name
SND520 JSR DISRFN ;display remote filename
*
* Now mark no files are open, and delay for the specified period
* to let user set up the other end
*
LDA #0
STA FHAND ;no file open
LDA #59
JSR PRTSST ;set status to 'pausing'
LDA DELAY
JSR WAIT ;and wait a bit
*
* All ready, so off to the state switcher
*
JSR SENDSW ;into state switcher
JMP REPORT ;report the result
*
* Here no files satisfied the wildcard name
*
SND920 BRK
DFB 0
ASC 'No matches'
DFB 0
***************************************
*
* LOGGING
* =======
*
* Starts/stops logging of terminal
* session
*
***************************************
LOG EQU *
*
* First parameter must be ON or OFF
*
JSR ONOFPAR ;get it in
CMP #1
BEQ LOG500 ;j if it's ON
*
* It's logging OFF, so tidy file if it's open
*
JSR CONFIRM ;check no more parameters given
LOG200 LDY LHAND ;get handle of file
BEQ LOG900 ;j if not open - null call
*
* Make sure the buffer is written to the file
*
LDA LOGCNT ;get count of bytes in it
BEQ LOG400 ;j if buffer empty
JSR WLOGB ;else write to disc
*
* Then close the file
*
LOG400 LDA #0
LDY LHAND ;else get the handle
STA LHAND ;clear it out
STA LOGON ;clear toggle too
JMP OSFIND ;close the file
*
* Here it's logging ON. Check not already logging
*
LOG500 LDY LHAND ;get handle of log file
BEQ LOG600 ;j if not logging
BRK ;else error
DFB 0
ASC 'Already on'
DFB 0
*
* Not logging yet. Next parameter must be the file name
*
LOG600 LDA #107 ;select help text
JSR LSTMPAR ;get param and check no more
*
* And open the file
*
LDA #0
STA LOGON ;clear toggle so don't log just yet
STA LOGCNT ;mark buffer empty
LDA #$80 ;write mode please
JSR OPNCUR ;open file
STA LHAND ;note the handle
LOG900 RTS
***************************************
*
* SAVE
* ====
*
* Writes current SET values to file
*
***************************************
SAVE EQU *
*
* First param is file name
*
LDA #113 ;select help text
JSR LSTMPAR ;get param and check no more
LDA #$80
JSR OPNCUR ;open file for writing
*
* File is open. Write our ID string first
*
TAY ;handle into Y
LDX #0
SAV200 LDA SAVID,X ;get byte
JSR OSBPUT ;write it
INX
CPX #4
BNE SAV200 ;j till all done
*
* Then write the parameter block
*
LDX #0
SAV300 LDA DFBASE,X ;get byte
JSR OSBPUT ;write it
INX
CPX #DFSIZE
BNE SAV300 ;j till all done
*
* Then close the file and finish
*
JMP CLOSEY ;handle in Y here
SAVID ASC 'KMT' ;id string for file
DFB $00
***************************************
*
* LOAD
* ====
*
* Loads SET params from file produced by
* SAVE
*
***************************************
LOAD EQU *
*
* First parameter is file name
*
LDA #113 ;select help text
JSR LSTMPAR ;get param and check no more
LDA #$40
JSR OPNCUR ;open file for reading
*
* File is open. read id to check it's a KERMIT parameter file
*
TAY ;handle into Y
STY CPTMP0 ;save for later, too
LDX #0
LOD200 JSR OSBGET ;read byte
BCS LOD900 ;j if EOF hit
CMP SAVID,X ;is it what we expect?
BNE LOD900 ;j if not
INX
CPX #4
BNE LOD200 ;j till 4 bytes checked
*
* File seems OK. Set current values to standard default
* in case we don't like it
*
JSR DEFAULT ;default params
*
* Then read values into the param block
*
LDX #0
LDY CPTMP0 ;get file handle
LOD300 JSR OSBGET ;get a byte
BCS LOD600 ;j if EOF
STA DFBASE,X ;save in the table
INX
CPX #DFSIZE ;this version's table full?
BCC LOD300 ;j if not - carry on
*
* Read complete, so close file
*
LOD600 JSR CLOSEY ;handle in Y here
IF RAM
*
* We're the RAM version, so eliminate any nasty values written from
* the ROM version
*
LDA DESTIN ;get data destination
CMP #1 ;is it MEMORY?
BNE LOD610 ;j if not
LDA #0
STA DESTIN ;else change to FILE
LOD610 EQU *
FI
*
* Then process the new params to set up dependent values
*
JMP DEF500
*
* Here the file isn't a KERMIT parameter file
*
LOD900 JSR CLOSEY ;close the file
BRK ;and error
DFB 0
ASC 'Not parameter file'
DFB 0
***************************************
*
* TAKE
* ====
*
* Switches command input to be a file
*
***************************************
TAKE EQU *
*
* Check TAKE file not already open
*
LDA TKHAND ;is TAKE file open?
BEQ TAK100 ;j if not
BRK ;else error
DFB 0
ASC 'Already TAKEing'
DFB 0
*
* No TAKE file open. Next parameter is mandatory filename
*
TAK100 LDA #117 ;select help text
JSR LSTMPAR ;get param and check no more
*
* Then open file and set up the handle
*
LDA #$40 ;read mode
JSR OPNCUR ;open it
STA TKHAND ;note the handle
STA CSOURCE ;and set it as command source
RTS
***************************************
*
* EXIT
* ====
*
* Quits KERMIT for BASIC
*
***************************************
EXIT JSR CONFIRM ;check no parameters
*
* First we'll put the screen back to normal
*
BIT SHADOW ;do we have shadow capability?
BPL EXI200 ;j if not
LDA #114
LDX ENTSHAD
JSR OBX0 ;else put it back as it was on entry
EXI200 LDA #22
JSR OSWRCH ;then change mode...
LDA #7
JSR OSWRCH ;...back to mode 7
*
* Then we'll reset all the other bits and pieces
*
JSR ESCON ;turn ESCAPE on
JSR LOSEACIA ;return 6850 to system
JSR LOSESYS ;reset vectors
IF RAM
JSR NOBINT ;lose BREAK intercept
LDA #$B4
LDX OLDHWM
JSR OBX0 ;restore original OSHWM value
FI
*
* And then we can go back to BASIC
*
LDX #>BASIC ;point to command
LDY #<BASIC
JMP OSCLI ;do *BASIC
BASIC STR 'B.'
***************************************
*
* RESET
* =====
*
* Restores built-in parameter values
*
***************************************
RESET JSR CONFIRM ;check no parameters
JSR DEFAULT ;copy default values to active table
JMP ADJTT ;and adjust terminal type default to suit machine
***************************************
*
* DISPLAY
* =======
*
* Displays message on screen
*
***************************************
DISPLAY EQU *
*
* Are we at end of command line already?
*
LDA #132 ;select help text
JSR GETPAR ;j if param - not at end of line
BCS DPY900 ;...else no text to display
*
* Use current param pointer as start of text, and display to EOLN
*
LDY #0
DPY100 LDA (CURPAR),Y ;get byte
JSR OSASCI ;display it
INY
CMP #$0D ;was it CR?
BNE DPY100 ;carry on if not
*
* All done
*
DPY900 RTS
***************************************
*
* WTCMD
* =====
*
* Delays for time or until keypress
*
***************************************
WTCMD EQU *
*
* Next (optional) parameter is the wait time
*
LDA #130 ;select help text
JSR GETPAR ;look for parameter
BCS WCM600 ;j if none there - indefinite wait
*
* Had a param, so wait for keypress or time up
*
JSR NUMPAR ;convert to binary
JSR CONFIRM ;check no more params
PHA ;save time
JSR WCM800 ;tell user we're waiting
PLA ;reget time
JMP WAIT ;and wait...
*
* Here we wait for ever until key is pressed
*
WCM600 JSR WCM800 ;tell user we're waiting
JMP WTKEY ;and wait...
*
* Routine to tell user we're waiting
*
WCM800 LDA #131
JMP MESS
IF ROM
***************************************
*
* FIX
* ===
*
* Saves current parameters back to defaults
* block if it is in sideways RAM
*
***************************************
FIX JSR CONFIRM ;check no parameters given
*
* Ask user if he really means it first
*
FIX100 LDA #147
JSR MESS ;ask for Y/N
JSR OSRDCH ;get reply
JSR UPPER ;force upper case
PHA ;save character
JSR OSWRCH ;echo it
JSR OSNEWL ;clear the line
PLA ;and reload character
CMP #'Y'
BEQ FIX300 ;j if he said Y
CMP #'N'
BNE FIX100 ;try again if not then N
RTS ;else we abort here
*
* User has confirmed. Check defaults block (and us) are in sideways RAM rather than
* a ROM
*
FIX300 LDY FIXCHK ;get byte from ROM space
INC FIXCHK ;increment it
INY ;increment the copy too
CPY FIXCHK ;both the same then?
BEQ FIX350 ;j if so - it's sideways RAM
BRK ;else we can't write
DFB 0
ASC 'No RAM'
DFB 0
*
* All OK, so copy current settings to defaults block
*
FIX350 LDY #DEFCNT-1
FIX380 LDA DFBASE,Y
STA DEFTAB,Y
DEY
BPL FIX380
*
* And finish
*
RTS
*
* Test byte to see if we're RAM or ROM
*
FIXCHK DFB 0 ;contents will change if RAM
FI
***************************************
*
* WIDTH
* =====
*
* Sets command-mode screen width
*
***************************************
WIDTH EQU *
IF RAM
JSR CKSHAD ;BRK if no shadow RAM
FI
JSR WIDPAR ;param is "40" or "80"
STA CWIDTH ;note the setting
LDA #2 ;set mode to 2 so we'll change command
STA MODE ;command screen mode in command processor
RTS
***************************************
*
* CLOSE
* =====
*
* Closes all open files
*
***************************************
CLOSE JSR CONFIRM ;check no parameters
*
* First we'll make sure any terminal log file is tidied up
*
JSR LOG200
*
* Now we do the close. To avoid the bug in "close all files" in
* DFS 2.24 we close any file we know we're writing to by hand
*
LDY FHAND ;transfer file open?
BEQ CLO300 ;j if not
LDA #0
STA FHAND ;else clear handle
JSR OSFIND ;and close it
*
* Rest of files we know of are read only, so do it the easy way
*
CLO300 LDA #0
STA CSOURCE ;clear TAKE handle
STA EXECH ;clear EXEC handle
STA TXHAND ;clear TRANSMIT handle
TAY
JMP OSFIND ;close all other files
***************************************
*
* TRANSMIT
* ========
*
* Raw-sends a file to a host in terminal
* mode
*
***************************************
TRANSMIT EQU *
*
* Parameter is the file name
*
LDA #225 ;select help text
JSR LSTMPAR ;get param and check no more
LDA #$40 ;select read mode
JSR OPNCUR ;open the file
*
* Then set up handle and enter terminal mode. The I/O handlers will
* automatically read the file as input instead of the keyboard
*
STA TXHAND
JMP CONNECT
***************************************
*
* JSR
* ===
*
* Enters user code with a JSR
*
***************************************
JSRCMD LDA #227 ;select help text
JSR LSTMNP ;get numeric address and check no more
JMP (NUM) ;then enter user's code
CHN BBCGEN
****** File BBCCOM *************************************************************
START COM
* BBCCOM: Updated 14/05/86 @ 1115
***************************************
*
* TXBYTE
* ======
*
* Transmits a byte over the RS423 link
*
***************************************
TXBYTE PHA ;save all registers
TXA
PHA
TYA
PHA
*
* Has transmit been held by an XOFF from the host?
*
TXB100 BIT TXHOLD
BMI TXB100 ;j if so - wait for it to clear
*
* Clear to go, so send the byte
*
TSX
LDA $103,X ;get data byte from stack
CLC ;specify 'wait for TDRE'
JSR IOWRITE ;and send the byte
*
* And that's it
*
TXB900 PLA
TAY
PLA
TAX
PLA
RTS
***************************************
*
* RXBYTE
* ======
*
* Reads a byte from the comms line or
* the keyboard
*
***************************************
RXBYTE PHA ;save all registers
TXA
PHA
TYA
PHA
*
* Are we doing a raw upload of a TRANSMIT file in terminal mode?
*
LDY TXHAND ;get TRANSMIT handle
BNE RXB230 ;j if doing raw upload
*
* Are we being a 'proper' terminal then?
*
BIT MODE
BPL RXB100 ;j if we are
*
* We're in transfer mode then. Do we want a byte timeout to run?
*
LDA TIMER ;else are we using timeout?
BEQ RXB100 ;j if we're not....
LDA RTIME ;...else get timeout period
JSR STCLCK ;and start the clock
*
* Not doing raw upload, so we service keyboard
* and comms line. The keyboard has the higher priority
*
RXB100 JSR INKEY ;do INKEY(0)
BCC RXB350 ;j if we have a keypress
JSR RDCBUF ;else look at comms input buffer
BCS RXB300 ;j if nothing there
RXB150 TSX
STA $103,X ;else set byte to be in A on entry
RXB200 JMP TXB900 ;and exit
*
* We're doing a raw send of a TRANSMIT file, so we read data from
* the file and the comms line, with the comms line having priority. We
* allow ESCAPE to terminate the upload
*
RXB230 JSR INKEY ;do INKEY(0)
BCS RXB250 ;j if no key is pressed
CMP #$1B ;is it ESCAPE?
BEQ RXB280 ;j if it is
RXB250 JSR RDCBUF ;else look at comms input buffer
BCC RXB150 ;j if a byte has come in
LDY TXHAND
JSR OSBGET ;else read the TRANSMIT file
BCS RXB280 ;j if EOF detected
JMP RXB910 ;else handle the byte
*
* EOF on TRANSMIT file or ESCAPE, so restore normal terminal operation
*
RXB280 JSR CLTXF ;close the file
JMP RXB100 ;and start at the top again
*
* Here we're in normal terminal or transfer mode, and there is no byte available
* from anywhere. If we're in transfer mode, see if we've now
* timed out
*
RXB300 LDA MODE
BPL RXB100 ;j if not transfer mode
LDA TIMER ;are we timing this?
BEQ RXB100 ;j if not
LDA TICKER ;else have we timed out?
BNE RXB100 ;j if not
LDA #90
JSR DMESS ;else log for debugging
INC TMOCNT ;step count of timeouts
BNE RXB320
INC TMOCNT+1
RXB320 BIT MODE ;do we display it?
BVC RXB340 ;j if generic mode - no display
LDA #19
JSR MESS ;else position cursor
LDX TMOCNT ;get the value
LDY TMOCNT+1
CLC ;select 5 digit field
JSR PRDEC ;and display the value
RXB340 JMP RXB800 ;then return C=1
*
* Key pressed here. We respond to CR, CTRL-X, CTRL-Z
* CTRL-D and CTRL-E if not in terminal mode
*
RXB350 LDA MODE
CMP #1
BEQ RXB900 ;j if terminal mode
CPX #$0D
BEQ RXB800 ;j if CR
CPX #CTRLX
BEQ RXB400 ;j if CTRL-X
CPX #CTRLD
BEQ RXB500 ;j if CTRL-D
CPX #CTRLE
BEQ RXB600 ;j if CTRL-E
CPX #CTRLZ
BEQ RXB390 ;j if CTRL-Z
JMP RXB100 ;else ignore the byte
*
* Here we had a CTRL-X or CTRL-Z. Note for higher level and carry on
*
RXB390 LDA #%11000000 ;CTRL-Z
BMI RXB450
RXB400 LDA #%10000000 ;CTRL-X
RXB450 STA TFSTOP
BIT MODE ;are we in generic mode for server command?
BVS RXB460 ;j if not
JMP RXB100 ;else no display
RXB460 TXA
PHA ;else save the character
LDA #42
JSR MESS ;position on screen...
LDA #75
JSR MESS ;print 'CTRL-'
PLA ;reload character
EOR #%01000000 ;make it character printable
JSR OSWRCH ;print it
JMP RXB100 ;and carry on
*
* CTRL-D here : toggle debug flag if debugging on
*
RXB500 LDA DEBUG
BNE RXB502 ;j if debug is on
JMP RXB100 ;else ignore it
RXB502 LDA DEBTOG
EOR #1
STA DEBTOG ;else toggle the flag
JMP RXB100
*
* CTRL-E here : Kick other side with an error packet
*
RXB600 BRK
DFB 0
ASC 'CTRL-E interrupt'
DFB 0
*
* Here we had keyboard CR or timed out, so abort the read loop
*
RXB800 SEC
JMP TXB900
*
* Here we're in terminal mode, and we have a keyboard byte
*
RXB900 TXA ;byte into A
RXB910 SEC ;return C=1 on exit
JMP RXB150
***************************************
*
* RDCBUF
* ======
*
* Extracts a character from the comms
* buffer and applies parity
*
***************************************
RDCBUF EQU *
*
* Is anything there to extract?
*
LDA IOCNT
BEQ RDC900 ;j if not - return fail
*
* Data there, so let's take byte under our remove cursor
*
SEI ;stop input to it
LDY IOOUT ;get remove pointer
LDA IOBUFF,Y
AND PARMSK ;apply any parity needed
PHA ;save the data
INC IOOUT ;step remove pointer
DEC IOCNT ;decrease count of chars in buffer
*
* See if it's appropriate to start the host now
*
LDX IOSTOP ;is he stopped at the moment?
BEQ RDC400 ;j if not - carry on
LDA IOCNT ;else he is stopped, so we ask ourselves...
CMP #IOTHR2+1 ;is buffer empty enough?
BCS RDC400 ;j if not - leave him stopped
JSR HOSTON ;else start him
*
* We get here if we have a byte to return
*
RDC400 PLA ;get data
CLI ;turn comms buffer on
CLC
RTS
*
* We come here if the buffer was empty
*
RDC900 CLI ;turn comms bufer on
SEC ;and return fail
RTS
***************************************
*
* IRQENT
* ======
*
* Handles receive data interrupts from
* the 6850 and drives our comms buffer.
* For ROM version registers must be stacked before
* we are entered by JMP
*
***************************************
IRQENT EQU *
IF RAM
PHA ;save registers
TXA
PHA
TYA
PHA
FI
*
* Is this a 6850 interrupt?
*
LDA IOSTAT
BPL IRQ900 ;j if not 6850
LSR A ;RDRF into carry
BCC IRQ900 ;j if not RDRF
*
* RDRF is set. Check for 6850 error (note status is shifted 1 bit right here!)
*
AND #%00111000 ;isolate error flags
BEQ IRQ200 ;j if no error
LDA IODATA ;else clear data register too
LDA #'@'
JSR IOR400 ;return a dummy "@" data byte
JMP IRQ300
*
* No error, read the byte and insert into our comms buffer under the
* insert cursor
*
IRQ200 JSR IOREAD
*
* Now let's see if we need to stop the host for a bit
*
IRQ300 LDA IOSTOP ;is he stopped already?
BNE IRQ800 ;j if so - he'll notice it sometime
LDA IOCNT ;he's not stopped, so we ask...
CMP #IOTHR+1 ;is buffer past threshold now?
BCC IRQ800 ;j if not - let him carry on
JSR HOSTOFF ;else stop him
IF RAM
*
* RAM version now goes to the old IRQ1 vector
*
IRQ800 EQU *
IRQ900 PLA
TAY
PLA
TAX
PLA
JMP (OLDIRQ)
ELSE
*
* ROM version adjusts stacked registers so A will be zero on exit since we've serviced the IRQ
*
IRQ800 LDA #0 ;stop lower ROMs being given this IRQ as well
TSX ;or speed will be dreadful
STA $103,X
*
* All done, so restore registers and finish. The
* RTS here terminates our sideways ROM processing of
* "unrecognised IRQ" and goes back to the OS.
*
IRQ900 PLA
TAY
PLA
TAX
PLA
RTS ;back to OS
FI
***************************************
*
* HOSTON
* ======
*
* Starts the host with either an XON or
* by bringing RTS low, and clears any
* flow control the host has exerted
*
***************************************
HOSTON LDA #0
STA TXHOLD ;clear host's flow control
BIT SCROLL ;is NOSCROLL set?
BMI HOS350 ;j if so - leave host alone
LDA FLOW ;get the flow control in use
BNE HOS400 ;j if CTS/RTS
*
* We're using XON/XOFF, so send an XON
*
LDA #XON
CLC ;select 'wait for TDRE'
JSR IOWRITE ;and send it
HOS300 LDA #0
STA IOSTOP ;note host not now XOFF'd
HOS350 RTS
*
* Here flow control is CTS/RTS, so reset the 6850 to bring rts low
*
HOS400 JSR RAC100 ;reset the 6850 to normal with RTS low
JMP HOS300 ;and note host is started
***************************************
*
* HOSTOFF
* =======
*
* Stops host with either an XOFF or with
* rts high
*
***************************************
HOSTOFF LDA FLOW ;get flow control in use
BEQ HOF600 ;j if XON/XOFF
*
* We're using CTS/RTS, so put RTS high
*
LDA PARSET ;get 6850 setting
AND #%10011111 ;change to rts high
ORA #%01000000
TAX
JSR CHACIA ;reset the 6850
JMP HOF650
*
* Here we're using XON/XOFF
*
HOF600 LDA #XOFF ;else we send an XOFF
SEC ;select 'no wait for TDRE'
JSR IOWRITE ;and send the XOFF
HOF650 LDA #1
STA IOSTOP ;and note host is now stopped
RTS
***************************************
*
* WTTDRE
* ======
*
* Waits for TDRE on the 6850
*
***************************************
WTTDRE LDX MUXWT ;get the MUX delay period
BEQ WTT200 ;j if no delay needed
LDY TXBAUD ;else get TX baud rate
JSR BYTEWT ;and wait for n byte periods
WTT200 LDA IOSTAT ;now look at the 6850 status
AND #%00000010 ;is TDRE set (and hence CTS low)?
BEQ WTT200 ;j if not - wait
RTS
***************************************
*
* FLUSH
* =====
*
* Empties comms buffer and ensures host
* is started
*
***************************************
FLUSH PHP ;save IRQ state
CLI ;stop inward traffic for a moment
*
* Reset buffer controls
*
LDA #0
STA IOCNT ;chars in buffer
STA IOIN ;insert pointer
STA IOOUT ;remove pointer
STA SCROLL ;clear NOSCROLL setting
*
* If host is stopped, we'll start him
*
LDX IOSTOP
BEQ FLU900 ;j if he's not stopped
STA IOSTOP ;note he's not any more
JSR RAC100 ;bring rts low regardless of flow control
LDA FLOW ;are we coing XON/XOFF?
BNE FLU900 ;j if not
LDA #XON
STA IODATA ;else also send XON, regardless of TDRE
*
* And finish
*
FLU900 PLP ;restore old IRQ state
RTS
***************************************
*
* IOREAD
* ======
*
* Gets a data byte from the 6850 and
* inserts it into the comms buffer,
* handling XON/XOFF from the host
*
***************************************
IOREAD LDA IODATA ;read byte
*
* If flow control is XON/XOFF, check what the byte is
*
LDY FLOW
BNE IOR400 ;j if not XON/XOFF
*
* We're using XON/XOFF, so check for flow control from the host
*
TAY ;save input byte
AND #%01111111 ;lose parity setting
CMP #XON
BEQ IOR520 ;j if XON
CMP #XOFF
BEQ IOR500 ;j if XOFF
TYA ;else get original value back
*
* Byte is not a control, so put it into the buffer
*
IOR400 LDY IOIN
STA IOBUFF,Y ;store it
INC IOIN ;step insert pointer
INC IOCNT ;step count of chars in buffer
RTS
*
* Host has sent an XOFF, so inhibit the transmit loop
*
IOR500 LDA #$FF
IOR510 STA TXHOLD
RTS
*
* Host has sent an XON, so clear the transmit hold
*
IOR520 LDA #0
BEQ IOR510
***************************************
*
* IOWRITE
* =======
*
* Writes a data byte to the 6850
*
***************************************
IOWRITE PHP ;save "wait on TDRE" flag
*
* Apply parity setting to the byte
*
LDX PARITY ;get parity setting
CPX #2 ;is it MARK or SPACE?
BCS IOW100 ;j if not - 6850 does it
DEX
BEQ IOW050 ;j if it's SPACE
*
* Parity wanted is MARK
*
ORA #%10000000
BMI IOW100
*
* Parity is SPACE
*
IOW050 AND #%01111111
*
* Save data for a bit, and wait for TDRE if required
*
IOW100 PLP ;get "wait" flag
PHA ;save data
BCS IOW200 ;j if we don't wait
JSR WTTDRE ;else we wait
*
* Now look for RDRF, in case a byte has just come in. We might lose
* the RDRF interrupt if we write at such a moment
*
IOW200 PHP
SEI ;hold IRQ levels
LDA IOSTAT ;get status byte
LSR A ;RDRF into carry
BCC IOW300 ;j if no byte come in
*
* A byte has just come in, so read and store it.
*
JSR IOREAD
IOW300 PLP ;restore old IRQ state
*
* Now it's safe to send our data byte. If we did get an XOFF on the
* read above we'll notice it next time round
*
PLA
STA IODATA
*
* And finish
*
RTS
***************************************
*
* BRKLVL
* ======
*
* Sets 6850 to output a break level
*
***************************************
BRKLVL LDA PARSET ;get current 6850 setting
ORA #%01100000 ;add "break level" bits
TAX
JMP CHACIA ;and set it up
***************************************
*
* SHTBRK
* ======
*
* Sends a short line break (240mS or so)
*
***************************************
SHTBRK JSR BRKLVL ;get 6850 sending break level
JSR TIMBRK ;delay for 240mS
BEQ RAC100 ;and put 6850 back as it was
***************************************
*
* LNGBRK
* ======
*
* Sends a long line break (3.5 S or so)
*
***************************************
LNGBRK LDA #15
STA WORK0 ;set counter
JSR BRKLVL ;get 6850 sending break level
LBK100 JSR TIMBRK ;wait for 240mS or so
DEC WORK0
BNE LBK100 ;keep waiting for about 3.5 S
BEQ RAC100 ;then put 6850 back as it was
***************************************
*
* TIMBRK
* ======
*
* Waits 240mS while sending line break
*
***************************************
TIMBRK LDX #188
TBR100 LDY #0
TBR200 DEY
NOP
NOP
BNE TBR200
DEX
BNE TBR100
RTS
***************************************
*
* CHACIA
* ======
*
* Writes the 6850 control register
*
***************************************
CHACIA LDA #$9C
JMP OBX0
***************************************
*
* SETACIA
* =======
*
* Sets 6850 baud rate and parity
*
***************************************
SETACIA LDA #7
LDX RXBAUD
JSR OSBYTE ;set receive rate
LDA #8
LDX TXBAUD
JSR OSBYTE ;set transmit rate
RSTACIA LDX #%00010011
JSR CHACIA ;master reset
RAC100 LDX PARSET
JMP CHACIA ;set parity, etc
***************************************
*
* BYTEWT
* ======
*
* Wait [X] byte periods at baud rate [Y]
*
***************************************
BYTEWT LDA BWTTBL,Y ;get 1000 micro second periods per byte
STX WORK7
STA WORK8 ;for this baud rate
STA WORK9
BWT100 JSR BWT900 ;wait about 1000 micro seconds
DEC WORK9
BPL BWT100 ;repeat to wait for1 byte period
LDA WORK8 ;refresh counter
STA WORK9
DEC WORK7
BPL BWT100 ;repeat for n byte periods
RTS
*
* Loop to wait for about 1000 micro seconds
*
BWT900 LDX #10
BWT905 LDY #26
BWT910 LDA #0
DEY
BPL BWT910
DEX
BPL BWT905
RTS
*
* Table of 1000 micro second intervals per byte period
*
BWTTBL DFB 147 ;75 baud
DFB 73 ;150
DFB 37 ;300
DFB 9 ;1200
DFB 5 ;2400
DFB 2 ;4800
DFB 1 ;9600
NEXT BBCTM1
****** File BBCCPR *************************************************************
START CPR
* BBCCPR: Updated 10/01/87 @ 1730
***************************************
*
* SCANTAB
* =======
*
* Scans a command table for an entry
*
***************************************
SCENT EQU CPTMP0
SCMTCH EQU CPTMP1
SCRSLT EQU CPTMP2
SCENTL EQU CPTMP3
SCANTAB PHP ;note abbreviation flag
LDY #0
STY SCENT ;start entry counter
STY SCMTCH ;no matches yet
*
* Process the next entry. Are we at end of table?
*
SCT100 LDA (CMDTBL),Y ;get length of entry
BEQ SCT800 ;j if at end of table
STA SCENTL ;else note length
*
* Move table pointer to start of the entry and start scan pointer
*
SCT200 INC CMDTBL
BNE SCT220
INC CMDTBL+1
SCT220 LDY #0
*
* Compare the next two bytes
*
SCT240 LDA (CURPAR),Y ;get from parameter
JSR UPPER ;force upper case
CMP (CMDTBL),Y ;and compare
BNE SCT600 ;j if mismatch
*
* Bytes match, so move on if we can
*
INY ;step string offset
CPY CURLEN ;at end of parameter?
BEQ SCT400 ;j if we are
CPY SCENTL ;at end of entry string?
BEQ SCT600 ;j if so - this is a mismatch
BNE SCT240 ;else keep going
*
* We've matched to end of parameter. Are we at end of the table string too?
*
SCT400 CPY SCENTL
BEQ SCT850 ;j if we are - exact match terminates scan
PLP ;else is an abbreviation OK here?
PHP
BCS SCT600 ;j if not - mismatch
*
* Here we have a match. Make sure it's the first, or it's an error
*
SCT500 LDA SCMTCH ;get match counter
BNE SCT900 ;j if not the first
INC SCMTCH ;else count this match
LDA SCENT
STA SCRSLT ;note the entry number
*
* Now we move to the next entry in the table
*
SCT600 LDY #0 ;restart string offset
INC SCENT ;step entry counter
LDA CMDTBL ;add string length to current pointer, which here points
CLC ;the string, not the length byte
ADC SCENTL
STA CMDTBL
BCC SCT100 ;do next entry
INC CMDTBL+1
BNE SCT100 ;do next entry
*
* We've done the whole table, and got either no matches or one match
*
SCT800 LDA SCMTCH ;get match counter
BEQ SCT910 ;j if none - error
PLP ;else tidy the stack
LDA SCRSLT ;pass match entry no to caller
RTS
*
* Here we had an exact match so we search no further
*
SCT850 PLP ;tidy the stack
LDA SCENT ;return entry number
RTS
*
* Here we had more than one match
*
SCT900 LDA #183 ;select error text
SCT905 JMP PARMERR ;and report
*
* Here we had no matches at all
*
SCT910 LDA #184 ;select error text
BNE SCT905 ;and report
***************************************
*
* PARAM
* =====
*
* Locates the next parameter in a command
* line
*
***************************************
PARAM EQU *
*
* Are we already at EOLN?
*
LDY CMDPTR ;scan start offset
LDA CMDBUF,Y ;get command byte
CMP #$0D
BEQ PAR600 ;j if at EOLN
DEY
*
* Scan for a space or CR as delimiter, or char for autohelp
*
PAR200 INY ;move on a byte
LDA CMDBUF,Y
CMP #$0D
BEQ PAR400 ;j if EOLN
CMP #' '
BEQ PAR220 ;j if space
CMP HLPTRG
BNE PAR200 ;j if not autohelp char
JMP AUTOHLP ;else do autohelp
*
* Here we've found a space. Set up details of the parameter, then move to the next
*
PAR220 JSR PAR800 ;set up details
JSR SPSKIP ;move to start of nxt
PAR240 LDA CURLEN ;return the length
CLC
RTS
*
* Here the parameter ends in CR
*
PAR400 JSR PAR800 ;set up details
JMP PAR240
*
* Here we were at EOLN on entry, so there's nothing
*
PAR600 SEC
RTS
*
*
* Routine to set up details of a parameter
*
PAR800 TYA ;offset to delimiter
SEC
SBC CMDPTR ;form the length
STA CURLEN
LDA CMDPTR ;note offset to start of parameter
STA CURST ;from strt of whole line
LDA #>CMDBUF ;get start address
CLC
ADC CMDPTR
STA CURPAR
LDA #<CMDBUF
ADC #0
STA CURPAR+1
STY CMDPTR ;update current position
RTS
***************************************
*
* MPARAM
* ======
*
* Locates the next parameter in a
* command line, erroring if none there
*
***************************************
MPARAM JSR PARAM ;anything there?
BCC SHL900 ;j if so
*
* No parameter, so error. Adjust the input line so we can retype it
* up to the end, with an added space
*
LDY CMDPTR ;pointer to the CR byte
LDA #' '
STA CMDBUF,Y ;put a space on the end
INY
STY CURST ;adjust place we retype up to
LDA #181 ;then select error text
MPA900 JMP PARMERR ;and report
***************************************
*
* MALLPAR
* =======
*
* Returns all the rest of the line as
* next mandatory parameter
*
***************************************
MALLPAR JSR GETMPAR ;find where it starts
MAP100 LDA RDLPTR ;get offset to final CR
SEC
SBC CURST
SBC #1 ;calculate length to end of line
STA CURLEN ;adjust parameter details
RTS
***************************************
*
* CONFIRM
* =======
*
* Checks command line has no excess
* parameters
*
***************************************
CONFIRM PHA
LDA #38 ;select help text
JSR GETPAR ;is parameter there?
PLA
BCS SHL900 ;j if not - all OK
LDA #182 ;else select error text
BNE MPA900 ;and report
***************************************
*
* PARMERR
* =======
*
* Reports parameter validation error and
* sets up for retyping
*
***************************************
PARMERR PHA ;save error text number
LDA #179
JSR MESS ;say "ERROR"
PLA
JSR MESS ;then output the text
JSR OSNEWL ;and tidy up
JSR OSNEWL
*
* Are we in a TAKE file?
*
LDA CSOURCE ;get command source
BNE PER500 ;j if a TAKE file
*
* Are we in an EXEC file?
*
JSR RDEXH
BNE PER500 ;j if we are
*
* Command source is not a file, so restart command processor and retype up to the failed parameter
*
LDY CURST ;offset to start of it
JMP AHL940 ;and restart
*
* We're in a TAKE or EXEC file, so close both and re-enter from the top
*
PER500 JSR KBDSRC
JMP BRK500 ;use BRK code to restart
***************************************
*
* SETHLP
* ======
*
* Selects the autohelp text for params
* that don't have tables
*
***************************************
SETHLP STA CMDTBL
LDA #0
STA CMDTBL+1
SHL900 RTS
***************************************
*
* SELTAB
* ======
*
* Selects a command table
*
***************************************
SELTAB STX CMDTBL ;note table base address
STY CMDTBL+1
*
* Now get the details from table header
*
LDY #0
LDA (CMDTBL),Y ;note action table base
STA JMPTBL
INY
LDA (CMDTBL),Y
STA JMPTBL+1
*
* Then move address to base of the entries
*
LDA CMDTBL
CLC
ADC #2
STA CMDTBL
BCC STB900
INC CMDTBL+1
*
* And finish
*
STB900 RTS
***************************************
*
* ACTION
* ======
*
* Enters an action routine
*
***************************************
ACTION ASL A
TAY ;form offset into address list
LDA (JMPTBL),Y ;set up address
STA ACTRTN
INY
LDA (JMPTBL),Y
STA ACTRTN+1
JMP (ACTRTN) ;and enter the code
***************************************
*
* AUTOHLP
* =======
*
* Gives help when user enters help trigger
* as a command line component
*
***************************************
AHCLFT EQU CPTMP0
AHENTL EQU CPTMP1
AUTOHLP EQU *
*
* Is this help a table dump or a text?
*
LDA CMDTBL+1
BNE AHL100 ;j if table dump
LDA CMDTBL ;get text number
JSR MESS ;and print it
JSR OSNEWL
JMP AHL920 ;and finish
*
* Here we do a table dump of the current command table
*
AHL100 LDA #27
JSR MESS ;print 'Options are..'
JSR AHL800 ;and start a print line
*
* Now sort out the length of the entry pointed by (CMDTBL)
*
AHL200 LDY #0
LDA (CMDTBL),Y ;get string length
BEQ AHL900 ;j if zero - end of table
STA AHENTL ;else save for later
CMP AHCLFT ;will it fit on the line?
BCC AHL300 ;j if it will
JSR AHL800 ;else start a new line
*
* There's room on the line now, so print the entry
*
AHL300 INC AHENTL ;add 1 to string length
LDY #1 ;start string pointer
AHL320 LDA (CMDTBL),Y
JSR AHL820 ;print the byte
INY
CPY AHENTL ;at end of string?
BNE AHL320 ;j if not
*
* Entry is done, so either tab to next field or start a new line
*
LDA AHCLFT ;get space left
CMP #8
BEQ AHL350 ;j if on start of last field
BCS AHL360 ;j if room to tab
AHL350 JSR AHL800 ;else start a new line
JMP AHL400
AHL360 AND #7 ;get distance to next field start
BNE AHL365 ;j if within a field
LDA #8 ;else move to next
AHL365 TAY
LDA #' ' ;and spacefill to it
AHL380 JSR AHL820
DEY
BNE AHL380
*
* Step the table pointer to the next entry
*
AHL400 LDA CMDTBL
CLC
ADC AHENTL
STA CMDTBL
BCC AHL200
INC CMDTBL+1
BNE AHL200
*
* Here we start a new output line
*
AHL800 LDY CSCRLN
INY
STY AHCLFT ;set space left count
JMP OSNEWL
*
* Here we print a byte and count it
*
AHL820 DEC AHCLFT
JMP OSWRCH
*
* Here it's all done, so tidy up and re-issue the prompt
*
AHL900 JSR OSNEWL
AHL920 JSR OSNEWL
LDY CMDPTR ;set pointer for RDLINE's prompt
AHL940 LDX STKHLP ;wind the stack back
TXS
JMP CMDRST ;and restart command processor
***************************************
*
* SPSKIP
* ======
*
* Skips to a non-space in the command
* line
*
***************************************
SPSKIP LDA CMDBUF,Y ;get a byte
CMP #' '
BNE SPS900 ;j if non-space
INY
BNE SPSKIP ;else carry on
SPS900 STY CMDPTR ;note position of non-space
RTS
***************************************
*
* CMDMODE
* =======
*
* This is the routine that processes
* KERMIT command level
*
***************************************
CMDMODE EQU *
*
* Fake mode to $02, so first header screen goes out
*
LDA #$02
STA MODE
*
* Set up restart details and take over system
*
TSX
JSR SETCRS ;set restart details up
JSR GETSYS ;take control of system
*
* Top of loop : note stack position and vector for BRK restart
* and set the autohelp stack point
*
CMO060 CLI ;make sure IRQ is allowed
TSX
STX STKHLP
JSR SETCRS
CMO100 JSR GETEV ;make sure we have event vector still
*
* Make sure cursor is on, and set up function keys to their
* power on state
*
JSR CSRON ;cursor on
LDA #4
JSR OB00 ;cursor keys are edit keys
LDX #>CMOTB1 ;point F key base values list
LDY #<CMOTB1
JSR SETKEY ;and set them up
LDX #48
JSR SETPAD ;return Master keypad to normal too
*
* Is command screen set up and in the right mode?
*
LDA MODE
BEQ CMO200 ;j if in command mode and screen up
CMP #%10000000
BEQ CMO200 ;j if in generic mode with screen up
*
* No command screen up, so output it
*
LDA CWIDTH ;what width do we want?
BNE CMO120 ;j if 40 byte MODE 7 screen
*
* We want an 80 byte MODE 3 screen
*
JSR STMDE3 ;go to mode 3
LDY #79 ;last char on line is 79
LDA #128 ;get header text number
LDX #177 ;and prompt text number
BNE CMO130
*
* Here we want a 40 byte MODE 7 screen
*
CMO120 LDY #39 ;last char on line is 39
LDA #110 ;get header text number
LDX #9 ;get prompt text number
CMO130 STY CSCRLN ;note chars on line
STX PMESS ;note prompt number
JSR MESS ;and put out the header
*
* Then, with the command screen up, ask any TXRs to say hello
*
LDX #$81
JSR DOKOSB
*
* Now note we're in command mode
*
CMO200 LDY #0 ;mode and buffer start to zero
STY MODE
*
* Now prompt for a command and read it in
*
K1CMD EQU *
STY WORK0 ;save buffer start
JSR ESCON ;make sure ESCAPE is on
LDA CSOURCE ;get command source
BNE CMO300 ;j if it's from file
CMO280 LDA PMESS ;else get prompt text number
JSR MESS ;and prompt for input from keyboard
LDY WORK0 ;reload buffer pointer
JSR RDLINE ;read with echo
JMP CMO380
CMO300 LDA TKECHO ;source is file, so check TAKE echo
BNE CMO280 ;j if echo on
JSR RDLINX ;else read without echo or prompt
*
* A holds first non-space byte, so see what sort of line we got
*
CMO380 CMP #':'
BEQ CMO200 ;j if comment line
CMP #'*'
BEQ CMO400 ;j if it's an OS command
CMP #$0D
BEQ CMO200 ;j if null line
*
* It's a KERMIT command. Select the top level
* command table. We know line is not empty here
*
LDX #>MAINCMD
LDY #<MAINCMD
JSR GMPAS ;get command and validate it
PHA ;it's OK so save the command number..
JSR ESCOFF ;...turn ESCAPE off..
PLA ;get the number back...
JSR ACTION ;...implement it....
JMP CMO060 ;...back to the top
*
* Here it's an OS command, so give it to the CLI
*
CMO400 JSR LOSEACIA ;give up 6850 control
JSR LOSESYS ;reset standard vectors...
JSR GETBRK ;...but keep hold of the BRK vector!
LDX #>CMDBUF ;point to the line
LDY #<CMDBUF
JSR OSCLI ;execute the command
JSR GETACIA ;retake control of 6850
JSR GETSYS ;retake vectors
JSR WHATFS ;see if filing system has changed on us
JMP CMO060 ;and start again
*
*
* Side entries
* ============
*
CMDRST EQU K1CMD ;autohelp re-entry point
CMOTB1 DFB 1,$80,$90,0 ;F Key base values
MAINCMD EQU *
DW MAINJMP ;jump table address
CMD 1,'C'
CMD 7,'CONNECT'
CMD 4,'SHOW'
CMD 3,'SET'
CMD 4,'SEND'
CMD 7,'RECEIVE'
CMD 3,'GET'
CMD 3,'BYE'
CMD 6,'FINISH'
CMD 6,'REMOTE'
CMD 7,'LOGGING'
CMD 4,'LOAD'
CMD 4,'SAVE'
CMD 4,'TAKE'
CMD 4,'EXIT'
CMD 5,'RESET'
CMD 7,'DISPLAY'
CMD 4,'WAIT'
CMD 5,'WIDTH'
CMD 5,'CLOSE'
IF ROM
CMD 3,'FIX'
FI
CMD 3,'JSR'
CMD 8,'TRANSMIT'
DFB 0
MAINJMP EQU *
DW CONNECT ;C
DW CONNECT ;CONNECT
DW SHOW ;SHOW
DW SET ;SET
DW SEND ;SEND
DW RECEIVE ;RECEIVE
DW GET ;GET
DW BYE ;BYE
DW FINISH ;FINISH
DW REMOTE ;REMOTE
DW LOG ;LOGGING
DW LOAD ;LOAD
DW SAVE ;SAVE
DW TAKE ;TAKE
DW EXIT ;EXIT
DW RESET ;RESET
DW DISPLAY ;DISPLAY
DW WTCMD ;WAIT
DW WIDTH ;WIDTH
DW CLOSE ;CLOSE
IF ROM
DW FIX ;FIX
FI
DW JSRCMD ;JSR
DW TRANSMIT ;TRANSMIT
***************************************
*
* RDLINE/RDLINEX
* ==============
*
* Reads an input line with echo (RDLINE)
* or without echo (RDLINX)
*
***************************************
RDLINE SEC ;echo required
BCS RDL050
RDLINX CLC ;echo not required
RDL050 PHP ;save echo flag
STY RDLPTR ;save buffer start offset
*
* Do we now re-issue existing buffer contents?
*
LDY RDLPTR ;look at supplied offset
BEQ RDL130 ;j if not
LDY #0 ;else we output contents
RDL100 LDA CMDBUF,Y
JSR OSWRCH
INY
CPY RDLPTR
BNE RDL100
*
* Now we can read and stuff up the buffer
*
RDL130 LDY CSOURCE ;what's the command source?
BNE RDL132 ;j if it's take file
JSR OSRDCH ;else read keyboard
BCC RDL150 ;j if not ESCAPE
RDL131 JSR ACKESC ;else ACK the condition
BRK ;and BRK
DFB 0
ASC 'Escape'
DFB 0
*
* Command source is a TAKE file. We need to poll the ESCAPE bit before we read
*
RDL132 JSR TSTESC ;BRK if ESCAPE pending
LDY CSOURCE ;else get TAKE handle
JSR OSBGET ;and read the file
BCC RDL150 ;j if got a byte
*
* End of TAKE file reached, so close it and tack a CR on to what we got
*
JSR CLTAKE ;close the file
RDL140 LDA #$0D ;and pretend we read a CR
*
* We have a character from somewhere: look for those control characters we allow
*
RDL150 AND #%01111111 ;strip B7 input byte
LDY RDLPTR ;get buffer pointer
CMP #$0D
BEQ RDL175 ;j if CR
CMP #CTRLU
BEQ RDL700 ;j if CTRL-U
CMP #$7F
BEQ RDL500 ;j if DEL
CMP #CTRLN
BEQ RDL180 ;j if CTRL-N
CMP #CTRLO
BEQ RDL180 ;j if CTRL-O
*
* Any other control character is ignored
*
CMP #32
BCC RDL130 ;j if control character
*
* For anything else, we need space in the buffer
*
CPY #MAXINP-2
BEQ RDL600 ;j if no space there
*
* There is room, so enter in buffer, echo if needed and step pointers
*
RDL175 STA CMDBUF,Y
INY
STY RDLPTR
RDL180 PLP
PHP ;get echo flag
BCC RDL187 ;j if echo off
JSR OSASCI ;else write to screen
*
* Was the byte a CR?
*
RDL187 CMP #$0D
BEQ RDL220 ;j if it was
*
* Not CR, so look for char which triggers autohelp
*
CMP HLPTRG ;is this the help trigger?
BNE RDL130 ;j if not
BEQ RDL140 ;else pretend we read a CR
*
* Now we'll scan the line to see what we got
*
RDL220 LDY #0
JSR SPSKIP ;skip to non-space
PLP ;lose the echo flag from the stack
RTS ;and finish
*
* Here user pressed DEL
*
RDL500 CPY #0 ;are we at start of buffer?
BEQ RDL610 ;j if we are
DEY ;else step pointer back
STY RDLPTR ;and note new value
JMP RDL180 ;and echo DEL to VDU
*
* Here buffer is full. Bleep if keyboard input, error if TAKE file
*
RDL600 LDY CSOURCE ;get commnd source
BEQ RDL610 ;j if keyboard
BRK ;else we error
DFB 0
ASC 'Line too long'
DFB 0
RDL610 LDA #7 ;simply bleep if keyboard input
BNE RDL180
*
* Here user pressed CTRL-U to abandon the line
*
RDL700 CPY #0
BNE RDL705 ;j if got some input
JMP RDL130 ;j if line is empty
RDL705 LDA #$7F ;else DEL back to start
RDL720 JSR OSWRCH
DEY
BNE RDL720
STY RDLPTR
JMP RDL130 ;and start again
CHN BBCCMD
****** File BBCDEF *************************************************************
START DEF
* BBCDEF: Updated 10/05/86 @ 1120
***************************************
*
* OS ADDRESSES
* ============
*
***************************************
OSFIND EQU $FFCE
OSGBPB EQU $FFD1
OSBPUT EQU $FFD4
OSBGET EQU $FFD7
OSARGS EQU $FFDA
OSFILE EQU $FFDD
OSRDCH EQU $FFE0
OSASCI EQU $FFE3
OSNEWL EQU $FFE7
OSWRCH EQU $FFEE
OSWORD EQU $FFF1
OSBYTE EQU $FFF4
OSCLI EQU $FFF7
OSWRSC EQU $FFB3
OSRDSC EQU $FFB9
OSEVEN EQU $FFBF
GSINIT EQU $FFC2
GSREAD EQU $FFC5
**************************************
*
* TELETEXT CONTROL CODES
* ======================
*
**************************************
RED EQU 129
GREEN EQU 130
YELLOW EQU 131
BLUE EQU 132
MAGENTA EQU 133
CYAN EQU 134
WHITE EQU 135
FLASH EQU 136
STEADY EQU 137
NORMHT EQU 140
DOUBLE EQU 141
BLKBG EQU 156
NEWBG EQU 157
**************************************
*
* HARDWARE ADDRESSES ON IO PROCESSOR
* ==================================
*
**************************************
IOSTAT EQU $FE08 ;6850 status register
IODATA EQU $FE09 ; data register
UVT1CL EQU $FE64 ;User VIA C1 low
UVT1LL EQU $FE64 ; T1 latch low
UVT1LH EQU $FE65 ; T1 latch high
UVACR EQU $FE6B ; ACR
UVIFR EQU $FE6D ; IFR
UVIER EQU $FE6E ; IER
***************************************
*
* COMMS CONTROL
* =============
*
***************************************
IOBSIZ EQU 256 ;size of comms buffer
IOTHR EQU 200 ;stop threshold
IOTHR2 EQU 50 ;go threshold
***************************************
*
* OS LOCATIONS
* ============
*
***************************************
IRQ1V EQU $0204 ;IRQ1 vector
EVENTV EQU $0220 ;event vector
BRKV EQU $0202 ;break vector
USERV EQU $0200 ;user vector
BYTEV EQU $020A ;OSBYTE vector
WSCPTR EQU $D6 ;pointer location used by OSWRSC
RSCPTR EQU $F6 ;pointer location used by OSRDSC
STDVLEN EQU $FFB6 ;length of default vector table
STDVPTR EQU $FFB7 ;position of the table
***************************************
*
* MESSAGE SYSTEM TOKENS
* =====================
*
***************************************
EOT EQU $FF ;end of text
TXT EQU $FE ;sub text expansion
RPT EQU $FD ;multiple character escape
XCR EQU $FC ;encoded CR byte
MTXT EQU $FB ;multiple sub text expansion
MSP EQU $FA ;multiple space
LIT EQU $F9 ;literal escape for next character
;this must be lowest number
***************************************
*
* PAGE ZERO AREAS
* ===============
*
***************************************
DSECT
ORG $00
* The first block of entries are fixed
* in format and position. A TXR may read
* details from them, but should alter them
* only with care
DEFPTR DW 0 ;address of SET values block
MODE DFB 0 ;system mode
CWIDTH DFB 0 ;command screen width (0=80,1=40)
PMESS DFB 0 ;number of command mode prompt message
EVECTB DW 0 ;address of extended vector table
STKRST DFB 0 ;stack position for BRK restart
RESTART DW 0 ;address for BRK restart
IOIN DFB 0 ;comms buffer insert pointer
IOOUT DFB 0 ; remove pointer
IOCNT DFB 0 ;characters in buffer
IOSTOP DFB 0 ;host stopped flag
TXHOLD DFB 0 ;transmit stopped by host XOFF
SCROLL DFB 0 ;scroll/noscroll status
PARSET DFB 0 ;6850 control settings
PARMSK DFB 0 ;mask for data parity
LOGCNT DFB 0 ;bytes in terminal log buffer
LHAND DFB 0 ;handle for logging file
LOGON DFB 0 ;logging toggle
TXHAND DFB 0 ;handle of TRANSMIT file
TICKER DFB 0 ;1 second count down
TXRACT DFB 0 ;0=local term;$FF=TXR doing it
OSTYPE DFB 0 ;OS type, minus one
SHADOW DFB 0 ;flag for shadow RAM in use
ENTSHAD DFB 0 ;shadow state on entry
CSOURCE DFB 0 ;command source (0=keyboard, else file handle)
TKHAND DFB 0 ;handle of TAKE file
EXECH DFB 0 ;handle of EXEC file
DEBTOG DFB 0 ;debug toggle
* Entries from here to $8F contain no
* permanent data and may be freely used
* by a TXR for its own purposes. TXRs
* should use space starting from $8F
* down to leave a gap for expansion
* of the fixed section
PTR0 DW 0 ;general pointers
PTR1 DW 0
PTR2 DW 0
PTR3 DW 0
WORK0 DFB 0 ;general workspace
WORK1 DFB 0
WORK2 DFB 0
WORK3 DFB 0
WORK4 DFB 0
WORK5 DFB 0
WORK6 DFB 0
WORK7 DFB 0
WORK8 DFB 0
WORK9 DFB 0
MWORK0 DFB 0 ;message system work space
MPTR0 DW 0
MPTR1 DW 0
MSGPTR DW 0 ;message system pointer
CPTMP0 DFB 0 ;command processor workspace
CPTMP1 DFB 0
CPTMP2 DFB 0
CPTMP3 DFB 0
PENDFLG DFB 0 ;char inject fglag for BUFEMP
PENDCHR DFB 0 ;char to inject
EORSEQ DFB 0 ;EOR processing flag
FBUFF DW 0 ;file buffer base pointer
FBPTR DW 0 ;file buffer use pointer
CMDTBL DW 0 ;command table pointer
JMPTBL DW 0 ;action address table base
CURPAR DW 0 ;current param pointer
CURST DFB 0 ;start offset of current par in whole line
CSCRLN DFB 0 ;no of last char in command mode line
RQUOTE DFB 0 ;quote he's sending
EBQCHR DFB 0 ;8 bit prefix we're using
EBQFLG DFB 0 ;flag for using 8 bit prefix
STATE DFB 0 ;protocol state
CHKSUM DFB 0 ;checksum sent/received
CSTEMP DFB 0 ;working checksum
NXTPAK DFB 0 ;next-packet number
NUMTRY DFB 0 ;retry counters
OLDTRY DFB 0
SMAXD DFB 0 ;max DATA length I send him
TFSTOP DFB 0 ;flag for CTRL/X or CTRL/Z seen
BKASENT DFB 0 ;flag for ACK/Z ACK/X sent
WAY DFB 0 ;transfer direction (0=R, 1=S)
CSRX DFB 0 ;X-position of cursor
CSRY DFB 0 ;Y-position
GRMODE DFB 0 ;VT52 graphics mode flag
CHARIN DW 0 ;character disposition vector
ESCYR DFB 0 ;row value sent in ESC-Y sequence
LFSUPP DFB 0 ;LF suppress flag for line-fold-bug
PRINTER DFB 0 ;copy-to-printer flag
VDUCNT DFB 0 ;countdown to end of line
TABEND DFB 0 ;posn of final tab stop in line
EDCRSR DFB 0 ;cursor edit/VT52 mode
STCOPY DW 0 ;address of status line copy
RXPTR DFB 0 ;packet buffer pointers
TXPTR DFB 0
TXDLEN DFB 0 ;data size of packet to go
TXTYPE DFB 0 ;type of packet to go
LPTYPE DFB 0 ;type of packet last sent
PACNUM DFB 0 ;packet number
PACTYP DFB 0 ; type
DATLEN DFB 0 ; length (DATA part only)
XSEOLN DFB 0 ;EOLN I actually send now
XSPADC DFB 0 ;pad char actually sending
XSNPAD DFB 0 ;count of pads actually sending
CURLEN DFB 0 ;size of current parameter
CMDPTR DFB 0 ;analyser position in line
RDLPTR DFB 0 ;RDLINE prompt pointer
NUM DS 5 ;number converter workspace
ASCNUM DS 2
ACTRTN DW 0 ;address of action routine
BRKSRC DFB 0 ;source of BRK (us/error packet)
STKHLP DFB 0 ;stack marker for autohelp
BINWRN DFB 0 ;flag for non-ASCII warning given
PKTCNT DW 0 ;packet count for one file
RTRCNT DW 0 ;retry count for one file
TMOCNT DW 0 ;timeout count for one file
FCOUNT DFB 0 ;files in wildcard group
KBYTET DW 0 ;Kbytes transferred in group
KBYTEC DW 0 ;Kbytes transferred in current file
BYTESC DW 0 ;bytes countdown in current file
IF *>$90
STOP '*** Too much in page 0 ***'
FI
DEND
***************************************
*
* KERMIT DEFINES
* ==============
*
***************************************
MAXPAK EQU 92 ;max size of packet DATA part
KOSBYT EQU 70 ;OSBYTE call used to talk to TXR
***************************************
*
* MISCELLANEOUS DEFINES
* =====================
*
***************************************
XON EQU $11
XOFF EQU $13
CTRLD EQU $04
CTRLE EQU $05
CTRLN EQU $0E
CTRLO EQU $0F
CTRLU EQU $15
CTRLX EQU $18
CTRLZ EQU $1A
FKEY EQU 128 ;base codes for function keys
SFKEY EQU FKEY+16
CFKEY EQU SFKEY+16
CSFKEY EQU CFKEY+16
CHN BBCWKS
****** File BBCFIL *************************************************************
START FIL
* BBCFIL : Updated 10/01/87 @ 1730
***************************************
*
* FOPEN
* =====
*
* Opens a file for read or write
*
***************************************
FOPEN PHA ;save opening mode
IF ROM
*
* See if this is a dummy call, with real data being MEMORY
*
CMP #$80
BEQ FOP100 ;j if writing
LDA SOURCE ;reading, so check source
BPL FOP110
FOP100 LDA DESTIN ;writing, so check destination
FOP110 BEQ FOP120 ;j if FILE
PLA ;else tidy stack
RTS ;and do noting
FI
*
* This is a real call. Set status display to 'opening file'
*
FOP120 LDA #52
JSR PRTSST
*
* Turn on ESCAPE so user can interrupt wait for drive ready (if he's on
* DNFS, of course)
*
JSR ESCON
*
* Now we try to open the file
*
PLA ;reget opening mode
LDX #>LFNAME ;point to filename
LDY #<LFNAME
JSR OSFIND ;open it
BEQ FOP800 ;j if we failed
STA FHAND ;else save the handle
*
* And we can turn ESCAPE off again
*
JSR ESCOFF
*
* Now initialise the file buffer pointers and flags
*
FOP500 LDY #1
STY EOB ;buffer empty
DEY
STY EOF ;not at EOF
LDA FBUFF
STA FBPTR
STA FBTOP
LDA FBUFF+1
STA FBPTR+1
STA FBTOP+1
RTS ;and finish
*
* Here we failed to open the file
*
FOP800 JSR ESCOFF ;make sure ESCAPE is off
BRK ;then bang
DFB 0
ASC 'Not found'
DFB 0
***************************************
*
* FWRITE
* ======
*
* Writes from the file buffer to current
* file
*
***************************************
FWRITE PHA ;save all registers
TXA
PHA
TYA
PHA
*
* Build most of the OSGBPB block
*
JSR MKGBPB
*
* Calculate data size and put into the block
*
LDA FBPTR
SEC
SBC FBUFF
STA GBPBLK+5
LDA FBPTR+1
SBC FBUFF+1
STA GBPBLK+6
*
* Set status display to 'writing disc'
*
LDA #45
JSR PRTSST
*
* And do the write
*
LDA #2
LDX #>GBPBLK
LDY #<GBPBLK
JSR OSGBPB
*
* And finish
*
PLA
TAY
PLA
TAX
PLA
RTS
***************************************
*
* FREAD
* =====
*
* Reads from current file into the file
* buffer
*
***************************************
FREAD PHA ;save all registers
TYA
PHA
TXA
PHA
*
* Build a partial OSGBPB control block
*
JSR MKGBPB
*
* Specify a read size of the whole buffer
*
LDA FBSIZE
STA GBPBLK+5
LDA FBSIZE+1
STA GBPBLK+6
*
* Set status display to 'reading disc'
*
LDA #46
JSR PRTSST
*
* And do a read from the current file position
*
LDA #4
LDX #>GBPBLK
LDY #<GBPBLK
JSR OSGBPB
*
* Did we hit EOF on the way?
*
BCC FRD400 ;j if we did not
*
* We hit EOF, so note for later and close the file
*
CLC ;no buffer flush, of course
JSR FCLOSE ;and close it
LDA #1
STA EOF ;set flag
*
* Now set up the buffer-top pointer
*
FRD400 LDA GBPBLK+1 ;ptr to byte past last one read
STA FBTOP
LDA GBPBLK+2
STA FBTOP+1
*
* And set up the buffer remove pointer
*
LDA FBUFF
STA FBPTR
LDA FBUFF+1
STA FBPTR+1
*
* Clear the 'end of buffer' flag
*
LDA #0
STA EOB
*
* And finish
*
PLA
TAX
PLA
TAY
PLA
RTS
***************************************
*
* NEWFILE
* =======
*
* Creates a new file for output - although
* the "file" may be a memory buffer or
* a printer, unbeknownst to the caller.
*
***************************************
NEWFILE EQU *
*
* Clear the 'renamed' warning line out
*
LDA #20
JSR MESS ;position cursor
JSR SPFILL ;clear to EOLN
*
* Copy the filename the host has sent into the remote filename buffer
*
LDY DATLEN ;get packet data length
LDA #$0D
STA RFNAME,Y ;put a CR at the back
DEY
STY WORK8 ;save offset to last byte
NFL200 LDA RXBUFF,Y ;get byte from packet
STA RFNAME,Y ;move it over
DEY
BPL NFL200 ;j till all moved over
*
* And display it on the status screen
*
JSR DISRFN
*
* Did user give us an explicit local name for this file?
*
LDA LFGIVEN
BNE NFL600 ;j if he did
*
* No explicit local name, so we have to generate one in some way
*
LDA FNTYPE ;get name translation mode
BEQ NFL270 ;j if we translate remote's name
*
* Here user has set UNTRANSLATED mode, so we use the name remote has sent us
* absolutely unchanged
*
LDX #0 ;copy from remote buffer to local
NFL260 LDA RFNAME,X
STA LFNAME,X
CMP #$0D
BEQ NFL450 ;j if CR copied over at end
INX
BNE NFL260 ;else carry on
*
* Here user has set NORMAL name handling, so transkate what remote has sent us into
* an acceptable BBC filename. First work out how long a BBC name can be
*
NFL270 LDX #7 ;assume we're other than ADFS for now
LDA FSNUM ;get filing system number
CMP #8
BNE NFL290 ;j if not ADFS
LDX #10 ;else adjust length of name
NFL290 STX FSNLEN ;and note it
*
* Now let's amend the supplied name
*
LDY WORK8 ;offset to last byte
NFL300 LDA RFNAME,Y ;get byte from name
CMP #'.'
BEQ NFL320 ;j if we find a "."
DEY
BPL NFL300 ;j if not off the front yet
BMI NFL400 ;else there's only one component there
*
* We've located the "." before the last component. Scan backwards to see if we can
* find another "."
*
NFL320 STY WORK9 ;note where we are now
NFL330 DEY ;step back one byte
BMI NFL400 ;j if now off the front
LDA RFNAME,Y ;else get a byte in
CMP #'.'
BNE NFL330 ;j if it's not a "."
*
* Here we've found the start and end of the penultimate or only component,
* so move up to FSNLEN bytes as the local filename
*
NFL400 INY ;move to first byte of component
LDX #0 ;start byte counter
NFL410 LDA RFNAME,Y ;get a byte
STA LFNAME,Y ;and note it
INY
CPY WORK9
BEQ NFL430 ;j if that was last byte of component
INX
CPX FSNLEN
BNE NFL410 ;j if not had FSNLEN bytes yet
DEX ;else step count back one
*
* Add a CR to end of the name
*
NFL430 LDA #$0D
INX
STA LFNAME,X ;add a CR
NFL450 STX LFNLEN ;save pointer to the CR
*
* Then display the local name for the user
*
JSR DISLFN
NFL600 EQU *
*
* If destination is FILE, we now try to actually open the file. If it's
* MEMORY or PRINTER, we've finished, as there isn't a file to open.
*
LDA DESTIN ;get destination flag
BNE NFL900 ;j if not FILE
*
* We open a real file here. Does it exist already?
*
NFL610 JSR FPROBE ;have a look
BCS NFL800 ;j if doen't exist
*
* File exists. Do we trample it or change our name?
*
LDA FWARN ;get warning flag
BEQ NFL620 ;j if we don't rename
LDA LFGIVEN ;else did user give explicit local name?
BEQ NFL660 ;no - we'll rename then
*
* Here we don't rename, but delete the existing file
*
NFL620 JSR ODL100 ;delete it
JMP NFL800 ;then recreate it
*
* Here we must rename our file to miss the existing one. tell the user this
*
NFL660 LDA #20
JSR MESS ;position cursor
LDA #104
JSR MESS ;tell user
*
* And try to change the name a bit
*
NFL670 DEC LFNLEN ;move change pointer back
BMI NFL680 ;j if nothing more we can change
LDX LFNLEN ;else get pointer
LDA #'+'
STA LFNAME,X ;change character to '+'
JSR DISLFN ;show him the new name
*
* Let's see if we now miss existing files
*
JSR FPROBE ;file exist now?
BCS NFL800 ;no - off we go
BCC NFL670 ;ho hum change a bit more then
*
* Here we've changed all we can, and still can't form a unique name
*
NFL680 BRK
DFB 0
ASC "Can't rename"
DFB 0
*
* Here we can open the file for output
*
NFL800 LDA #$80 ;select write mode
JSR FOPEN ;open it
NFL900 RTS ;and finish
***************************************
*
* FPROBE
* ======
*
* Checks for file existence
*
***************************************
FPROBE LDX #>LFNAME ;point to name
LDY #<LFNAME
LDA #$40 ;select read mode
JSR OSFIND ;try an open on the file
CMP #0 ;did it work?
BEQ FPB900 ;no - file doesn't exist
*
* File exists, so close it up and return C=0
*
TAY ;handle into Y
JSR CLOSEY ;close file
CLC
RTS
*
* File doesn't exists here
*
FPB900 SEC
RTS
***************************************
*
* FCLOSE
* ======
*
* Closes the current file
*
***************************************
FCLOSE EQU *
LDA FHAND ;is a file open?
BEQ FCL900 ;j if not - null call
BCC FCL400 ;j if no flush required
JSR FWRITE ;else flush the buffer
*
* Set status display to 'closing file'
*
FCL400 LDA #53
JSR PRTSST
*
* And close it
*
LDA #0 ;select 'close'
LDY FHAND ;get the handle
STA FHAND ;mark file is closed
JSR OSFIND ;and close the file
FCL900 RTS
***************************************
*
* GNXTFIL
* =======
*
* Searches for the next filename to
* match a wildcarded specification
*
***************************************
GNXTFIL EQU *
*
* Set up a block to use on OSFILE calls to find file type
*
LDA #>LFNAME ;just set up name pointer
STA GBPBLK
LDA #<LFNAME
STA GBPBLK+1
*
* Set up transfer address in our OSGBPB block
* And request one file name
*
GNX100 LDA #>LFNLEN ;address
STA GNXBLK+1
LDA #<LFNLEN
STA GNXBLK+2
LDY #$FF
STY GNXBLK+3
STY GNXBLK+4
INY
STY GNXBLK+6 ;one name wanted
STY GNXBLK+7
STY GNXBLK+8
INY
STY GNXBLK+5
*
* Then see if there's another name. We check this by testing the
* 'names NOT transferred' count, since NFS does not return C=1 if no names are
* passed back, contrary to what the manulas imply.
*
LDA #8
LDX #>GNXBLK
LDY #<GNXBLK
JSR OSGBPB
CMP #0 ;does filing system support this call?
BNE GNX900 ;j if it doesn't
LDA GNXBLK+5 ;get count of names NOT transferred
BEQ GNX200 ;j if we did get one
*
* No more names, so return 'fail'
*
SEC
RTS
*
* We have another name. Adjust its length to remove trailing spaces
*
GNX200 LDY LFNLEN ;length returned in call
GNX220 LDA LFNAME-1,Y ;get a byte
CMP #' '
BNE GNX240 ;j if byte not a space
DEY
BNE GNX220
GNX240 STY LFNLEN ;note adjusted length
*
* Add a CR to the end in case we use this name
*
LDA #$0D
STA LFNAME,Y
*
* Start the scan pointers
*
LDX #0 ;wildcarded name
LDY #0 ;file name
*
* Get byte from wildcard name and see if it's a "*"
*
GNX250 LDA WCNAME,Y
CMP #'*'
BEQ GNX500 ;j if it is a *
*
* Not a * wildcard, so see if it matches the filename. We allow
* a # wildcard to match one byte here
*
CPX LFNLEN ;at end of filename?
BEQ GNX100 ;j if so - no match
CMP #'#' ;is wildcard name byte a "#"?
BEQ GNX300 ;j if so - automatic match
EOR LFNAME,X ;else compare bytes
AND #%11011111 ;lose difference in case of chars
BNE GNX100 ;j if mismatch
*
* Bytes match, so move on and see if that's the lot
*
GNX300 INX
INY
CPY WCLEN ;at end of wildcard name?
BNE GNX250 ;j if not - keep going
CPX LFNLEN ;at end of filename too?
BNE GNX100 ;j if not - mismatch
*
* We have a match, so see if it's a file or directory
*
GNX400 LDA #5 ;select "read cat details"
LDX #>GBPBLK ;point control block
LDY #<GBPBLK
JSR OSFILE ;file type now in A
CMP #1 ;is it a file?
BNE GNX100 ;j if not - ignore the entry
*
* We have a matching file, so display the local name
*
JSR DISLFN
*
* Then generate and display a remote name
*
LDY LFNLEN ;get length of local name
JSR MKRNAME
JSR DISRFN
*
* And return success
*
CLC
GNX480 RTS
*
* Here we met a wildcard in the wildcard name. Move to a non-wildcard
* in this name
*
GNX500 INY
CPY WCLEN ;at end of wildcard name?
BEQ GNX400 ;j if so - match
CMP WCNAME,Y ;is next byte a "*"
BEQ GNX500 ;j if so - keep looking
*
* We've come to a non-wildcard now, so try to find this in
* the filename
*
GNX550 CPX LFNLEN ;at end of filename?
BNE GNX555 ;j if not - keep going
JMP GNX100 ;else it's a mismatch
GNX555 LDA WCNAME,Y
CMP LFNAME,X ;else compare bytes
BEQ GNX300 ;j if they're the same
INX
BNE GNX550 ;else keep looking
*
* Here the filing system does not support the OSGBPB call to
* read the directory
*
GNX900 BRK
DFB 0
ASC 'Cat scan not supported'
DFB 0
***************************************
*
* OPTDEL
* ======
*
* Deletes incoming file if incomplete
* and option is DELETE
*
***************************************
OPTDEL LDA DESTIN ;check current destination
BNE OCR900 ;j if not FILE
LDA FINCOM ;else check the option
BNE GNX480 ;j if it's KEEP
*
* We do need to delete. Build a partial OSFILE block using the
* OSGBPB block as a handy place.
*
ODL100 LDA #>LFNAME
STA GBPBLK
LDA #<LFNAME
STA GBPBLK+1
*
* And delete the file
*
LDA #6 ;delete action
LDX #>GBPBLK ;pointer to block
LDY #<GBPBLK
JMP OSFILE ;delete the file
***************************************
*
* OPNCUR
* ======
*
* Opens file whose name is current
* command parameter
*
***************************************
OPNCUR STA WORK5 ;save opening mode
JSR ESCON ;allow ESCAPE to work
*
* Make sure name terminates with a CR
*
LDY CURLEN
LDA (CURPAR),Y ;get char past name
PHA ;save it
LDA #$0D
STA (CURPAR),Y ;change for a CR
LDA WORK5 ;get opening mode
LDX CURPAR ;point to name
LDY CURPAR+1
JSR OSFIND ;try to open the file
*
* Did it work?
*
CMP #0
BNE OCR600 ;j if it did
JMP FOP800 ;else break
*
* File is open, so restore command line to original
*
OCR600 STA WORK5 ;save handle
PLA ;get trampled characer
LDY CURLEN
STA (CURPAR),Y ;put it back
JSR ESCOFF ;turn ESCAPE off again
LDA WORK5 ;reload handle
OCR900 RTS ;and finish
NEXT BBCSB1
****** File BBCGEN *************************************************************
START GEN
* BBCGEN : Updated 28/01/87 @ 2020
***************************************
*
* GET
* ===
*
* Pulls a file from a server
*
***************************************
GET EQU *
*
* Parameter 1 is mandatory, and is the remote filename
*
LDA #32 ;select help text
JSR GETMFN ;get param and check size
*
* Copy the filename to our buffer, and also build an R packet
*
LDY #0
GET100 LDA (CURPAR),Y ;get a byte
STA RFNAME,Y ;into our buffer
STA SCBUFF,Y ;into the server command buffer
INY
CPY CURLEN
BNE GET100 ;j till all moved
*
* Add a CR to the end of our copy
*
LDA #$0D
STA RFNAME,Y
STY WORK6 ;note size of packet data for later
*
* Note we're GET and not RECEIVE, and side enter the receive command code
*
LDA #$FF
STA WORK9
JMP RCVST
***************************************
*
* BYE
* ===
*
* Sends a GL command to a server
*
***************************************
BYE JSR CONFIRM ;check no more parameters
LDX #'L' ;command is 'L'
BYE100 LDA #'G' ;packet type is 'G'
JSR INSCMD ;prepare command packet
CLC ;we don't want an I packet
JMP SRVCMD ;and into state switcher
***************************************
*
* FINISH
* ======
*
* Sends a GF command to a server
*
***************************************
FINISH JSR CONFIRM ;check no more parameters
LDX #'F' ;command is 'F'
BNE BYE100
***************************************
*
* REMOTE
* ======
*
* Handles the REMOTE command
*
***************************************
REMOTE LDX #>REMOPT ;point to option table
LDY #<REMOPT
JSR GMPAS ;get parameter and validate
JMP ACTION ;and implement it
REMOPT DW REMJMP ;address of jump table
CMD 9,'DIRECTORY'
CMD 3,'CWD'
CMD 5,'SPACE'
CMD 6,'DELETE'
CMD 4,'TYPE'
CMD 4,'HELP'
CMD 4,'COPY'
CMD 6,'RENAME'
CMD 3,'WHO'
CMD 4,'HOST'
CMD 6,'STATUS'
DFB 0
REMJMP DW RMDIR ;DIRECTORY
DW RMCWD ;CWD
DW RMSPACE ;SPACE
DW RMDEL ;DELETE
DW RMTYPE ;TYPE
DW RMHELP ;HELP
DW RMCOPY ;COPY
DW RMREN ;RENAME
DW RMWHO ;WHO
DW RMHOST ;HOST
DW RMSTAT ;STATUS
***************************************
*
* REMOTE WHO
* ==========
*
***************************************
RMWHO JSR CONFIRM ;check no more parameters
LDX #'W' ;command is W
RWH100 LDA #'G' ;packet type is G
JSR INSCMD ;prepare to send it
SEC ;I packet wanted
JMP SRVCMD ;and into state switcher
***************************************
*
* REMOTE STATUS
* =============
*
***************************************
RMSTAT JSR CONFIRM ;check no more parameters
LDX #'Q' ;command is Q
BNE RWH100
***************************************
*
* REMOTE HELP
* ===========
*
***************************************
RMHELP LDX #'H' ;command is H
LDA #'G' ;packet type G
JSR INSCMD ;prepare the packet
*
* We pass on the rest of the command line as the help argument
*
LDA #165 ;select help text
JSR GETPAR ;see if there's a parameter
BCS RDR240 ;j if not
JSR MAP100 ;else take all of rest of line as value
JMP RDR200
***************************************
*
* REMOTE DIRECTORY
* ================
*
***************************************
RMDIR LDA #'G' ;packet type is G
LDX #'D' ;command is D
JSR INSCMD ;initialise the packet
*
* Optional parameter is a filespec
*
LDA #161 ;select help text
RDR100 JSR LSTPAR ;get param, check no more
BCS RDR240 ;j if no parameter
*
* Put parameter into the packet and send it
*
RDR200 JSR PAKPRL
RDR230 SEC ;request an I packet
RDR240 JMP SRVCMD
***************************************
*
* REMOTE CWD
* ==========
*
***************************************
RMCWD LDA #'G' ;packet type is G
LDX #'C' ;command is C
JSR INSCMD ;initialise the buffer
*
* Next parameter is optional directory name
*
LDA #197 ;select help text
JSR LSTPAR ;look for param and check no more
BCS RCW500 ;j if no parameter there
JSR PAKPRL ;else put into buffer
*
* User gave directory, so ask him for the password
*
LDA #204
JSR MESS ;prompt him
LDA #0 ;force source to keyboard
STA CSOURCE
TAY ;set buffer pointer up
JSR RDLINX ;read password without echoing
JSR OSNEWL ;tidy the line up
LDA TKHAND ;get TAKE handle or 0
STA CSOURCE ;and restore command source
*
* Adjust things so the analyser thinks the inout line is one parameter
*
LDA #0
STA CURST ;start offset pf param is 0
LDA #>CMDBUF ;set up start of parameter string
STA CURPAR
LDA #<CMDBUF
STA CURPAR+1
JSR MAP100 ;set up length to be whole line
JMP RDR200 ;and send it
*
* No directory, so don't ask for password
*
RCW500 SEC ;I packet wanted
JMP SRVCMD
***************************************
*
* REMOTE DELETE
* =============
*
***************************************
RMDEL LDX #'E' ;command is E
RDE100 LDA #'G' ;packet type is G
JSR INSCMD ;prepare the packet
*
* Next parameter is the file name
*
LDA #32 ;select help text
RDE200 JSR LSTMPAR ;get param, check no more
JMP RDR200 ;then handle it
***************************************
*
* REMOTE TYPE
* ===========
*
***************************************
RMTYPE LDX #'T' ;command is T
BNE RDE100
***************************************
*
* REMOTE RENAME
* =============
*
***************************************
RMREN LDX #'R' ;command is R
RRN100 LDA #'G' ;packet type is G
JSR INSCMD ;initialise packet
*
* First parameter is the old filename
*
LDA #162 ;select help text
JSR GETMPAR ;get the parameter
JSR PAKPRL ;put it into the packet
*
* Next parameter is the new filename
*
LDA #164 ;select help text
BNE RDE200 ;share code with REMOTE DELETE
***************************************
*
* REMOTE COPY
* ===========
*
***************************************
RMCOPY LDX #'K' ;command is K
BNE RRN100
***************************************
*
* REMOTE HOST
* ===========
*
***************************************
RMHOST LDA #'C' ;packet type is C
JSR INSCMD ;initialise the packet
LDA #166 ;select help text
JSR MALLPAR ;get rest of line as parameter
JSR PAKPAR ;packet it with no length encoding
JMP RDR230 ;and send it
***************************************
*
* REMOTE SPACE
* ============
*
***************************************
RMSPACE LDA #'G' ;packet type is 'G'
LDX #'U' ;command is U
JSR INSCMD ;initialise packet
LDA #168 ;select help text
JMP RDR100 ;then act as REMOTE DIR
***************************************
*
* INSCMD
* ======
*
* Initialises server command buffer, etc, for a
* server command packet of type A with command
* X
*
***************************************
INSCMD STA TXTYPE ;save packet type
LDY #0
STY TXPTR ;start buffer pointer
STY TXDLEN ;start packet data length
CMP #'G' ;is packet type G?
BNE ICD900 ;j if not
TXA
STA SCBUFF,Y ;else put command into packet
INC TXPTR ;step buffer pointer
INC TXDLEN ;and packet data length
ICD900 RTS
***************************************
*
* SRVCMD
* ======
*
* Initiates sending a server command
*
***************************************
SRVCMD LDA #%10000000 ;set mode to 'generic'
STA MODE
*
* If source is a TAKE file, do a brief delay in case we're
* talking to VAX/VMS which can't handle packets if they come too fast
*
SRV100 PHP ;save I packet request
JSR TAKDEL ;delay or not
PLP
*
* Now go either to state I or state G
*
BCC SRV500 ;j if no I packet wanted
LDA #'I' ;else set inital state to I
BNE SRV900
SRV500 LDA #'G'
SRV900 JMP RECSW ;and enter the receive switcher
CHN BBCST1
****** File BBCMAI *************************************************************
START MAI
* BBCMAI: Updated 24/02/87 @ 1200
IF RAM
****************************************
*
* RAM HEADER
* ==========
*
* This is the start of the RAM version.
* If you make patches to it, place them
* from PRGTOP upwards. You MUST then
* change the address stored here at
* PTPPTR to point the next byte after your
* patch, or the patch will be trampled
* by the file buffer.
*
***************************************
MSW $FFFF ;must run in i/o processor
ORG $1F00 ;avoid econet and such
JMP MAIN ;JMP to make dehexer easy
DFB MARK ;mark number
DFB VERSION ;version number
DW DEFTAB ;address of defaults block
PTPPTR DW PRGTOP ;first byte past image and patches
ASC '(C)1987 CUCCA/Lancaster '
ASC 'By A. Phillips'
ELSE
***************************************
*
* ROM HEADER
* ==========
*
* This is the start of the language
* ROM
*
***************************************
MSW $FFFF ;so we *LOAD to IO processor sideways RAM
ORG $8000
JMP MAIN ;language entry point
JMP SENTRY ;service entry point
DFB %11000010 ;ROM type byte
DFB CPRMES-$8000 ;copyright offset
DFB MARK ;mark number
TITLE ASC 'KERMIT' ;ROM title
ROMCLN EQU *-TITLE-1
DFB 0
DFB MARK+$30
DFB '.'
DFB VERSION/10+$30
DFB (VERSION-(VERSION/10*10))+$30
CPRMES DFB 0
ASC '(C)1987 CUCCA/Lancaster'
DFB 0
DFB MARK ;mark number
DFB VERSION ;version number
DW DEFTAB ;address of defaults block
DW PRGTOP ;first byte past image
ASC 'By A. Phillips'
***************************************
*
* SERVICE ENTRY
* =============
*
* We pick up service entry calls here
*
***************************************
SENTRY PHA ;save registers
TXA
PHA
TYA
PHA
TSX
LDA $103,X ;reload original A
*
* We look for a type 4 entry, 'unrecognised command', or a
* type 9, '*HELP', or type 5, 'interrupt'
*
CMP #5
BEQ SEN200 ;j if interrupt
CMP #4
BEQ SEN400 ;j if command
CMP #9
BNE SEN900 ;j if not then *HELP
*
* Here it's *HELP, so maybe we print our title
*
SEN100 LDA ($F2),Y ;look at what's past the "*HELP"
CMP #' '
BNE SEN120 ;j if not a space
INY
BNE SEN100 ;else keep looking
SEN120 CMP #$0D ;if non-space is not CR there's a sub-topic on
BNE SEN900 ;line, so we ignore the call
LDA #223
JSR MESS ;else print our title
JMP SEN900
*
* Here it's an unrecognised interrupt. Service it if we are
* the current language ROM. Note that the clean way to tell if we are
* current language is with OSBYTE $FC, but it's too slow, so we have to look at the
* OS RAM table directly
*
SEN200 LDX $F4 ;get our ROM number
CPX $28C ;are we current language?
BNE SEN900 ;j if not - do nothing
JMP IRQENT ;and into our interrupt handler
*
* Here it's an unrecognised command, so look for "*KERMIT"
*
SEN400 LDX #0 ;pointer to our title
SEN420 LDA ($F2),Y ;get byte from command
JSR UPPER ;force upper case
CMP TITLE,X
BNE SEN480 ;j if mismatch
INX
INY
CPX #ROMCLN
BNE SEN420 ;j if more to go
*
* Command is "KERMIT", so activate ourselves
*
SEN440 LDA #$FF ;set flag to show language entry
STA STARTUP
LDA #$8E
LDX $F4 ;then get our ROM number
JMP OSBYTE ;and enter ourselves
*
* Input line mismatches search. If we've had at least one match,
* we'll take a "." as matching OK
*
SEN480 CPX #0
BEQ SEN900 ;j if first char mismatched
CMP #'.' ;else is current char a "."?
BEQ SEN440 ;j if so - call it a match
*
* All done, so return with registers intact
*
SEN900 PLA
TAY
PLA
TAX
PLA
RTS
FI
***************************************
*
* MAIN
* ====
*
* This is the initialisation and control
* routine for KERMIT
*
***************************************
MAIN EQU *
IF RAM
LDA #$FF ;set flag to show first entry
STA STARTUP
MAI010 SEI ;turn IRQ off if RAM to keep tidy
FI
LDX #$FF
TXS ;set up the stack
*
* For now, point the BRK vector to a loop stop
*
LDA #>MAI900
STA BRKV
LDA #<MAI900
STA BRKV+1
IF ROM
*
* Make sure user isn't running us in a second processor
*
LDA #$EA
JSR RSYSVAL ;read TUBE flag
TXA
BEQ MAI050 ;j if TUBE not on
BRK ;else BRK and loop stop
DFB 0
ASC 'Not on TUBE'
DFB 0
ELSE
*
* Change start up mode to 7 in case user hits BREAK with it at something
* that may corrupt us
*
LDA #$FF
LDY #%11111000
LDX #7
JSR OSBYTE
*
* Then point the BREAK intercept to us
*
JSR NOBINT ;remove the JMP while we do it
LDA #$F8 ;then set the address
LDX #>BREAK
JSR OBX0
LDA #$F9
LDX #<BREAK
JSR OBX0
LDA #$F7 ;and put the JMP in
LDX #$4C
JSR OBX0
FI
*
* Disable the ESCAPE key
*
MAI050 JSR ESCOFF ;now generates $1B
*
* Now see if we need to initialise the workspace
*
BIT STARTUP ;test startup flag
IF RAM
BPL MAI300 ;j if restarted from BREAK
ELSE
BMI MAI090 ;j if language entry
JSR RDBTYP ;else look at BREAK type
TXA
BEQ MAI300 ;j if soft BREAK
FI
*
* Here we do need to clean up the workspace
*
MAI090 LDA #0
TAY
MAI100 STA WKBASE,Y
STA WKBASE+$100,Y
STA WKBASE+$200,Y
STA WKBASE+$300,Y
INY
BNE MAI100
*
* Also make sure page 0 from $00 to $8F is clear
*
LDX #0
MAI120 STA $0,X
INX
CPX #$90
BNE MAI120
*
* Set default values up
*
JSR DEFAULT
MAI300 JSR FLUSH ;clear the comms buffer
JSR GETACIA ;take control of 6850
JSR SETACIA ;and set it up as we need
IF ROM
*
* Now locate the system's extended vector table
*
LDA #$A8
JSR RSYSVAL ;find where it is
STX EVECTB ;save pointer to it
STY EVECTB+1
FI
*
* Force vectors back to power on state
*
JSR STDVEC
*
* Note the type of OS (and hence the machine) in use
*
LDA #0
JSR OB10 ;get value in X
DEX ;scale to 0=model B
STX OSTYPE
IF RAM
*
* If RAM set the type flag to $FF
*
LDA #$FF
STA PTYPE
*
* If RAM and we're running in a B+ or Master, turn shadow mode on
*
LDA #0
STA SHADOW ;assume no shadow capability
LDX OSTYPE
BEQ MAI350 ;j if model B (OS 1)
LDA #114
JSR OB00 ;else turn shadow on at next mode change
STX ENTSHAD ;and note what it was before
DEC SHADOW ;note we have shadow capability
ELSE
*
* If ROM and on a B+ or Master, turn shadow mode off
*
LDA #0
STA SHADOW ;no shadow capability
LDX OSTYPE
BEQ MAI350 ;j if model B (OS 1)
LDA #114
JSR OB10 ;else turn shdow off at mode change
STX ENTSHAD ;note what it was before
FI
*
* Clear the flag that indicates a BRK is an error packet
*
MAI350 LDA #0
STA BRKSRC
*
* Adjust terminal type to an appropriate one if it's on its
* "use default" setting after a cold start
*
JSR ADJTT
*
* Note the filing system current
*
JSR WHATFS
IF RAM
*
* Adjust OSHWM to be above the KERMIT program area and patches
*
LDA #$B4
LDX PTPPTR+1
INX
JSR OBX0 ;change to new setting
STX OLDHWM ;and note previous value
FI
*
* Set up address of the SET block in case a TXR might want to know
*
LDA #>DFBASE
STA DEFPTR
LDA #<DFBASE
STA DEFPTR+1
*
* And finally enter the command mode routine which will enable IRQ
*
MAI600 LDA #1 ;set command mode to use 40 byte screen
STA CWIDTH
JMP CMDMODE ;and enter command processor
*
*
* Routine to handle BRK in initialisation phase
*
MAI900 JSR BRKTXT ;print the text
MAI910 JMP MAI910 ;and loop-stop
IF RAM
***************************************
*
* BREAK INTERCEPT
* ===============
*
* BREAK key is directed here
*
***************************************
BREAK BCC BAK900 ;j if pre-init call
*
* If this was a CONTROL-BREAK we will not restart
*
JSR RDBTYP ;read last BREAK type
CPX #2
BNE BAK200 ;j if not CONTROL-BREAK
JMP NOBINT ;else lose BREAK intercept and finish
*
* Not a CONTROL-BREAK so we re-enter ourselves
*
BAK200 LDA #$8F ;issue sideways ROM call to restart the
LDX #$12 ;filing system that was there when we started
LDY FSNUM
JSR OSBYTE
JMP MAI010 ;and restart ourselves
BAK900 RTS
FI
***************************************
*
* OB00, OBX0
* ==========
*
* Does OSBYTE with X=0, Y=0 (OB00) or
* with Y=0 (OBX0)
*
***************************************
OB00 LDX #0
OBX0 LDY #0
JMP OSBYTE
***************************************
*
* OB10
* ====
*
* Does OSBYTE with X=1, Y=0
*
***************************************
OB10 LDX #1
BNE OBX0
***************************************
*
* DOKOSB
* ======
*
* Does OSBYTE to talk to TXR with Y=0
*
***************************************
DOKOSB LDA #KOSBYT
BNE OBX0
IF RAM
***************************************
*
* NOBINT
* ======
*
* Clears the BREAK intercept
*
***************************************
NOBINT LDA #$F7
JMP OB00 ;ensure a $00 where a $4C is expected
FI
***************************************
*
* RSYSVAL
* =======
*
* OSBYTE with X=0, Y=$FF to read value
*
***************************************
RSYSVAL LDY #$FF
LDX #0
JMP OSBYTE
***************************************
*
* RDBTYP
* ======
*
* Reads type of last BREAK
*
**************************************
RDBTYP LDA #$FD
BNE RSYSVAL
**************************************
*
* DEFAULT VALUES
* ==============
*
* Initial protocol and control values
* are taken from this table
*
**************************************
DEFTAB DFB 7 ;transmit baud rate 9600
DFB 7 ;receive baud rate 9600
DFB 0 ;local echo off
DFB 0 ;obsolete byte (1.03)
DFB 0 ;debug flag off
DFB 0 ;obsolete byte (1.03)
DFB 15 ;timeout he uses on me
DFB 15 ;timeout I use on him
DFB 0 ;timer is off
DFB 0 ;pause after packet read
DFB 30 ;delay after send
DFB 0 ;obsolete byte (1.40)
DFB 0 ;obsolete byte (1.40)
DFB 0 ;keyclick off
DFB '#' ;quote I send
DFB '&' ;preferred 8 bit prefix
DFB $0D ;EOLN I send
DFB $0D ;EOLN he sends
DFB 0 ;pad character I send
DFB 0 ;number of them
DFB 0 ;pad character he sends
DFB 0 ;number of them
DFB 1 ;parity SPACE
DFB 0 ;file type ASCII
DFB 0 ;EOR type LFCR
DFB 0 ;data source FILE
DW 0 ;source memory base
DW 0 ;source memory top
DFB 0 ;data destination FILE
DW 0 ;dest memory base
DW 0 ;dest memory top
DFB $01 ;start of packet I send
DFB $01 ;start of packet he sends
DFB 94 ;max packet length I want in
DFB 16 ;file buffer is 16 pages
DFB 1 ;file warning on
DFB 0 ;incomplete file DELETE
DFB 0 ;flow control XON/XOFF
DFB 3 ;file suffix length
ASC 'BBC ' ;file suffix string
DFB 1 ;TAKE echo on
DFB 7 ;VDU text colour 7 (white)
DFB 1 ;do *TV for terminal mode
DFB 0 ;with parameters 0...
DFB 1 ;...and 1
DFB 0 ;VDU ignore character off
DFB 0 ;space for char to ignore
DFB 0 ;MUX wait 0 byte periods
DFB '?' ;autohelp triggered by '?'
DFB 5 ;max retries allowed
DFB 0 ;no handshaking used
DFB $FF ;set terminal to suit machine
DFB 0 ;file name translation normal
DEFCNT EQU *-DEFTAB ;size of defaults table
IF DEFCNT-DFSIZE
INFO '** Default table size wrong **'
FI
***************************************
*
* BRKH
* ====
*
* This is the BRK handler
*
***************************************
BRKH EQU *
*
* Make sure the system is nice and clean
*
JSR ACKESC ;ACK any ESCAPE outstanding
JSR OPVDU ;ensure VDU is selected
JSR PRTOFF ;ensure printer if off
JSR GETACIA ;take over 6850
JSR LOSESYS ;set known state
JSR GETSYS ;and take over
*
* If command source is a TAKE file, we close it
*
JSR CLTAKE
*
* Make sue any TRANSMIT file is closed
*
JSR CLTXF
*
* If terminal, transfer or generic mode we bleep
*
BRK100 LDA MODE
BEQ BRK120 ;j if command mode
LDA #7
JSR OSWRCH ;else toll the bell
*
* If command, terminal or generic mode, output goes on next line down
*
BRK120 LDA MODE
CMP #%11000000
BEQ BRK600 ;j if transfer mode
JSR TIDYLN ;else ensure we're on a clean line
JSR BRKTXT ;print the text
JSR OSNEWL
*
* If this is generic mode, maybe we send an E packet to the other end
*
BIT MODE
BMI BRK615 ;j if generic mode
*
* It's command or terminal mode : if terminal mode, make sure the log file are closed
*
LDA MODE
CMP #1
BNE BRK400 ;j if not terminal mode
LDY LHAND ;is log file open?
BEQ BRK400 ;j if not
LDA #0
STA LHAND ;else clear out handle
STA LOGON ;clear the log toggle
JSR OSFIND ;and close the file
*
* Now wind stack back to restart point and jump to the
* restart vector
*
BRK400 LDA #0 ;clear the error packet idicator
STA BRKSRC
BRK500 LDX STKRST
TXS
JMP (RESTART)
*
* Here we're in transfer mode, so status screen is up and the
* text goes to a specific place
*
BRK600 LDA #12
JSR MESS ;position and say 'fatal error'
JSR BRKTXT ;and print the text
*
* Make sure any files open are closed. Because DFS 2.24 screws up
* on "close all files" we close the transfer file (which might be open for
* writing) explicitely first
*
LDY FHAND ;do we have a transfer file?
BEQ BRK615 ;j if not
LDA #0
JSR OSFIND ;else close it
LDY #0 ;then close all the rest
JSR CLOSEY
*
* Do we have to delete an incoming incomplet file now?
*
LDA FHAND ;check handle
BEQ BRK615 ;j if no file open
LDA WAY ;check transfer direction
BNE BRK615 ;j if we'1re SEND here
*
* Well, we are receiving, so we might have to
*
JSR OPTDEL ;delete if needed
*
* Do we now send this text as an error packet to the other end?
*
BRK615 LDA BRKSRC ;is text an error packet from other side?
BNE BRK900 ;j if so - don't send it back!
*
* BRK was issued by us, so send to the other end. Copy text to TXBUFF
*
INC $FD ;point to start of text
BNE BRK620
INC $FE
BRK620 LDY #0
BRK630 LDA ($FD),Y ;get a byte
BEQ BRK640 ;j if end of text
STA TXBUFF,Y ;else store it
INY ;move pointer on
CPY #81
BNE BRK630 ;j if packet not yet full
*
* And send the error packet
*
BRK640 STY DATLEN ;save size of data part
LDA #'E' ;get type
LDX NXTPAK ;and number
JSR SPACK ;send it
LDA #51
JSR PRTSST ;set screen status to "idle"
*
* If transfer mode we wait for a keypress and restart
*
BRK900 BIT MODE
BVC BRK400 ;j if not transfer mode
JSR WTCMODE ;else wait a bit
JMP BRK400
***************************************
*
* EVENT
* =====
*
* This handles the timer event
*
***************************************
EVENT CMP #5 ;timer event?
BNE EVE900 ;j if not - ignore
*
* We've had a one-second tick here
*
PHA ;save things
TXA
PHA
TYA
PHA
LDA TICKER ;has timer expired?
BEQ EVE800 ;j if so
DEC TICKER ;else step it down
JSR CLOCK ;and reset the clock interval
*
* And finish
*
EVE800 PLA
TAY
PLA
TAX
PLA
EVE900 RTS
CHN BBCCPR
****** File BBCPM1 *************************************************************
START PM1
* BBCPM1: Updated 12/08/86 @ 1500
***************************************
*
* BUFEMP
* ======
*
* Takes bytes from a data packet and
* puts them into the file buffer or on
* the screen
*
***************************************
BUFEMP EQU *
*
* Initialise pointers to the receive packet buffer and set up
* length counts, etc
*
JSR INIRPK ;byte count in X now
BEQ BEM350 ;j if no data
*
* Get next byte from packet
*
BEM100 LDY #0
STY WORK9 ;assume B7 will be clear later
BEM120 LDY RXPTR ;get remove pointer
LDA RXBUFF,Y ;get char from packet
INC RXPTR ;step pointer for next time
*
* Is this character special?
*
CMP RQUOTE
BEQ BEM500 ;j if it's quote character
BIT EBQFLG ;are we 8 bit prefixing?
BPL BEM150 ;j if not
CMP EBQCHR ;else is char the prefix in use?
BEQ BEM400 ;j if it is
*
* We've got the char in A and the B7 setting in WORK9. Do we do still more?
*
BEM150 ORA WORK9 ;set B7 up
BMI BEM260 ;j if set - no more to so
LDY FTYPE ;else look at file type
BNE BEM260 ;j if binary - no more to do
BIT MODE ;are we doing server command (generic mode)?
BVC BEM260 ;j if so -also no more to do
*
* File is ASCII, so we're on the look out for CRLF
*
LDY EORTYPE ;how do we do EOR here?
CPY #1
BEQ BEM260 ;we're CRLF too, so no action
BIT PENDFLG ;else was last char a CR?
BPL BEM250 ;j if not
*
* Last char was a CR. Is this one an LF then?
*
CMP #$0A
BNE BEM180 ;j if not
*
* Host has sent CRLF, so translate this into the specified EOR sequence
*
LDA EOR
JSR TOFILE ;always one byte
LDA EOR+1
BEQ BEM160 ;j if only one
BEM155 JSR TOFILE ;else write the second one too
BEM160 INC PENDFLG ;set flag to 0
BEQ BEM300 ;get next byte in from packet
*
* We had a CR last time, but this byte isn't LF
*
BEM180 PHA ;save the byte
LDA #$0D ;and put the CR into the file
JSR TOFILE
PLA ;reload data byte
JMP BEM155 ;and wrie it, too
*
* Previous character wasn't a CR. Is this one a CR then?
*
BEM250 CMP #$0D
BNE BEM260 ;j if not
DEC PENDFLG ;else set flag to $FF
BMI BEM300 ;and get next byte
BEM260 JSR TOFILE ;else write bye to file
*
* Move to next packet byte, if there is one
*
BEM300 DEX
BNE BEM100 ;j if more to do
BEM350 RTS ;else finish
*
* Here we've met an 8-bit quote character
*
BEM400 LDA #%10000000
STA WORK9 ;note B7 on for later
DEX ;decrement chars-left count
JMP BEM120 ;and do next char, noting it's got B7 set
*
* Here we met a quote character
*
BEM500 LDY RXPTR
LDA RXBUFF,Y ;get following character
INC RXPTR ;step get pointer past quoted char
DEX ;decrease count of bytes left
BIT EBQFLG ;are we 8 bit prefixing?
BPL BEM520 ;j if not
*
* Is the quoted character the 8-bit-prefix in use? (here we know the
* character has B7 clear as we are actually doing 8-bit-prefixing..)
*
CMP EBQCHR
BEQ BEM150 ;j if it is
*
* Is the quoted character the quote itself? At this point we may have B7 set in the character,
* so be sure we check only ls 7 bits
*
BEM520 TAY ;save character a moment
AND #%01111111 ;lose B7
CMP RQUOTE
BNE BEM600 ;j if B6-0 not the quote character
TYA ;else get original back
JMP BEM150 ;and output to file as is
*
* Here the quoted character isn't anything special, so just flip B6 and output it
*
BEM600 TYA ;get original back
EOR #%01000000 ;flip B6
JMP BEM150 ;and output it
***************************************
*
* TOFILE
* ======
*
* Writes a byte into the file buffer or
* to the screen, or to the printer
*
***************************************
TOFILE PHA ;save registers
TYA
PHA
TXA
PHA
TSX
LDA $103,X ;get data byte back
BIT MODE ;in generic mode for server command?
BVC TOF600 ;j if so
*
* It's a transfer, so is it to the printer directly?
*
LDX DESTIN ;get destination flag
CPX #2
BNE TOF100 ;j if not to printer
PHA ;else save data byte
JSR OPPTR ;select parallel printr
PLA
JSR OSWRCH ;print the character
JSR OPVDU ;reselect VDU
JSR COUNTB ;count this byte
JMP TOF900 ;and finish
*
* Transfer is to file or memory, so put byte into the buffer
*
TOF100 LDY #0 ;else put character into buffer
STA (FBPTR),Y
JSR COUNTB ;count the byte
*
* Step buffer pointer and see if it's now full
*
INC FBPTR
BNE TOF200
INC FBPTR+1
TOF200 LDA FBPTR+1
CMP FBMAX+1
BNE TOF500 ;j if not full
LDA FBPTR
CMP FBMAX
BNE TOF500 ;j if not full
*
* Buffer is full, so write and reset it
*
LDA #39
JSR DMESS ;send diagnostic text
*
* If destination is memory, we error since that's all there's room for
*
LDA DESTIN
BEQ TOF300 ;j if to file
BRK ;else crunch
DFB 0
ASC 'Memory full'
DFB 0
*
* Destination is file, so write buffer away
*
TOF300 JSR FWRITE ;write the buffer
LDA FBUFF ;reset the pointer
STA FBPTR
LDA FBUFF+1
STA FBPTR+1
TOF500 JMP TOF900 ;and finish
*
* Here we're doing a server command, so put the byte on the screen
*
TOF600 CMP #$0D
BEQ TOF680 ;j if CR
CMP #$0A
BEQ TOF685 ;j if LF
CMP #$09
BEQ TOF690 ;j if TAB
CMP #$7F
BEQ TOF695 ;j if DEL
CMP #$08
BEQ TOF695 ;j if BS
CMP #$0C
BEQ TOF700 ;j if FF
CMP #32
BCS TOF650 ;j if not other control char
JMP TOF900 ;else ignore it
*
* Not control, so just print it
*
TOF650 JSR CHROUT ;print character
JMP TOF900
*
* Here it was a control character that we accept
*
TOF680 JSR CROUT ;CR
JMP TOF900
TOF685 JSR LFOUT ;LF
JMP TOF900
TOF690 JSR TABOUT ;TAB
JMP TOF900
TOF695 JSR DELOUT ;DEL or BS
JMP TOF900
TOF700 JSR OSWRCH ;FF
JSR VDUINI
*
* And exit
*
TOF900 PLA
TAX
PLA
TAY
PLA
RTS
***************************************
*
* BUFILL
* ======
*
* Takes bytes from the file buffer and
* builds packet data. SMAXD holds max
* DATA size remote wants, less 1 as we
* count from 0, less another 2 to make
* sure we don't split a quote sequence
* across packets. This is a rather conservative
* approach, but it saves having to do a
* look ahead, as the maximum length of a
* quote sequence is 3 (i.e. "<char>")
* and we will always have space available
* for it.
*
***************************************
BUFILL EQU *
*
* Do we need to read data into the buffer first?
*
IF ROM
LDA SOURCE ;is source MEMORY
BNE BUF020 ;j if so - no file to read
FI
LDA EOB ;look at buffer state flag
BEQ BUF020 ;j if not empty
JSR FREAD ;else read some in
*
* Set up pointers to the transmit packet data buffer
*
BUF020 LDA #0
STA TXPTR
*
* Is a byte pending from last time round?
*
BUF050 BIT PENDFLG
BPL BUF060 ;j if not
INC PENDFLG ;else clear flag to 0
LDA PENDCHR ;get the pended character
STA WORK9 ;pretend we read it normally
JMP BUF300 ;and inject it
*
* OK, we need to get a byte
*
BUF060 EQU *
*
* Gets bytes from the buffer. Have we exhausted it?
*
LDA FBPTR
CMP FBTOP
BNE BUF115 ;j if not
LDA FBPTR+1
CMP FBTOP+1
BNE BUF115 ;j if not
*
* Buffer is exhausted, so read some more from the file (if we have one)
*
LDA #40
JSR DMESS ;log this
IF ROM
LDA SOURCE
BNE BUF100 ;j if source is MEMORY
FI
LDA EOF ;are we at EOF here?
BNE BUF100 ;j if so - no more data
JSR FREAD ;else read the file
JMP BUF060 ;and process what we got, if anything
*
* EOF hit. Was last char we saw the star of an EOR sequence?
*
BUF100 INC EORSEQ
BEQ BUF240 ;j if so - write it to packet
*
* Now back to caller, setting up length of the packet we've built
*
BUF105 LDY TXPTR ;get packet pointer
BEQ BUF110 ;j if packet empty
STY TXDLEN
CLC ;return 'packet built'
RTS
*
* Here packet is empty, so tell caller
*
BUF110 SEC
RTS
*
* Here we've not exhausted the buffer, so get a byte
*
BUF115 JSR COUNTB ;count the byte
LDY #0
LDA (FBPTR),Y ;get the byte
*
* Make a note of the byte jusr obtained
*
BUF118 STA WORK9 ;save it
STY WORK8 ;assume B7 clear at the end
INC FBPTR ;move the pointer
BNE BUF120
INC FBPTR+1
*
* Do we need to watch for end-of-record?
*
BUF120 LDY FTYPE ;get type of file
BNE BUF300 ;j if binary - no action
*
* Yes we do. Is this char the first in the EOR sequence?
*
CMP EOR
BNE BUF220 ;j if not
LDY EOR+1 ;else is ther a second byte too?
BEQ BUF200 ;j if not - EOR is CR or LF
DEC EORSEQ ;else set flag to $FF
BNE BUF060 ;and look at next byte
*
* We've found end of record, so send a CRLF
*
BUF200 LDA #$0D
STA WORK9 ;change char to send to be a CR
DEC PENDFLG ;set pending flag to $FF
LDA #$0A
STA PENDCHR ;and pend an LF
JMP BUF500 ;and output the CR
*
* Byte wasn't the first in the EOR sequence. Are we looking for the second?
*
BUF220 BIT EORSEQ
BPL BUF300 ;j if not - send the byte
INC EORSEQ ;else clear the flag to 0
CMP EOR+1 ;is it the byte looked for?
BEQ BUF200 ;j if so - output CRLF
*
* We saw byte 0 of the EOR sequence, but not byte 1. Write the first byte to the
* packet and pend the current data byte
*
BUF240 STA PENDCHR ;pend the data in now
DEC PENDFLG ;set pend flag to $FF
LDA EOR
STA WORK9 ;inject first byte of EOR sequence
BNE BUF500 ;j always
*
* Does the character need special treatment?
*
BUF300 LDA WORK9 ;get it back
BMI BUF400 ;j if B7 is on
BUF320 CMP SQUOTE
BEQ BUF550 ;j if it's the quote character
BUF325 CMP #32
BCC BUF500 ;j if it's a control char
CMP #127
BEQ BUF500 ;j if it's DEL
BIT EBQFLG ;are we 8 bit prefixing?
BPL BUF380 ;j if not - char isn't special
CMP EBQCHR ;else is it the prefix in use?
BEQ BUF700 ;j if it is
*
* Character is non-controversial, so stuff it up the buffer
*
BUF380 ORA WORK8 ;put B7 into it
JSR BUF800 ;into the buffer
*
* Is the packet buffer now full?
*
BCS BUF105 ;j if it is
JMP BUF050 ;j if not
*
* Character has B7 set, so we might 8-bit quote it
*
BUF400 BIT EBQFLG
BMI BUF480 ;j if 8 bit prefix in use
LDY PARITY ;else look at our parity
CPY #4
BEQ BUF490 ;j if NONE - can send 8 bits
*
* We can't send 8 bits and can't prefix, so warn user of loss
*
BIT BINWRN ;warned already?
BMI BUF450 ;j if so
DEC BINWRN ;else set flag to $FF
LDA #11
JSR MESS ;and write warning out
*
* Now strip off B7 and packet the byte
*
BUF450 LDA WORK9 ;get data back and lose B7
BUF455 AND #%01111111
STA WORK9
BPL BUF320 ;and put into packet
*
* Here data is 8 bit, but we can prefix it
*
BUF480 LDA EBQCHR ;get prefix char
JSR BUF800 ;packet the prefix
JMP BUF450 ;send data character as 7 bits
*
* Here data is 8 bit, and we can send it all (parity none)
*
BUF490 LDY #$80
STY WORK8 ;note B7 on at the end
BMI BUF455 ;check ls 7 bits for specials
*
* Here the character is a control character, so quote it
*
BUF500 LDA SQUOTE
JSR BUF800 ;output a quote
LDA WORK9 ;get the character back
EOR #%01000000 ;flip control bit
JMP BUF380 ;and put into buffer
*
* Here it's the quote character. Put it in the buffer twice
*
BUF550 JSR BUF800
JMP BUF380
*
* Here char is the 8 bit prefix in use, so quote it
*
BUF700 PHA ;save char
LDA SQUOTE
JSR BUF800 ;put a quote in the buffer
PLA ;reget character
BNE BUF380 ;and output it itself
*
*
*
* Routine to put character into packet data buffer
*
BUF800 LDY TXPTR
STA TXBUFF,Y ;put char away
INY
STY TXPTR ;move pointer on
CPY SMAXD ;see if past end point
RTS
***************************************
*
* INPARS
* ======
*
* Analyses remote's init params sent in
* response to ours
*
***************************************
INPARS SEC ;note we've sent ours
JSR RPAR ;extract host's parameters
*
* Host may have defaulted some values, so check them
*
LDA XSEOLN
BNE IPR200 ;j if he gave his EOLN
LDA SEOLN ;else get the SET value
STA XSEOLN ;and use this
IPR200 LDA RQUOTE
BNE IPR900 ;j if he gave his quote
LDA #'#'
STA RQUOTE ;else set to "#"
IPR900 RTS ;and finish
NEXT BBCPM2
****** File BBCPM2 *************************************************************
START PM2
* BBCPM2: Updated 28/01/87 @ 2030
***************************************
*
* RPACK
* =====
*
* Receives a packet
*
***************************************
RPACK EQU *
*
* Send a diagnostic header if necessary
*
LDA #1
JSR DMESS
*
* Set status on screen to 'waiting'
*
LDA #23
JSR PRTSST
* Read data until we find start-of-packet
*
RPA100 JSR RXBYTE
BCC RPA110 ;j if not keyboard CR or timeout
JMP RPA900
RPA110 CMP RSOP
BNE RPA100 ;j if not SOP
*
* SOP seen, so set state on the screen to 'receiving'
*
LDA #25
JSR PRTSST
*
* Now we'll read the packet length byte in
*
RPA120 JSR RXBYTE
BCC RPA130 ;j if not keyboard CR or timeout
JMP RPA900
RPA130 JSR DBYTE ;log the byte
CMP RSOP
BNE RPA140 ;j if byte is not SOP again
JMP RPA800
RPA140 CMP REOLN
BNE RPA150 ;j if it's not sender's EOLN
JMP RPA820
RPA150 STA CHKSUM ;else start the checksum
JSR UNCHAR ;de-char it
STA DATLEN ;and save it
*
* Next comes the packet sequence number
*
JSR RXBYTE
BCC RPA200 ;j if not keyboard CR or timeout
JMP RPA900
RPA200 JSR DBYTE ;log it
CMP RSOP
BNE RPA220 ;j if it's not SOP again
JMP RPA800
RPA220 CMP REOLN
BNE RPA240 ;j if not sender's EOLN
JMP RPA820
RPA240 PHA ;else save it
CLC
ADC CHKSUM
STA CHKSUM ;and update checksum
PLA ;get byte back
JSR UNCHAR ;de-char it
STA PACNUM ;and note the value
*
* Next comes the packet type
*
JSR RXBYTE
BCC RPA260 ;j if not keyboard CR or timeout
JMP RPA900
RPA260 JSR DBYTE ;log it
CMP RSOP
BNE RPA280 ;j if it's not SOP again
JMP RPA800
RPA280 CMP REOLN
BNE RPA290 ;j if not sender's EOLN
JMP RPA820
RPA290 STA PACTYPE ;else save it
CLC
ADC CHKSUM
STA CHKSUM ;and update checksum
*
* Now we read data until we hit the EOLN character
*
LDY #0 ;buffer pointer
RPA300 JSR RXBYTE ;read a byte in
BCC RPA320 ;j if not keyboard CR or timeout
JMP RPA900
RPA320 JSR DBYTE ;log it
CMP RSOP
BNE RPA330 ;j if not SOP again
JMP RPA800 ;else resync and start again
RPA330 CMP REOLN
BEQ RPA400 ;j if it's sender's EOLN
*
* If there's still room in the receive buffer we note the byte,
* and if not we ignore it
*
CPY #MAXPAK+1
BEQ RPA300 ;j if buffer is full
STA RXBUFF,Y ;else note the byte
CLC
ADC CHKSUM
STA CHKSUM ;update the checksum
INY ;step packet buffer pointer
BNE RPA300 ;get next character
*
* We've had sender's EOLN in. Do we wait on a handshake byte now?
*
RPA400 LDX HSHAKE ;get handshake type in use
BEQ RPA500 ;j if NONE
RPA410 JSR RXBYTE ;else read a byte in
BCC RPA420 ;j if had one from sender
JMP RPA900 ;else it was keyboard/timeout
RPA420 CMP RSOP ;was it SOP again?
BNE RPA430 ;j if not
JMP RPA800
RPA430 CMP SKTAB2,X ;was it the handshake byte?
BNE RPA410 ;j if not - ignore it
*
* Packet is now complete. Check we had at least one byte in (the checksum)
*
RPA500 JSR DCLRLN ;clear debug line
CPY #0
BEQ RPA830 ;j if short packet
*
* We added the checksum into the checksum just now, so we'll
* have to remove it
*
LDA CHKSUM
SEC
SBC RXBUFF-1,Y
*
* Convert the value into a characterised checksum
*
JSR CSUM
*
* Does this now match the checksum we actually received?
*
CMP RXBUFF-1,Y
BNE RPA840 ;j if it doesn't
*
* Checksum is OK. Make sure packet isn't shorter than expected
*
INY
INY
CPY DATLEN
BCC RPA850 ;j if it is
*
* Adjust DATLEN so it realy is length of th DATA part only
*
DEC DATLEN
DEC DATLEN
DEC DATLEN
*
* Count the packet, then wait for PAUSE seconds in case other end's comms is a bit
* nadgered at high speed
*
RPA700 JSR COUNTP ;count packet
LDA PAUSE
JSR WAIT ;and wait
*
* Now look at the packet type. If it's the same as the one we just
* sent, we've read an echo which we ignore
*
LDA PACTYPE
CMP LPTYPE ;compare packet types
BNE RPA750 ;j if not same - all OK
LDA #116
JSR DMESS ;else log this is an echo
JMP RPACK ;and wait for next one to come along
*
* Not an echo, so pass packet type back to caller
*
RPA750 PHA ;save packet type
LDA #208
JSR DMESS ;print diagnostic text
LDA DATLEN
JSR DPRHEX ;print packet data length
PLA ;reload packet type
JSR DBYTE ;log it
JSR DCLRLN ;clear diagnostic line
CLC ;note packet read OK
RTS
*
* Here we hit an unexpected SOP
*
RPA800 LDA #2
JSR DMESS ;log it
JSR FLUSH ;clear comms buffer
JMP RPA120 ;restart
*
* Here we met sender's EOLN too early
*
RPA820 LDA #3
RPA825 JSR DMESS ;log it
JSR FLUSH ;clear comms buffer
JMP RPA900
*
* Here packet ended after the red tape bytes
*
RPA830 LDA #4
BNE RPA825
*
* Here the checksum was wrong
*
RPA840 LDA #6
BNE RPA825
*
* Here the length in PACLEN doesn't match the actual data
*
RPA850 LDA #5
BNE RPA825
*
* Here user hit CR on the keyboard, or reception failed
*
RPA900 SEC
RTS
***************************************
*
* SPACK
* =====
*
* Transmits a packet
*
***************************************
SPACK STA PACTYPE ;set packet type
STX PACNUM ;and number
*
* First output the debug text
*
LDA #35
JSR DMESS
*
* Set status on screen to 'sending'
*
LDA #24
JSR PRTSST
*
* Then we send any pad characters the other end wants
*
LDY XSNPAD ;get number to send
BEQ SPA200 ;j if none wanted
LDA XSPADC ;else get the character
SPA100 JSR TXBYTE ;send it
DEY
BNE SPA100 ;j till all pads sent
*
* Start packet off with a start-of-packet
*
SPA200 LDA SSOP
JSR TXBYTE
*
* First send the packet length and start the checksum up
*
LDA DATLEN ;get length of DATA portion
CLC
ADC #3 ;form total packet length
JSR TOCHAR ;characterise it
JSR DBYTE ;log the byte
JSR TXBYTE ;send it
STA CHKSUM ;start checksum
*
* Now send the packet sequence number
*
LDA PACNUM
JSR TOCHAR ;characterise it
JSR DBYTE ;log it
JSR TXBYTE ;send it
CLC
ADC CHKSUM
STA CHKSUM ;update checksum
*
* Now send and note the packet type letter
*
LDA PACTYPE
JSR DBYTE ;log it
STA LPTYPE ;record it for receiver
JSR TXBYTE ;and send it
CLC
ADC CHKSUM
STA CHKSUM ;update checksum
*
* Now prepare to send the data part
*
LDA DATLEN ;get length of data part
BEQ SPA800 ;j if none
TAX ;else prepare counter
*
* Send the next data byte
*
LDY #0 ;TXBUFF pointer
SPA600 LDA TXBUFF,Y ;get next byte
JSR DBYTE ;log it
JSR TXBYTE ;send it
CLC
ADC CHKSUM
STA CHKSUM ;update checksum
*
* Any more data to send?
*
INY ;step buffer pointer
DEX
BNE SPA600 ;j if more to go
*
* All data sent, so now send the checksum value
*
SPA800 LDA CHKSUM
JSR CSUM ;form character value
JSR DBYTE ;log it
JSR TXBYTE ;and send it
*
* Then send the EOLN character
*
LDA XSEOLN
JSR DBYTE ;log it
JSR TXBYTE ;send it
*
* Finally clear the debug line and count the packet
*
SPA900 JSR DCLRLN
JMP COUNTP
***************************************
*
* PAKPAR/PAKPRL
* =============
*
* Puts current parameter into a packet
* for a server command with a field length
* (PAKPRL) or without one (PAKPAR). This
* routine may be called several times to
* build one packet: on entry TXPTR holds
* current place in SCBUFF where we're
* building the command and TXDLEN holds
* the current size of the command
*
***************************************
PAKPRL EQU *
*
* Start with the parameter length
*
LDA CURLEN ;get the length
JSR TOCHAR ;characterise it
JSR PPR800 ;put into the packet
*
* Then the bulk of the parameter
*
PAKPAR EQU *
PPR100 LDA CURLEN
BEQ PPR700 ;j if zero length parameter
LDY #0 ;else start pointer to take from paramete
*
* Process next character
*
PPR200 STY WORK0 ;save pointe
LDA (CURPAR),Y ;get character
JSR PPR800 ;output it
LDY WORK0 ;reload pointer
INY ;step parameter pointer on
CPY CURLEN ;got to the end?
BNE PPR200 ;j if not
*
* All done
*
PPR700 RTS
*
* Routine to put character into buffer
*
PPR800 LDY TXPTR ;ge buffer pointe
CPY #MAXPAK+1 ;is buffer full?
BEQ PPR890 ;j if so
STA SCBUFF,Y ;else put character in
INC TXPTR ;step buffer pointer
INC TXDLEN ;step data size
RTS
*
* Here packet is full. As we've not yet sent an I packet, we don't want to send an E packet
* to the server
*
PPR890 LDA #0
STA MODE ;fake 'command mode' to inhibit E packet
*
* And do a "long command" break
*
PPR900 BRK
DFB 0
ASC 'Command too long'
DFB 0
***************************************
*
* INIRPK
* ======
*
* Initialise to process received packet
*
***************************************
INIRPK LDA #0
STA RXPTR ;start pointer to buffer
LDX DATLEN ;and length of data portion
RTS
NEXT BBCPM3
****** File BBCPM3 *************************************************************
START PM3
* BBCPM3 : Updated 11/06/86 @ 1110
***************************************
*
* STDPAK
* ======
*
* Sends a standard packet with no data
*
***************************************
STDPAK LDY #0 ;data size is 0
SPK100 STY DATLEN
JMP SPACK ;send it
***************************************
*
* STDPKD
* ======
*
* Sends a standard packet with one data
* byte
*
***************************************
STDPKD STY TXBUFF ;set data byte
LDY #1 ;data size is 1
BNE SPK100
***************************************
*
* STDBREAK
* ========
*
* Sends a 'B' packet
*
***************************************
STDBREAK EQU *
LDA #'B'
SBR100 LDX NXTPAK ;get sequence number
JMP STDPAK
***************************************
*
* STDEOF
* ======
*
* Sends a 'Z' packet
*
***************************************
STDEOF LDA #'Z'
BNE SBR100
***************************************
*
* SDCEOF
* ======
*
* Sends an EOF/Z packet
*
***************************************
SDCEOF LDY #'D' ;data byte
LDA #'Z' ;packet type
SDE100 LDX NXTPAK ;packet number
JMP STDPKD
***************************************
*
* SBKACK
* ======
*
* Sends an ACK/Z or ACK/X
*
***************************************
SBKACK LDA #'Y' ;packet type 'y'
BNE SDE100
***************************************
*
* STDNAK
* ======
*
* Sends a NAK packet
*
***************************************
STDNAK LDA #'N'
BNE SBR100
***************************************
*
* STDACK
* ======
*
* Sends a parameterless ACK packet
*
***************************************
STDACK LDA #'Y'
BNE SBR100
***************************************
*
* CSUM
* ====
*
* Converts the 8 bit value in A into a
* characterised checksum
*
***************************************
CSUM STA CSTEMP ;save the value
CLC
ROL A
ROL A
ROL A
AND #%00000011 ;get top bits at bottom
CLC
ADC CSTEMP ;add original
AND #%00111111 ;lose top bits
JMP TOCHAR ;and characterise it
***************************************
*
* VALSEQ
* ======
*
* Checks that a packet has the expected
* sequence number
*
***************************************
VALSEQ LDA NXTPAK
CMP PACNUM ;sequence correct?
BNE VSQ900 ;j if not
LDA #0
STA NUMTRY ;else clear retry count
JSR INCNXT ;step next-packet number
CLC
RTS ;return OK
*
* Sequence incorrect so return fail
*
VSQ900 SEC
RTS
***************************************
*
* VALNAK
* ======
*
* Checks whether a NAK is for the next
* packet to be sent
*
***************************************
VALNAK LDX PACNUM
DEX ;step sequence number back
BPL VNK200
LDX #63 ;MOD 64
VNK200 CPX NXTPAK ;does it now match?
BNE VSQ900 ;j if not - retrun fail
CLC ;else OK
RTS
***************************************
*
* RPTACK
* ======
*
* Sees if it is appropriate to resend an
* ACK, and does so if it is
*
***************************************
RPTACK LDX NXTPAK ;step next-packet back by 1
DEX
BPL RCK200
LDX #0
*
* Does this number now match that of the received packet?
*
RCK200 CPX PACNUM
BNE RCK800
*
* Yes it does, so we assume host has lost an ACK
* which we will repeat
*
LDA #'Y'
LDY PACNUM ;re-use packet number
JSR STDPAK ;send it
CLC ;return OK
RTS
*
* Not appropriate to resend, so return fail
*
RCK800 SEC
RTS
***************************************
*
* ERRPKT
* ======
*
* Handles an error packet received from
* the other end
*
***************************************
ERRPKT EQU *
*
* We'll copy the text to the stack. First put in
* a BRK and a zero error number
*
LDA #0
STA $100
STA $101
*
* Copy the text from the receive packet buffer, with a zero at the end
*
LDY DATLEN ;get data length
STA $102,Y ;put in finishing 0 byte
DEY ;step to last byte of data
EPK200 LDA RXBUFF,Y ;get byte in
STA $102,Y ;store it
DEY
BPL EPK200 ;j till all moved
*
* Note that this is an error packet and not a locally
* generated BRK
*
LDA #1
STA BRKSRC
*
* And do a BRK to give break handler control
*
JMP $100
***************************************
*
* SPAR
* ====
*
* Sets up a packet containing our
* parameters
*
***************************************
SPAR PHP ;note 'send/receive' flag
*
* Put values into transmit packet buffer
*
LDA RMAXL ;max packet size I want
JSR TOCHAR
STA TXBUFF
LDA STIME ;my timeout period
JSR TOCHAR
STA TXBUFF+1
LDA RNPAD ;number of pad characters I want
JSR TOCHAR
STA TXBUFF+2
LDA RPADC ;pad character I want
EOR #%01000000
STA TXBUFF+3
LDA REOLN ;EOLN character I want
JSR TOCHAR
STA TXBUFF+4
LDA SQUOTE ;quote character I will use
STA TXBUFF+5
LDA #'1' ;always check type 1
STA TXBUFF+7
*
* Now the 8-bit prefixing bit. Am I doing a SEND?
*
PLP ;get the flag
BCS SPR600 ;j if I'm sending
*
* I'm receiving, so I've already had other side's ideas on this
*
LDA EBQCHR ;get what he sent me
BNE SPR300 ;j if didn't default it
SPR210 JSR EBQOFF ;else tell user we won't do it
SPR220 LDA #0
STA EBQCHR ;kill it over here
LDA #'N' ;and we'll send an N in the field
BNE SPR800
*
* Other side didn't default the field, so look at what he said
*
SPR300 CMP #'Y'
BEQ SPR400 ;j if sent Y
CMP #'N'
BEQ SPR210 ;j if he sent N - we won't do it
JSR VALEBQ ;else is it legal?
BCS SPR210 ;j if not legal
*
* He sent us a legal prefix, so we'll use it
*
SPR380 STA EBQCHR ;note for packet handlers
JSR EBQON ;tell user we do it
LDA EBQCHR
BNE SPR800 ;and send the char back to him to confirm
*
* Here he sent a Y - he'll do it if we will
*
SPR400 LDA PARITY ;am I parity NONE?
CMP #4
BEQ SPR210 ;j if so - don't prefix
LDA CUREBQ
BNE SPR380 ;else we will
*
* Here I'm sending, so what I request for prefix depends on my parity setting
*
SPR600 LDA PARITY
CMP #4 ;am I parity NONE?
BNE SPR620 ;j if not
LDA #'Y'
BNE SPR630 ;else I will if he will
SPR620 LDA CUREBQ ;not parity NONE, so I want to prefix
SPR630 STA EBQCHR ;so note my character
*
* And here I'm all set,and A contains the prefix field to send to him
*
SPR800 STA TXBUFF+6 ;into packet
LDA #8 ;set packet data length
STA DATLEN
*
* And finish
*
RTS
***************************************
*
* RPAR
* ====
*
* Reads the other end's parameters from
* an init packet
*
***************************************
RPAR PHP ;save 'send/receive' flag
*
* First build a block of defaults in case he sent a short packet with some
* fields absent. Use the transmit buffer for this
*
LDY #6
RPR100 LDA RPRTAB,Y
STA TXBUFF,Y
DEY
BPL RPR100
*
* Now copy the stuff we had from him into the buffer
*
LDY DATLEN ;get length of data part
BEQ RPR120 ;j if none at all
RPR110 DEY ;step pointer back
LDA RXBUFF,Y ;get next byte
STA TXBUFF,Y ;move to our new buffer
BNE RPR110 ;j always
*
* Now analyse what we've just produced
*
RPR120 LDA TXBUFF ;max packet size he wants
JSR UNCHAR
SEC
SBC #5 ;form max DATA size - 3 (see BUFILL for comments)
STA SMAXD
LDA TXBUFF+2 ;number of pad characters he wants
JSR UNCHAR
STA XSNPAD
LDA TXBUFF+3 ;pad character he wants
EOR #%01000000
STA XSPADC
LDA TXBUFF+4 ;end of line character I must send
JSR UNCHAR
STA XSEOLN
LDA TXBUFF+5 ;quote character he will send
STA RQUOTE
*
* Now the 8 bit prefix. Am I doing a send or a receive?
*
PLP ;get the flag
BCS RPR300 ;j if I'm sending
LDA TXBUFF+6 ;else see what he said
STA EBQCHR ;note for SPAR in a minute
RTS
*
* Now look at the 8bit prefix field
*
RPR300 LDA TXBUFF+6 ;get what he sent
CMP #'N'
BEQ RPR500 ;j if he won't do it
CMP #'Y'
BEQ RPR360 ;j if he said yes to something
*
* He's sent me a prefix character. Did I send a Y or my own prefix?
*
LDX EBQCHR ;get what I sent him
CPX #'Y' ;was it a Y?
BNE RPR340 ;j if not
*
* I sent Y, he replied with a prefix, so do it
*
STA EBQCHR ;note prefix to use
RPR330 JMP EBQON ;tell user we do it
*
* I sent a prefix, he replied with one. Is it the same one?
*
RPR340 CMP EBQCHR
BEQ RPR330 ;j if it is - we do it
BNE RPR500 ;else we differ, so we don't
*
* He's sent me a Y. Did I send Y or a prefix?
*
RPR360 LDA EBQCHR ;get what I sent him
CMP #'Y'
BEQ RPR500 ;we both sent Y, so don't do it
JMP EBQON ;else tell user we will
*
* We disagree or don't want to, so we won't
*
RPR500 LDA #0
STA EBQCHR ;clear prefix character out
JMP EBQOFF ;tell user it's off
*
* Default S packet contents
*
RPRTAB DFB 80+' ' ;MAXL
DFB 0+' ' ;TIME
DFB 0+' ' ;NPAD
DFB 0!%01000000 ;PADC
DFB $0D+' ' ;EOLN
DFB '#' ;QCTL
DFB 'N' ;QBIN
NEXT BBCFIL
****** File BBCREC *************************************************************
START REC
* BBCREC: Updated 24/02/87 @ 1200
***************************************
*
* RECSW
* =====
*
* The state table switcher for receiving
* a file or the output of a server command.
* Initial state is in A on entry.
*
***************************************
RECSW STA STATE ;note initial stte
*
* Clear out the comms buffer
*
JSR FLUSH
*
* Set up receiving buffer for the current destination
*
LDA DESTIN ;get destination
LDX #0 ;mode is receive
JSR FBINIT
*
* Initialise protocol values and counts
*
JSR KINIT
*
* Log new position and state
*
RSW050 LDA #15 ;get text number
JSR LOGST ;and log it
*
* Switch on our current state to the correct handler
*
LDA STATE
CMP #'R'
BEQ RSW100 ;j if REC_INIT
CMP #'F'
BEQ RSW200 ;j if REC_FILE
CMP #'D'
BEQ RSW300 ;j if REC_DATA
CMP #'C'
BEQ RSW400 ;j if COMPLETE
CMP #'I'
BEQ RSW500 ;j if SEND_SERVER_INIT
CMP #'G'
BEQ RSW600 ;j if SEND_GEN_CMD
*
* Here we're in an unknown state, so break
*
RSW090 BRK
DFB 0
ASC 'Bad protocol state'
DFB 0
*
*
*
* State REC_INIT
* --------------
*
RSW100 JSR RINIT
JMP RSW050
*
*
* State REC_FILE
* --------------
*
RSW200 JSR RFILE
JMP RSW050
*
*
* State REC_DATA
* --------------
*
RSW300 JSR RDATA
JMP RSW050
*
*
* State COMPLETE
* --------------
*
RSW400 RTS
*
*
* State SEND_SERVER_INIT
* ----------------------
*
RSW500 JSR SVINIT
JMP RSW050
*
*
* State SEND_GEN_CMD
* ------------------
*
RSW600 JSR SNDCMD
JMP RSW050
***************************************
*
* STATE REC_INIT
* ==============
*
***************************************
RINIT JSR CHKTRY ;check retry limit
*
* Read packet from host
*
JSR RPACK
BCC RIN040 ;j if got it OK
JMP STDNAK ;else send a NAK
*
* Branch on packet type
*
RIN040 CMP #'S'
BEQ RIN100 ;j if S
CMP #'E'
BEQ RIN200 ;j if E
*
* Packet type invalid here, so abort
*
RIN050 JMP ABORT
*
*
*
* S received
* ----------
*
RIN100 CLC ;note we're receiving
JSR RPAR ;read other side's parameters
CLC ;note we're receiving
JSR SPAR ;set ours up
LDA #'Y' ;select packet type Y
LDX NXTPAK ;and get the number
JSR SPACK ;and send our parameters
LDA NUMTRY
STA OLDTRY ;save try counter
LDA #0
STA NUMTRY ;reset the main counter
STA FCOUNT ;clear file counter
JSR INCNXT ;step next-packet number by 1
LDA #'F'
STA STATE ;and go to state REC_FILE
RTS
*
*
* ERROR received
* --------------
*
RIN200 JMP ERRPKT
***************************************
*
* STATE REC_FILE
* ==============
*
***************************************
RFILE JSR CHKTRY ;check retry limit
*
* Read a packet from the host
*
JSR RPACK
BCC RFI040 ;j if got it OK
JMP STDNAK ;else NAK it
*
* Branch on packet type
*
RFI040 CMP #'S'
BEQ RFI100 ;j if S
CMP #'Z'
BEQ RFI200 ;j if Z
CMP #'F'
BEQ RFI300 ;j if F
CMP #'B'
BEQ RFI400 ;j if B
CMP #'E'
BEQ RFI500 ;j if E
CMP #'X'
BEQ RFI600 ;j if X
*
* Packet type unknown here, so abort
*
RFI050 JMP ABORT
*
*
*
* S Received
* ----------
*
* This implies host lost an ACK from us with
* the parameters, so maybe we'll resend them
*
RFI100 JSR CHKOTRY
CLC ;mark we're sending
JSR SPAR ;set our parameters up (C clear for receive here)
LDA #'Y' ;packet type is Y
LDX PACNUM ;use old number again
JSR SPACK ;and send it once more
*
* Reset the try counter and stay in this state
*
RFI120 LDA #0
STA NUMTRY
RTS
*
*
*
* Z Received
* ----------
*
* This implies host lost an ACK from us
*
RFI200 JSR CHKOTRY ;check retry limit
JSR RPTACK ;repeat the ACK if possible
BCS RFI050 ;j if not allowed here
BCC RFI120 ;else start again
*
*
*
* F received
* ----------
*
* This is a file header announcing a file
*
RFI300 LDA NXTPAK
CMP PACNUM ;is sequence OK?
BNE RFI050 ;abort if not
*
* Packet is ok. Try to open the file, or set up printer, etc
*
JSR NEWFILE
*
* Destination is ready, so we'll prepare ourselves and ACK the host
*
JSR STDACK ;send an ACK
LDA NUMTRY
STA OLDTRY ;copy try counter
LDA #0
STA NUMTRY ;reset counter
STA PENDFLG ;clear char inject flag
STA TFSTOP ;and interrupt flag
STA BKASENT ;and flag for ACK/X ACK/Z sent
JSR CLRINT ;clear interrupt status line
JSR INCNXT ;step next-packet number by 1
JSR COUNTF ;add to file count
JSR CLRKBC ;clear Kbyte count for current file
*
* Then switch to state REC_DATA
*
RFI380 LDA #'D'
RFI385 STA STATE
RTS
*
*
* B received
* ----------
*
RFI400 LDA NXTPAK
CMP PACNUM ;is packet sequence OK?
BNE RFI050 ;abort if not
JSR STDACK ;else send an ACK
JSR PRTOFF ;and ensure printer is off
*
* If in generic mode for server output, make sure screen is tidy
*
BIT MODE
BVS RFI420 ;j if not generic mode
JSR TIDYLN ;else tidy the line
*
* Then go to state COMPLETE
*
RFI420 LDA #'C'
BNE RFI385
*
*
*
* ERROR received
* --------------
*
RFI500 JMP ERRPKT
*
*
* X received
* ----------
*
* This is the header for bulk server output to screen
*
RFI600 LDA NXTPAK ;is sequence number OK
CMP PACNUM
BNE RFI050 ;j if not
JSR BUFEMP ;else write packet data to screen
JSR TIDYLN ;tidy up the output line
JSR STDACK ;send an ACK
JSR INCNXT ;step packet counter
JSR RXINIT ;clear counts and flags
JMP RFI380 ;and go to state REC_DATA
***************************************
*
* STATE REC_DATA
* ==============
*
***************************************
RDATA JSR CHKTRY ;check retry limit
*
* Get packet from host
*
JSR RPACK
BCC RDA040 ;j if got it OK
JMP STDNAK ;else send a NAK
*
* Branch on packet type
*
RDA040 CMP #'D'
BEQ RDA100 ;j if D
CMP #'F'
BNE RDA046 ;j if not F
JMP RDA200
RDA046 CMP #'Z'
BNE RDA048 ;j if not Z
JMP RDA300
RDA048 CMP #'X'
BNE RDA049 ;j if not X
JMP RDA200
RDA049 CMP #'E'
BNE RDA050 ;j if not E
JMP RDA400
*
* Packet type unknown here, so abort
*
RDA050 JMP ABORT
*
*
*
* D received
* ----------
*
RDA100 BIT BKASENT ;did we ACK/Z or ACK/X?
BPL RDA120 ;j if not
*
* Other side can't handle ACK/X or ACK/Z, so crash to a stop
*
BIT MODE ;are we in genric mode for server command?
BVC RDA105 ;j if so - no file to close
SEC
JSR FCLOSE ;close file nicely first
JSR OPTDEL ;delete it if nesessary
RDA105 BRK ;then crunch bang pow zap splatt
DFB 0
ASC 'Interrupted'
DFB 0
*
* Not interrupting, so process this
*
RDA120 LDA PACNUM
CMP NXTPAK ;is it the right sequence?
BEQ RDA160 ;j if it is
*
* Packet isn't the one expected.
*
JSR CHKOTRY ;check retry limit not exceeded
JSR RPTACK ;if OK, send an ACK if possible
BCS RDA050 ;abort if not possible
RDA140 LDA #0 ;else reset our count
STA NUMTRY
RTS
*
* Here the D packet is valid, so file it
*
RDA160 JSR BUFEMP ;this may go to disc
*
* Data is put away, possibly to disc, so it's clear to ACK now
*
BIT TFSTOP ;had keyboard interrupt?
BPL RDA180 ;j if not
*
* User has done CTRL-X or CTRL-Z
*
LDY #'X' ;assume CTRL-X
BVC RDA170 ;j if that's right
LDY #'Z' ;else it's CTRL-Z
RDA170 JSR SBKACK ;send ACK/<char>
LDA #$FF
STA BKASENT ;note we sent it
BMI RDA190
*
* No keyboard interrupt, so keep going
*
RDA180 JSR STDACK ;ordinary ACK
RDA190 LDA NUMTRY
STA OLDTRY ;save try counter
LDA #0
STA NUMTRY ;reset it
JSR INCNXT ;step next-packet number
*
* And make sure we're in state REC_DATA
*
LDA #'D'
STA STATE
RTS
*
*
*
* F or X received
* ---------------
*
* This implies host has lost an ACK from us. Repeat it if we can
*
RDA200 JSR RPTACK
BCS RDA050 ;abort if not appropriate
BCC RDA140 ;else reset counts
*
*
*
* Z received
* ----------
*
RDA300 LDA NXTPAK
CMP PACNUM ;is sequence correct?
BNE RDA050 ;j if not
*
* Are we receiving a file or server output?
*
BIT MODE ;in for generic mode?
BVC RDA340 ;j if so - it's server output
*
* File send is over. We could have a character still to write to it
*
BIT PENDFLG ;character pending?
BPL RDA320 ;j if we not
LDA PENDCHR
JSR TOFILE ;else output pended character
RDA320 SEC ;select 'flush buffer'
JSR FCLOSE ;and close the file
*
* Did we or remote interrupt the transfer with CTRL-X or CTRL-Z?
*
BIT BKASENT
BMI RDA330 ;j if we interrupted
LDA DATLEN ;else look at EOF packet data field
BEQ RDA340 ;j if there isn't one
LDA RXBUFF ;else get first character
CMP #'D'
BNE RDA340 ;j if not EOF(D) - not interrupted
*
* We do have an interrupted transfer, so maybe delete incoming file
*
RDA330 JSR OPTDEL
*
* Then send an ACK and prepare for the next bit
*
RDA340 JSR STDACK
JSR INCNXT ;step next-packet number
JSR STOTCT ;clear counters
LDA #0
STA NUMTRY ;clear the try counter
LDA #'F'
STA STATE ;and go to state REC_FILE
RTS
*
*
*
* ERROR received
* --------------
*
RDA400 JMP ERRPKT
***************************************
*
* STATE SEND_SERVER_INIT
* ======================
*
***************************************
SVINIT JSR CHKTRY ;check retry limit
*
* Build parameters and send an I packet
*
SEC ;we're sending here
JSR SPAR ;build packet
LDA #'I' ;type is I
LDX #0 ;sequence is 0
JSR SPACK ;so send it
*
* Read the reply
*
JSR RPACK
BCC SVI040 ;j if OK
RTS ;else stay in this state
*
* Branch on packet type
*
SVI040 CMP #'N'
BEQ SVI200 ;j if N
CMP #'Y'
BEQ SVI300 ;j if Y
CMP #'E'
BEQ SVI400 ;j if E
*
* Unknown packet type, so abort
*
JMP ABORT
*
*
* NAK received
* ------------
*
SVI200 RTS ;stay in this state
*
*
* ACK received
* ------------
*
* This contains server's parameters
*
SVI300 JSR VALSEQ ;sequence OK?
BCS SVI200 ;j if not - stay in this state
SVI320 JSR INPARS ;else analyse the parameters
LDA #'G'
STA STATE ;go to state SEND_GEN_CMD
LDA #0
STA NXTPAK ;restart packet counter
STA NUMTRY ;and try counter
RTS
*
*
* ERROR received
* --------------
*
* This means server does not implement I packets so
* we assume he'll use default values
*
SVI400 LDA #0 ;fake that we had a zero length ACK
STA DATLEN ;so we'll use all defaults
BEQ SVI320 ;and go to state SEND_GEN_CMD
***************************************
*
* STATE SEND_GEN_CMD
* ==================
*
***************************************
SNDCMD JSR CHKTRY ;check retry limit
*
* Copy the command to the transmit buffer. Here TXDLEN gives the number of
* bytes in the string, but we have yet to handle quoting and 8th-bit-prefixing.
* Set up some control values first
*
LDX #0 ;start pointer to take from string
LDY #0 ;start pointer to insert into transmit buffer
*
* Get a byte from the command string and see what we need to do
*
SCD010 LDA SCBUFF,X ;get the byte
CMP SQUOTE ;is it the quote we send?
BEQ SCD030 ;j if it is
BIT EBQFLG ;are we 8th-bit-prefixing?
BPL SCD020 ;j if not - move byte unchanged
CMP EBQCHR ;else is it the 8-bit-prefix character?
BNE SCD020 ;j if not - move byte unchanged
*
* Byte is the 8-bit-prefix, so it has to be quoted
*
LDA SQUOTE ;get the quote character
JSR SCD040 ;move it to the transmit buffer
LDA EBQCHR ;then get the 8-bit-prefix char again
SCD020 JSR SCD040 ;move that to the buffer
*
* Now see if there's any more to move
*
SCD025 INX ;step remove pointer
CPX TXDLEN
BNE SCD010 ;j if more to move
*
* All moved, so we now have the actual packet size in Y
*
STY DATLEN ;set up the length
BEQ SCD045 ;and send the packet
*
* Here character is the quote, so we double it
*
SCD030 JSR SCD040 ;output it to the buffer once...
JSR SCD040 ;...and once again
JMP SCD025 ;and round again
*
* Here we insert the character into the transmit buffer
*
SCD040 CPY SMAXD ;is buffer full?
BCC SCD042 ;j if not
JMP PPR900 ;else break
SCD042 STA TXBUFF,Y ;insert char into buffer
INY ;step buffer pointer
RTS
*
* Here we send the packet that we've just built
*
SCD045 LDA TXTYPE ;get type
LDX #0 ;sequence is 0
JSR SPACK
*
* Then get the reply
*
JSR RPACK
BCC SCD050 ;j if OK
RTS ;else stay in this state
*
* Branch on packet type
*
SCD050 CMP #'S'
BEQ SCD100 ;j if S
CMP #'Y'
BEQ SCD200 ;j if Y
CMP #'N'
BEQ SCD300 ;j if N
CMP #'X'
BEQ SCD400 ;j if X
CMP #'E'
BEQ SCD500 ;j if E
*
* Packet type unknown, so break
*
JMP ABORT
*
*
* S received
* ----------
*
SCD100 JMP RIN100 ;process params and reply
*
*
* Y received
* ----------
*
* This may contain a message for the screen
*
SCD200 JSR VALSEQ ;sequence OK?
BCS SCD290 ;j if not - stay in this state
JSR VDUINI ;else initialise VDU output values
JSR BUFEMP ;and write data to sceen
JSR TIDYLN ;make sure screen line is tidy
LDA #'C'
SCD240 STA STATE ;and go to state COMPLETE
SCD290 RTS
*
*
* N received
* ----------
*
SCD300 RTS ;stay in this state
*
*
* X received
* ----------
*
SCD400 LDA PACNUM ;is sequence OK
CMP NXTPAK
BNE SCD300 ;j if not - stay in this state
JSR VDUINI ;else initialise VDU output values
JSR BUFEMP ;and copy packet data to screen
JSR TIDYLN ;make sure screen line is tidy
JSR STDACK ;then ACK it
JSR INCNXT ;step packet number
JSR RXINIT ;clear counts and flags
LDA #'D'
BNE SCD240 ;and go to state REC_DATA
*
*
* ERROR received
* --------------
*
SCD500 JMP ERRPKT
CHN BBCSND
****** File BBCSB1 *************************************************************
START SB1
* BBCSB1: Updated 07/07/86 @ 1500
***************************************
*
* MESS
* ====
*
* Outputs a preset message text
*
***************************************
MESS EQU *
*
* Work out start address of string. The lsb is a straight table
* look-up
*
TAY ;message number into Y
PHA ;and saved for later
LDA MSGTBL,Y ;get address lsb
STA MPTR0 ;and note it
*
* The msb is more complicated. We have a list that gives the number of the
* first message to start within each page, relative to the
* page that M0 starts in, so we scan back until we find which page our own
* message starts in
*
PLA ;get message number
LDY #MTHCNT+1 ;point past end of list
MES100 DEY ;step back one element
CMP MSGTBH,Y ;check with list
BCC MES100 ;j if message in a lower page
*
* Y now gives the page number relative to M0 start, so add in the
* high byte of M0 to get the msb of the address
*
TYA
CLC
ADC #<M0
STA MPTR0+1 ;and save the address
*
* Now output text, looking for our control characters
*
LDY #0
MES200 LDA (MPTR0),Y ;get character
CMP #LIT ;is it a special?
BCC MES300 ;j if not
*
* Character is a special, so go to the relevant service routine
*
TAX ;get target address
LDA MSGT1L-LIT,X
STA MPTR1
LDA MSGT1H-LIT,X
STA MPTR1+1
JMP (MPTR1) ;and into sercvice routine
*
* Not a special character, so output it
*
MES300 JSR OSASCI ;output it
MES310 JSR MES950 ;step pointer on
JMP MES200
*
* Here we have EOT for end-of-text
*
MES400 RTS ;finish the routine
*
* Here we have LIT to force literal use of the next character
*
MES420 JSR MES950 ;step pointer on
LDA (MPTR0),Y ;get next character
JMP MES300 ;output it
*
* Here we have RPT for multiple literal character expansion. This is
* followed by <count> and <character>
*
MES440 JSR MES950 ;step to count value
LDA (MPTR0),Y ;pick value up
TAX ;save into X
JSR MES950 ;step to data character
LDA (MPTR0),Y ;get it
MES450 JSR OSASCI ;print it
DEX
BNE MES450 ;until count expires
JMP MES310 ;then do next character
*
* Here we have TXT, which is followed by the text number
* we recurse into
*
MES460 JSR MES950 ;move pointer on
LDA #1 ;fake a repeat count of 1
STA MWORK0 ;save it
BNE MES510 ;and use MTXT code
*
* Here we have XCR, so we output a $0D without conversion
* to LF-CR
*
MES480 LDA #$0D
JSR OSWRCH
JMP MES310
*
* Here we have MTXT, for multiple sub-text
*
MES500 JSR MES950 ;move to next character
LDA (MPTR0),Y ;get the repeat count
STA MWORK0 ;save for a moment
JSR MES950 ;move to text number
MES510 LDA (MPTR0),Y ;get sub-text number
MES512 TAX ;hold it in X
PHA ;and stack it
LDA MWORK0 ;get repeat count back
PHA ;and stck it
TYA ;stack the current offset
PHA
LDA MPTR0 ;stack current text pointer
PHA
LDA MPTR0+1
PHA
TXA ;get sub-text number back
JSR MESS ;recurse to do the sub-text
PLA ;then unstack old pointer
STA MPTR0+1
PLA
STA MPTR0
PLA ;unstack offset
TAY
PLA ;unstack repeat count
SEC
SBC #1 ;decrement it
BEQ MES518 ;j if no more to do
STA MWORK0 ;else save it
PLA ;reload text number
JMP MES512 ;and do it again
MES518 PLA ;all done so lose text number
JMP MES310 ;and carry on
*
* Here we have MSP for multiple space
*
MES520 JSR MES950 ;move to repeat count
LDA (MPTR0),Y ;get the count
TAX ;hold it in X
LDA #' ' ;set up a space as repeated character
BNE MES450 ;and use RPT code
*
*
* Step text pointer
* -----------------
*
MES950 INY
BNE MES960 ;j if still in same page
INC MPTR0+1 ;else move on a page
LDY #0 ;and start offset again at zero
MES960 RTS ;and finish
*
*
* Addresses for routines servicing $F0..$FF
*
MSGT1L DFB >MES420 ;$F9 - LIT
DFB >MES520 ;$FA - MSP
DFB >MES500 ;$FB - MTXT
DFB >MES480 ;$FC - XCR
DFB >MES440 ;$FD - RPT
DFB >MES460 ;$FE - TXT
DFB >MES400 ;$FF - EOT
MSGT1H DFB <MES420 ;$F9 - LIT
DFB <MES520 ;$FA - MSP
DFB <MES500 ;$FB - MTXT
DFB <MES480 ;$FC - XCR
DFB <MES440 ;$FD - RPT
DFB <MES460 ;$FE - TXT
DFB <MES400 ;$FF - EOT
***************************************
*
* DMESS
* =====
*
* Sends a diagnostic text to parallel
* printer
*
***************************************
DMESS PHA
LDA DEBTOG ;is debug on?
BEQ DME990 ;j if not - null call
*
* Debug is on, so let's do it
*
TXA
PHA
TYA
PHA
*
* Select parallel printer output
*
JSR OPPTR
*
* Then do a standard 'print text' call
*
TSX
LDA $103,X ;get text number
JSR MESS
*
* Reset output to VDU
*
DME800 JSR OPVDU
*
* And finish
*
DME900 PLA
TAY
PLA
TAX
DME990 PLA
RTS
***************************************
*
* DBYTE
* =====
*
* Outputs one byte to the parallel printer
* in ASCII if possible
*
***************************************
DBYTE PHA
LDA DEBTOG ;is debug mode on?
BEQ DME990 ;j if not - null call
*
* Debug mode is on, so we print
*
CLC ;note ASCII wanted
DBY100 TXA
PHA
TYA
PHA
PHP ;save ASCII/hex switch
*
* Output byte in required form
*
JSR OPPTR ;select parallel printer
TSX
LDA $104,X ;pick up the byte
PLP ;ASCII or hex wanted?
BCS DBY400 ;j if hex wanted
CMP #32
BCC DBY400 ;j if control char
CMP #127
BCS DBY400 ;j if not printable
DBY300 JSR OSASCII ;else print it
JMP DME800 ;and finish
*
* Here byte isn't printable, so do it in hex
*
DBY400 PHA ;save the byte
LDA #'<' ;print '<'
JSR OSWRCH
PLA ;reget the byte
JSR PRHEX ;print it in hex
LDA #'>' ;then a '>'
JSR OSWRCH
JMP DME800 ;and end
***************************************
*
* DPRHEX
* ======
*
* Outputs one byte to parallel printer
* in hex
*
***************************************
DPRHEX PHA
LDA DEBTOG ;is debugging active?
BEQ DME990 ;j if not
SEC ;else select hex mode
BCS DBY100 ;and print the byte
***************************************
*
* DCLRLN
* ======
*
* Tidies up the line on the parallel
* printer with a CR
*
***************************************
DCLRLN PHA
LDA DEBTOG ;is debug on?
BEQ DME990 ;j if not - null call
*
* Debug is on, so save registers
*
TXA
PHA
TYA
PHA
*
* Select parallel printer output
*
JSR OPPTR
*
* And send a CR
*
LDA #$0D
BNE DBY300
***************************************
*
* PRHEX
* =====
*
* Prints value in A in hex
*
***************************************
PRHEX PHA ;save the value
LSR A ;get top nibble
LSR A
LSR A
LSR A
JSR PRH500 ;print it
PLA
AND #$0F ;get bottom nibble
PRH500 CMP #10
BCC PRH600 ;j if 0..9
CLC
ADC #'A'-10 ;else form 'A'..'F'
BCC PRH650
PRH600 ADC #'0' ;scale to '0'..'9'
PRH650 JMP OSWRCH ;and print it
***************************************
*
* PRWHEX
* ======
*
* Prints value in X,Y (low-high) in hex
*
***************************************
PRWHEX TXA
PHA ;save low byte
TYA
JSR PRHEX ;print high byte
PLA ;reload low byte
JMP PRHEX ;print it
***************************************
*
* INCNXT
* ======
*
* Steps the next-packet number by 1
*
***************************************
INCNXT LDX NXTPAK
INX
CPX #64
BCC INX900
LDX #0
INX900 STX NXTPAK
RTS
***************************************
*
* OPVDU
* =====
*
* Directs output to the VDU drivers
*
***************************************
OPVDU LDX #%00000000
OPV100 LDY #0
LDA #3
JMP OSBYTE
***************************************
*
* OPPTR
* =====
*
* Directs output to printer
*
***************************************
OPPTR LDX #%00001010
BNE OPV100
***************************************
*
* MKGBPB
* ======
*
* Partially fills an OSGBPB control
* block
*
***************************************
MKGBPB LDA FHAND ;set handle as byte 0
STA GBPBLK
*
* Set transfer address to the base of the file buffer
*
LDA FBUFF
STA GBPBLK+1
LDA FBUFF+1
STA GBPBLK+2
LDY #$FF
STY GBPBLK+3
STY GBPBLK+4
*
* Set top two bytes of transfer size to 0
*
INY
STY GBPBLK+7
STY GBPBLK+8
*
* Set sequential pointer to 0
*
STY GBPBLK+9
STY GBPBLK+10
STY GBPBLK+11
STY GBPBLK+12
*
* And that's it
*
RTS
***************************************
*
* TOCHAR
* ======
*
* Makes a control char printable
*
***************************************
TOCHAR CLC
ADC #' '
RTS
***************************************
*
* UNCHAR
* ======
*
* Reverses the action of TOCHAR
*
***************************************
UNCHAR SEC
SBC #' '
RTS
***************************************
*
* FLSHKB
* ======
*
* Flushes the keyboard buffer
*
***************************************
FLSHKB LDA #15
JMP OB10
***************************************
*
* INKEY
* =====
*
* Does an INKEY(0) call
*
***************************************
INKEY JSR SUSEXF ;suspend any EXEC file
LDX #0
INK100 LDA #$81
JSR OBX0 ;do INKEY(0)
PHP ;save status result
TXA
PHA ;and the key code
JSR RSTEXF ;reset any EXEC file
PLA ;and reset key code and status
TAX
PLP
RTS
***************************************
*
* HEXFLG
* ======
*
* Checks if a character is X, $ or &
*
***************************************
HEXFLG JSR UPPER ;into upper case
CMP #'X'
BEQ HFG800 ;j if X
CMP #'$'
BEQ HFG800 ;j if $
CMP #'&'
BEQ HFG800 ;j if &
*
* Not in the list
*
SEC
RTS
*
* In the list
*
HFG800 CLC
RTS
***************************************
*
* CHKFNL
* ======
*
* Checks if current param is too long
* to be a filename
*
***************************************
CHKFNL LDA CURLEN
CMP #MAXFNL
BCS CFL900 ;j if too long
RTS
*
* Parameter is too long
*
CFL900 LDA #195 ;select error text
JMP PARMERR ;and report
***************************************
*
* TELLACT
* =======
*
* Reports if a toggle is on or off
*
***************************************
TELLACT CMP #$FF ;check the toggle
BEQ TAC400 ;j if active
LDA #126 ;else say it's off
BNE TAC410
TAC400 LDA #127 ;get text for 'on'
TAC410 JMP MESS ;print the text
***************************************
*
* WHATFS
* ======
*
* Notes number of current filing system
*
***************************************
WHATFS LDA #0
TAY
LDX #>WORK0 ;point dummy control block
JSR OSARGS ;get number in A
STA FSNUM ;note the number
RTS
***************************************
*
* LOGST
* =====
*
* Logs state of a state switcher
*
***************************************
LOGST JSR DMESS ;log heading
LDA STATE
JSR DBYTE ;log the state letter
JMP DCLRLN ;tidy up the line
***************************************
*
* PRTON / PRTOFF
* ==============
*
* Turns printer on/off with VDU 2/3
*
***************************************
PRTON LDA #2
PON100 JMP OSWRCH
PRTOFF LDA #3
BNE PON100
IF RAM
***************************************
*
* CKSHAD
* ======
*
* Errors if we do not have shadow screen
* capability
*
***************************************
CKSHAD BIT SHADOW
BPL CKD900 ;j if shadow capability
RTS ;else OK
*
* No shadow capability, so we BRK
*
CKD900 BRK
DFB 0
ASC 'Not on BBC B'
DFB 0
FI
***************************************
*
* GETACIA
* =======
*
* Masks 6850 IRQ from the system
*
***************************************
GETACIA LDX #0
GAC100 LDA #$E8
JMP OBX0
***************************************
*
* LOSEACIA
* ========
*
* Allows the system to see 6850 IRQ
*
***************************************
LOSEACIA LDX #$FF
BMI GAC100
NEXT BBCSB2
****** File BBCSB2 *************************************************************
START SB2
* BBCSB2: Updated 10/05/86 @ 1900
***************************************
*
* REPORT
* ======
*
* Reports termination of a transfer
*
***************************************
REPORT LDA #17
JSR MESS ;print "completed"
LDA #51 ;and set status on screen to "idle"
JSR PRTSST
*
* If command source is keyboard we wait for a CR
*
LDA CSOURCE ;get source indicator
BNE REP600 ;j if source is TAKE file
JMP WTCMODE ;else wait for CR
*
* Source is take file. Close it if CTRL-Z was used
*
REP600 BIT TFSTOP ;was transfer interrupted?
BPL REP800 ;j if not
JMP WAI900 ;else back to keyboard input
*
* Not interrupted, so just wait 2 seconds
*
REP800 LDA #2
JMP WAIT
***************************************
*
* UPPER
* =====
*
* Converts lower case to upper
*
***************************************
UPPER CMP #'a'
BCC UPP900 ;j if not 'a'..'z'
CMP #'z'+1
BCS UPP900 ;j if not 'a'..'z'
AND #$DF ;else convert to upper
UPP900 RTS
***************************************
*
* ONOFPAR
* =======
*
* Gets a parameter and analyses it as
* ON or OFF
*
***************************************
ONOFPAR EQU *
*
* Select the commnd table and get the parameter
*
LDX #>ONOFTB
LDY #<ONOFTB
JSR SELTAB
JSR MPARAM ;get parameter
JMP SCANTAB ;validate it
ONOFTB DW 0 ;no jump table
CMD 3,'OFF'
CMD 2,'ON'
DFB 0
***************************************
*
* BRKTXT
* ======
*
* Outputs the text for a BRK
*
***************************************
BRKTXT JSR LOCATE ;find where we are
*
* Now print the text, stopping at column 79 or end-of-text
*
LDY #1 ;start past error number
BTX100 LDA ($FD),Y ;get a byte
BEQ BTX900 ;j if end-of-text
JSR OSWRCH ;else print it
INY
INX
CPX #80
BNE BTX100 ;j if not at end of line now
*
* And finish
*
BTX900 RTS
***************************************
*
* SPFILL
* ======
*
* Spacefills current line to the end
*
***************************************
SPFILL JSR LOCATE ;find where we are
LDA #28 ;and form window on the rest of
JSR OSWRCH ;the line
TXA
JSR OSWRCH ;left X is where we are
TYA
JSR OSWRCH ;bottom Y is this line
LDA MODE ;get system mode
LSR A
BCC SPF200 ;j if not terminal - screen is 40 wide
LDX TTYPE ;else get terminal type
LDA SPFTB1,X ;get rh col from table
BNE SPF300
SPF200 LDA #39 ;here it's not terminal
SPF300 JSR OSWRCH ;write rh X as rh of screen
TYA
JSR OSWRCH ;top Y is this line
LDA #62
JSR MESS ;clear window and reset to full screen
JMP REPOSN ;put cursor back where it was
SPFTB1 DFB 39,79,79
***************************************
*
* DISFN
* =====
*
* Displays a filename
*
***************************************
DISFN STX PTR3 ;save pointer to name
STY PTR3+1
JSR LOCATE ;find where we are on screen
*
* Write text, stopping at a CR or column 39
*
LDY #0
DFN200 CPX #40 ;off end of screen?
BEQ BTX900 ;j if so - stop her
LDA (PTR3),Y ;else get next byte
CMP #$0D
BEQ DFN900 ;j if CR
JSR OSWRCH
INX
INY
BNE DFN200 ;else carry on
*
* Then spacefill to end of line
*
DFN900 JMP SPFILL
***************************************
*
* WTCMODE
* =======
*
* Prompts and waits for key on return
* to command mode
*
***************************************
WTCMODE LDA #16
JSR MESS ;prompt for a key
JSR FLSHKB ;flush keyboard buffer
JSR KEYRD ;and wait for a key, bypassing EXEC file
*
* Clear the screen and finish
*
LDA #$0C
JMP OSWRCH
**************************************
*
* PRDEC
* =====
*
* Print number in X,Y in decimal
*
**************************************
PRDEC STX ASCNUM ;save original value
STY ASCNUM+1
PHP ;save 5/3 digit flag
*
* Clear output area to "00000"
*
LDA #'0'
LDX #4
PRD100 STA NUM,X
DEX
BPL PRD100
*
* Do a subtract loop for successive powers of 10
*
LDX #0 ;prepare subtract loop
PRD200 LDA ASCNUM
PRD210 SEC
SBC TENL,X ;subtract next power of 10
PHA
LDA ASCNUM+1
SBC TENH,X
BCC PRD300 ;j if carry out
*
* No carry from this, so add one to this power of
* 10 in the output array
*
INC NUM,X
STA ASCNUM+1 ;and note new value
PLA
STA ASCNUM
JMP PRD210
*
* Subtraction caused a carry, so no more left for this power of 10
*
PRD300 PLA ;tidy the stack up
INX
CPX #4
BCC PRD200 ;do next power of ten
*
* Now add in what's left in the original as the units figure
*
LDA ASCNUM
CLC
ADC #'0'
STA NUM,X
*
* Now scan the output list to do zero suppression
*
LDX #0 ;assume we want 5 digits
PLP ;then look at flag
BCC PRD400 ;j if 5 wanted
LDX #2 ;else we send last 3 only
PRD400 LDA NUM,X ;get output digit
CMP #'0'
BNE PRD450 ;j if not '0' - end suppression
LDA #' '
JSR OSWRCH ;else output a space instead
INX
CPX #4
BNE PRD400
*
* Suppression ended here, so print digits unchanged
*
PRD430 LDA NUM,X
PRD450 JSR OSWRCH
INX
CPX #5
BNE PRD430
RTS
TENL HEX '10E8640A'
TENH HEX '27030000'
***************************************
*
* CLRKBC
* ======
*
* Clears and displays the Kilobyte count
* for the current file
*
***************************************
CLRKBC LDA #0
STA KBYTEC ;clear count of Kbytes
STA KBYTEC+1
STA BYTESC ;reset count down
LDA #4
STA BYTESC+1
JMP DISKBC ;display cleared total
***************************************
*
* STATUS
* ======
*
* Displays the status screen and
* selects transfer mode, clearing counts
*
***************************************
STATUS LDA #%11000000
STA MODE ;set transfer mode
LDA #10
JSR MESS ;show status display
JSR CSROFF ;turn off cursor
*
* Now clear some counters
*
JSR STOTCT ;packets, etc
LDA #0
STA KBYTET ;total Kbytes in group
STA KBYTET+1
*
* Now put up the current file type
*
LDA #72
JSR MESS ;position cursor
JMP PRFTYPE ;and output it
***************************************
*
* STOTCT
* ======
*
* Initialises the packet total counters
*
***************************************
STOTCT LDA #0
STA PKTCNT ;total packet count
STA PKTCNT+1
STA RTRCNT ;total retry count
STA RTRCNT+1
STA TMOCNT ;timeout count
STA TMOCNT+1
STT900 RTS
***************************************
*
* COUNTP
* ======
*
* Increments and displays the total
* packet count
*
***************************************
COUNTP INC PKTCNT ;step counter
BNE CTP400
INC PKTCNT+1
CTP400 BIT MODE ;are we in transfer or generic mode?
BVC STT900 ;j if generic - no display
LDA #36
JSR MESS ;position cursor
LDX PKTCNT
LDY PKTCNT+1
CLC ;select 5 digit print
JMP PRDEC ;print the value
***************************************
*
* COUNTR
* ======
*
* Increments and displays the total
* retry count
*
***************************************
COUNTR INC RTRCNT ;step the value
BNE CTR400
INC RTRCNT+1
CTR400 BIT MODE ;are we in transfer or generic mode?
BVC STT900 ;j if generic - no display
LDA #37
JSR MESS ;position cursor
LDX RTRCNT
LDY RTRCNT+1
CLC ;select 5 digit print
JMP PRDEC ;and print the value
***************************************
*
* COUNTB
* ======
*
* Increments the bytes transferred count
* and maintains display in Kilobytes
*
***************************************
COUNTB PHA ;save registers
TYA
PHA
TXA
PHA
DEC BYTESC ;step byte countdown
BNE CTB900 ;j if not expired
DEC BYTESC+1
BNE CTB900 ;j if not expired
*
* We've completed a kilobyte. Refresh countdown
*
LDA #4
STA BYTESC+1
*
* Step and display Kbyte count for whole group
*
INC KBYTET ;step value
BNE CTB500
INC KBYTET+1
CTB500 LDA #149
JSR MESS ;position cursor
LDX KBYTET ;pick up value
LDY KBYTET+1
SEC ;select 3 digit field
JSR PRDEC ;print it
*
* Step and display Kbyte count for current file
*
INC KBYTEC ;step value
BNE CTB600
INC KBYTEC+1
CTB600 JSR DISKBC ;and display it
*
* Restore registers and finish
*
CTB900 PLA
TAX
PLA
TAY
PLA
RTS
***************************************
*
* DISKBC
* ======
*
* Displays the kilobyte count for the
* current file
*
***************************************
DISKBC LDA #145
JSR MESS ;position cursor
LDX KBYTEC ;get the value
LDY KBYTEC+1
SEC ;select 3 digit field
JMP PRDEC ;print value
***************************************
*
* ABORT
* =====
*
* Sets system into Abort state
*
***************************************
ABORT PHA ;save the bad packet type
LDA #209
JSR DMESS ;print diagnostic text
PLA
JSR DBYTE ;print bad packet type
JSR DCLRLN ;clear diagnostic line
LDA #'A'
STA STATE ;set new state
BRK ;and crunch
DFB 0
ASC 'Protocol error'
DFB 0
***************************************
*
* DISLFN
* ======
*
* Displays the local filename
*
***************************************
DISLFN LDA #29
JSR MESS ;position cursor
LDX #>LFNAME ;point to buffer
LDY #<LFNAME
JMP DISFN ;and display it
***************************************
*
* DISRFN
* ======
*
* Displays the remote filename
*
***************************************
DISRFN LDA #28
JSR MESS ;position cursor
LDX #>RFNAME ;point to buffer
LDY #<RFNAME
JMP DISFN ;and display it
***************************************
*
* CSRON
* =====
*
* Turns the cursor on
*
***************************************
CSRON LDA #43
JMP MESS
***************************************
*
* CSROFF
* ======
*
* Turns the cursor off
*
***************************************
CSROFF LDA #44
JMP MESS
***************************************
*
* ESCON/ESCOFF
* ============
*
* Controls whether ESCAPE generates a
* $1B or causes an ESCAPE condition
*
***************************************
ESCON LDA #229
JMP OB00
ESCOFF LDA #229
JMP OB10
***************************************
*
* SETCRS
* ======
*
* Sets BRK restart details for command
* mode loop
*
***************************************
SETCRS STX STKRST ;save stck point
LDX #>CMO100 ;declare restart vector
STX RESTART
LDX #<CMO100
STX RESTART+1
RTS
***************************************
*
* GETBRK
* ======
*
* Takes the BRK vector
*
***************************************
GETBRK LDA #>BRKH ;point it to our BRK handler
STA BRKV ;it's easy since BRKV is non-extended
LDA #<BRKH
STA BRKV+1
RTS
***************************************
*
* WIDPAR
* ======
*
* Gets a "40"/"80" parameter and checks it's
* the last
*
***************************************
WIDPAR LDX #>WIDTAB ;point to table
LDY #<WIDTAB
JSR MPARTAB ;get the parameter
CLC ;allow abbreviations
JSR SCANTAB ;and validate it
JMP CONFIRM ;check no more params
WIDTAB DW 0 ;no jump table
CMD 2,'80'
CMD 2,'40'
DFB 0
***************************************
*
* STMDE3
* ======
*
* Switches to MODE 3
*
***************************************
STMDE3 LDA TVFLAG ;do we do a *TV?
BEQ SMD100 ;j if not
LDA #$90
LDX TVPAR1
LDY TVPAR2
JSR OSBYTE ;else do the *TV
SMD100 LDA #210
JSR MESS ;go to MODE 3...
SMD200 LDA #134
JSR MESS ;...then VDU 19,1
LDA VDUCOL
JSR OSWRCH ;output foreground colour
LDA #34
JMP MESS ;and 0,0,0 to finish off
***************************************
*
* KINIT
* =====
*
* Initialises protocol values and counts
*
***************************************
KINIT LDA SPADC ;pad character we send
STA XSPADC
LDA SNPAD ;number of them
STA XSNPAD
LDA SEOLN ;EOLN byte we send
STA XSEOLN
LDA #79 ;default packet DATA length + 1
STA SMAXD
LDA #0
STA NXTPAK ;packet sequence
STA NUMTRY ;try counter
RTS
***************************************
*
* SUSEXF
* ======
*
* Suspends an EXEC file, taking future
* input from keyboard
*
***************************************
SUSEXF LDA #$C6
JSR OB00 ;reac EXEC handle and clear it
STX EXECH ;save old value
RTS
***************************************
*
* RSTEXF
* ======
*
* Resets EXEC file handle to previous
* value
*
***************************************
RSTEXF PHA
PHP
LDA #$C6
LDX EXECH
JSR OBX0
PLP
PLA
REX900 RTS
***************************************
*
* SETPAD
* ======
*
* Sets base value for Master 128 keypad
*
***************************************
SETPAD LDA #238
JMP OBX0
***************************************
*
* CLTXF
* =====
*
* Closes TRANSMIT file
*
***************************************
CLTXF LDY TXHAND
BEQ REX900 ;j if file not open
LDA #0
STA TXHAND ;else clear the handle
JMP OSFIND ;and close it
NEXT BBCSB3
****** File BBCSB3 *************************************************************
START SB3
* BBCSB3: Updated 09/05/86 @ 1830
***************************************
*
* CHKTRY
* ======
*
* Tests the NUMTRY counter
*
***************************************
CHKTRY LDA NUMTRY ;get the value
INC NUMTRY ;increment it
CKT050 CMP MAXTRY ;has it reached limit?
BCS CKT900 ;j if reached limit
*
* Not at limit yet - is this first go or a retry?
*
CKT100 CMP #0
BEQ CKT400 ;j if first time
CKT200 JMP COUNTR ;else step count of repeats
CKT400 RTS
*
* Retry limit reached, so error
*
CKT900 BRK
DFB 0
ASC 'Retry limit exceeded'
DFB 0
***************************************
*
* CHKOTRY
* =======
*
* Tests the OLDTRY counter
*
***************************************
CHKOTRY LDA OLDTRY ;get the value
INC OLDTRY ;increment it
JMP CKT050 ;and check for limit
***************************************
*
* PRTSST
* ======
*
* Puts system status on status screen
*
***************************************
PRTSST BIT MODE ;are we in generic or transfer mode?
BVC CKT400 ;j if generic - no display
PHA ;else save message number
LDA #54
JSR MESS ;position cursor
PLA
JMP MESS ;then send text
***************************************
*
* NUMPAR
* ======
*
* Converts current parameter to binary
*
***************************************
NUMPAR LDY #0 ;clear totals byte
STY NUM
STY NUM+1
*
* Look at first byte to see if number is in hex
*
LDA (CURPAR),Y ;get the byte
JSR HEXFLG ;is it $, X or &?
BCS NPR210 ;j if not - value is decimal
JMP HXP800 ;else do it in hex
*
* Get next byte from param and check it's numeric
*
NPR200 LDA (CURPAR),Y
SEC
NPR210 SBC #'0' ;scale to "0"=0
BMI NPR900 ;j if not 0..9
CMP #10
BCS NPR900 ;j if not 0..9
*
* Multiply current total by 10 and add in new digit
*
STA NUM+1 ;save new digit
LDA NUM ;get old total
ASL A
STA NUM ;save total*2
ASL A
ASL A ;form total*8
CLC
ADC NUM ;form total*10
CLC
ADC NUM+1 ;add in new digit
STA NUM ;save new total
*
* Carry on to end of parameter
*
INY
CPY CURLEN
BNE NPR200 ;j if not at end
*
* Return the ls byte of the value
*
LDA NUM
CLC
RTS
*
* Here a non-numeric byte was met
*
NPR900 LDA #196 ;select error text
JMP PARMERR ;and report
***************************************
*
* MKRNAME
* =======
*
* Generates a remote filename from a
* local one
*
***************************************
MKRNAME EQU *
*
* Scan backwards, looking for a "."
*
STY WORK8 ;save offset to the CR
DEY
MKR100 LDA LFNAME,Y ;get a byte
CMP #'.'
BEQ MKR200 ;j if it's a "."
DEY ;else step back another
BPL MKR100 ;j if not at front yet
*
* Here we're pointing the byte before the last component. Copy this
* component to the remote name buffer
*
MKR200 INY
LDX #0 ;output pointer
MKR240 LDA LFNAME,Y
STA RFNAME,X
INX
INY
CPY WORK8 ;all done yet?
BNE MKR240 ;j if not
*
* Then add the defined suffix to the name
*
LDA SUFLEN ;get length of suffix
BEQ MKR600 ;j if null - nothing to add
LDA #'.'
STA RFNAME,X ;else add a "."
INX
LDY #0 ;and then the suffix
MKR400 CPX #MAXFNL-1 ;name now too long?
BEQ MKR600 ;j if so - take what we've got now
LDA SUFFIX,Y
STA RFNAME,X
INX
INY
CPY SUFLEN
BNE MKR400
*
* Round off the remote name with a CR
*
MKR600 LDA #$0D
STA RFNAME,X
*
* And that's it
*
RTS
***************************************
*
* CLRINT
* ======
*
* Clears interrupt status line
*
***************************************
CLRINT LDA #42
JSR MESS ;position cursor
JMP SPFILL ;clear to end of line
***************************************
*
* CHRPAR
* ======
*
* Checks current parameter is one byte
* only and picks it up
*
***************************************
CHRPAR LDY CURLEN
DEY
BNE CHP900 ;j if length not 1
LDA (CURPAR),Y ;else load the byte
RTS
CHP900 LDA #198 ;select error text
JMP PARMERR ;and report
***************************************
*
* LOCATE
* ------
*
* Returns cursor position
*
***************************************
LOCATE LDA #$86
JSR OSBYTE ;locate cursor
STX CSRX ;note position
STY CSRY
RTS
***************************************
*
* REPOSN
* ======
*
* Puts cursor back to CSRX, CSRY
*
***************************************
REPOSN LDA #31
JSR OSWRCH
LDA CSRX
JSR OSWRCH
LDA CSRY
JMP OSWRCH
***************************************
*
* HOME
* ----
*
* Homes cursor to top left
*
***************************************
HOME LDA #30
JMP OSWRCH
***************************************
*
* PRTSW
* =====
*
* Prints a setting from the ON/OFF
* option table
*
***************************************
PRTSW LDX #>ONOFTB+2 ;select table
LDY #<ONOFTB+2
JMP PRTENT ;and print it
***************************************
*
* PRTSWF
* ======
*
* Prints an ON/OFF option in a field
* size of 3
*
***************************************
PRTSWF STA WORK0 ;save entry number
LDA #3
JSR SETPEF ;set field width to 3
LDX #>ONOFTB+2 ;select table
LDY #<ONOFTB+2
JMP PEN100 ;side enter PRTENT
***************************************
*
* PRBYTE
* ======
*
* Prints a byte in ASCII
*
***************************************
PRBYTE TAX
LDY #0
SEC ;select 3 digit print
JMP PRDEC
***************************************
*
* PRTENT
* ======
*
* Prints a command table entry
*
***************************************
PRTENT STA WORK0 ;save entry number
LDA #0 ;set free format
STA WORK1
PEN100 STX PTR0 ;save pointer to table
STY PTR0+1
LDY #0 ;start table offset
LDA WORK0 ;get entry number
BEQ PEN400 ;j if we want entry 0
*
* Move to next entry and see if we've reached the one we want
*
PEN220 LDA (PTR0),Y ;get entry length
SEC ;add 1 for length byte itself
ADC PTR0 ;step to next entry
STA PTR0
BCC PEN240
INC PTR0+1
PEN240 DEC WORK0 ;decrease countdown
BNE PEN220 ;j if not there yte
*
* We've reached the entry, so print it in specifeid field width
*
PEN400 LDA WORK1 ;get field width
BEQ PEN410 ;j if free format
*
* Not free format, so calculate spaces needed
*
SEC
SBC (PTR0),Y ;field size - entry size
BMI PEN410 ;j if won't fit
BEQ PEN410 ;j if exact fit
*
* Specfill to where we start to print
*
TAX ;space coubt
LDA #' '
PEN405 JSR OSWRCH
DEX
BNE PEN405
*
* In right place now, so print the entry itself
*
PEN410 LDA (PTR0),Y ;get length byte
TAX
LDY #1 ;start offset
PEN420 LDA (PTR0),Y ;get a byte
JSR OSWRCH ;print it
INY
DEX
BNE PEN420 ;j if not at the end yet
*
* And finish
*
RTS
***************************************
*
* SETPEF
* ======
*
* Sets up field width for call to PRTEF
*
***************************************
SETPEF STA WORK1 ;save width
SPF900 RTS
***************************************
*
* PRTEF
* =====
*
* Prints a table entry in a set field
* width
*
***************************************
PRTEF STA WORK0 ;save entry number
JMP PEN100 ;side enter PRTENT
***************************************
*
* EBQON / EBQOFF
* ==============
*
* Shows on status screen 8 bit
* prefixing state and sets the flag
*
***************************************
EBQON LDX #$FF ;get new flag state
LDA #26 ;get message number
EBQ100 STX EBQFLG ;set the flag
BIT MODE ;are we in generic mode?
BVC SPF900 ;j if so - no display
JMP MESS ;else tell user
EBQOFF LDX #0 ;get new flag state
LDA #22 ;get message number
BNE EBQ100
***************************************
*
* WLOGB
* =====
*
* Writes the terminal log buffer to disc
*
***************************************
WLOGB STA WORK1 ;save count of bytes to write
LDX #0 ;start pointer
LDY LHAND ;get file handle
*
* Process the bytes
*
WLB100 LDA LOGBUF,X ;get the byte
JSR OSBPUT ;write the byte
INX ;step pointer
CPX WORK1 ;all done?
BNE WLB100 ;j if not
*
* All done
*
WLB900 RTS
***************************************
*
* FNDTOP
* ======
*
* Gets address of top line of VDU
*
***************************************
FNDTOP LDA #$A0 ;address is in VDU variables
LDX #$50 ;$50,$51
JMP OBX0
***************************************
*
* TIDYLN
* ======
*
* Ensures cursor is at start of empty
* line
*
***************************************
TIDYLN JSR LOCATE ;find cursor position
CPX #0
BEQ WLB900 ;no action if at start of line
JMP OSNEWL ;else start new line
***************************************
*
* RXINIT
* ======
*
* Initialises values for a receive transfer
*
***************************************
RXINIT LDA #0
STA NUMTRY ;clear retry count
STA BKASENT ;clear ACK/Z flag
STA TFSTOP ;clear interrupt flag
STA PENDFLG ;clear character-pending flag
RXI900 RTS
***************************************
*
* TAKDEL
* ======
*
* Delays for 1/4 second if command source
* is a TAKE file.
*
***************************************
TAKDEL LDA CSOURCE ;get command source
BEQ RXI900 ;j if not file - null call
JSR FLSHKB ;flush keyboard buffer
LDA #$81
LDX #25 ;select 25/100 second pause
JMP OBX0 ;do INKEY(25)
***************************************
*
* KEYRD
* =====
*
* Reads key, bypassing any EXEC file
*
***************************************
KEYRD JSR SUSEXF ;suspend any EXEC file
JSR OSRDCH ;read keyboard
JMP RSTEXF ;put EXEC back as it was
***************************************
*
* SETKEY
* ======
*
* Sets base values for function keys
*
***************************************
SETKEY STX PTR3 ;save address of base values table
STY PTR3+1
LDA #228
STA WORK1 ;set first OSBYTE code to use
LDA #3
STA WORK0 ;and counter
*
* Set up next base value
*
SKY200 LDY WORK0
LDA (PTR3),Y ;get value from table
TAX
LDA WORK1 ;get OSBYTE call
JSR OBX0 ;and do it
*
* Then on to the next
*
DEC WORK1 ;step OSBYTE code back one
DEC WORK0 ;step count
BPL SKY200 ;j if more to do
SKY900 RTS
***************************************
*
* ADJTT
* =====
*
* Adjusts terminal type to be a suitable
* default for the machine
*
***************************************
ADJTT BIT TTYPE ;is type still undecided?
BPL SKY900 ;j if not - do nothing
IF ROM
*
* ROM version assumes we'll use VT52
*
LDA #2
STA TTYPE ;set VT52 type
ELSE
*
* RAM version sets VT52 if we have shadow screen, else TT40
*
BIT SHADOW
BMI ATT300 ;j if we have shadow screen
INC TTYPE ;else set TT40
BEQ ATT400
ATT300 LDA #2
STA TTYPE ;we have shadow so set VT52
FI
*
* Then we ask any TXR fitted if we should change this
*
ATT400 LDX #$80
JSR DOKOSB ;ask a TXR
BVS SKY900 ;j if none there or it doesn't want to change
STX TTYPE ;else use what it asks for
RTS
NEXT BBCSB4
****** File BBCSB4 *************************************************************
START SB4
* BBCSB4: Updated 05/05/86 @ 1800
***************************************
*
* HEXPAR
* ======
*
* Converts current parameter from hex
* to binary
*
***************************************
HEXPAR LDY #0 ;start pointer
STY NUM ;and total value
STY NUM+1
*
* First byte could be $, X or &
*
LDA (CURPAR),Y ;get byte
JSR HEXFLG ;check for X, $, &
BCC HXP800 ;j if one of them - step over it
BCS HXP120 ;else it's got to be a hex digit
*
* See if next byte is valid hex
*
HXP100 LDA (CURPAR),Y
JSR UPPER ;force upper case
HXP120 CMP #'0'
BCC HXP900 ;j if illegal
CMP #'9'+1
BCC HXP200 ;j if '0'..'9'
CMP #'A'
BCC HXP900 ;j if illegal
CMP #'F'+1
BCS HXP900 ;j if illegal
*
* Byte is 'A'..'F'
*
SEC
SBC #'A'-10 ;scale to 10..15
BNE HXP300
*
* Byte is '0'..'9'
*
HXP200 AND #$0F ;scale to 0..9
*
* Multiply total by 16 and add new byte in
*
HXP300 LDX #3
HXP320 ASL NUM
ROL NUM+1
DEX
BPL HXP320
ORA NUM ;put in new byte
STA NUM
*
* And carry on
*
HXP700 INY
CPY CURLEN
BNE HXP100 ;j if more to do
RTS ;else end
*
* Here first character is X, $ or &
*
HXP800 INY
LDX CURLEN ;any more in string?
DEX
BNE HXP100 ;j if so, else error
*
* Here digit is invalid
*
HXP900 JMP NPR900
***************************************
*
* CLOCK
* =====
*
* Resets the interval timer to 1 second
*
***************************************
CLOCK LDX #>CBLK
LDY #<CBLK
LDA #4
JMP OSWORD ;set time period
CBLK HEX '9CFFFFFFFF'
***************************************
*
* STCLCK
* ======
*
* Starts the clock ticker running
*
***************************************
STCLCK SEI
STA TICKER ;set interval wanted
JSR CLOCK ;reset the timer period
CLI
RTS
***************************************
*
* PRFTYPE
* =======
*
* Prints the current file type
*
***************************************
PRFTYPE EQU *
*
* First the type itself
*
LDX #>STYTAB+2 ;select table
LDY #<STYTAB+2
LDA FTYPE ;get the type
JSR PRTENT ;print it
*
* If ASCII, add end-of-record type
*
LDA FTYPE
BNE PFT900 ;j if not ASCII
LDA #' '
JSR OSWRCH ;else print a space
LDX #>SASTAB+2 ;select table
LDY #<SASTAB+2
LDA EORTYPE ;get EOR type
JSR PRTENT ;print it
*
* And finish
*
PFT900 RTS
***************************************
*
* FBINIT
* ======
*
* Initialises the file transfer buffer
*
***************************************
FBINIT EQU *
IF ROM
*
* For ROM version buffer could be for file or memory
*
CMP #0
BEQ FBI500 ;j if using for a file
*
* Buffer is for a MEMORY transfer - but which way?
*
CPX #0
BEQ FBI300 ;j if receiving
*
* Set buffer to send from MEMORY
*
LDA MSBASE ;set base address
STA FBUFF
LDA MSBASE+1
STA FBUFF+1
LDA MSTOP ;set limit address
STA FBMAX
LDA MSTOP+1
STA FBMAX+1
JMP FBI400 ;and compute size, etc
*
* Set up for receive into MEMORY
*
FBI300 LDA MDBASE ;set base pointer
STA FBUFF
LDA MDBASE+1
STA FBUFF+1
LDA MDTOP ;and limit address
STA FBMAX
LDA MDTOP+1
STA FBMAX+1
*
* Compute size, etc, of memory buffer
*
FBI400 LDA FBMAX ;set limit as the high water mark
STA FBTOP
LDA FBMAX+1
STA FBTOP+1
LDA FBUFF ;set base as the receive pointer
STA FBPTR
LDA FBUFF+1
STA FBPTR+1
LDA FBMAX ;and get the size
SEC
SBC FBUFF
STA FBSIZE
LDA FBMAX+1
SBC FBUFF+1
STA FBSIZE+1
*
* And finish
*
RTS
FI
*
* Here buffer will hold a real file
*
FBI500 EQU *
IF ROM
*
* ROM version takes memory from OSHWM up
*
LDA #$B4 ;find OSHWM
LDX #0
LDY #$FF
JSR OSBYTE ;ms byte is in X
LDA #0
STA FBUFF ;set OSHWM as buffer start
STX FBUFF+1
ELSE
*
* RAM version takes space above program and patches
*
LDY PTPPTR ;set up base of buffer
STY FBUFF
LDY PTPPTR+1
STY FBUFF+1
FI
*
* Size is as set by SET FILE BUFFER
*
LDA #0
STA FBSIZE
IF ROM
LDA FBPAGES
ELSE
LDA #8
FI
STA FBSIZE+1
*
* Then calculate last address in buffer + 1
*
LDA FBUFF
CLC
ADC FBSIZE
STA FBMAX
LDA FBUFF+1
ADC FBSIZE+1
STA FBMAX+1
*
* And finish
*
FBI900 RTS
***************************************
*
* LFDUMMY
* =======
*
* Sets up a fake local filename as
* <MEMORY> or <PRINTER>
*
***************************************
LFDUMMY LSR A ;form 0=MEMORY,1=PRINTER
TAX ;point to dummy string
LDA LFDTBL,X
STA PTR0
LDA LFDTBH,X
STA PTR0+1
*
* Copy dummy string to local filename buffer
*
LDY #9
LFD300 LDA (PTR0),Y
STA LFNAME,Y
DEY
BPL LFD300
*
* Set "local name given" flag and finish
*
LDY #1
STY LFGIVEN
RTS
LFDMEM ASC '<MEMORY> '
DFB $0D
LFDPRT ASC '<PRINTER>'
DFB $0D
LFDTBL DFB >LFDMEM
DFB >LFDPRT
LFDTBH DFB <LFDMEM
DFB <LFDPRT
***************************************
*
* WAIT
* ====
*
* Waits for a given time or a keypress,
* whichever comes first
*
***************************************
WAIT CMP #0
BEQ FBI900 ;null call if zero interval
PHA ;else save delay time
JSR FLSHKB ;flush keyboard buffer
PLA ;get interval back
JSR STCLCK ;start the clock
*
* Got a key press?
*
WAI200 JSR INKEY ;do INKEY(0)
BCC WAI800 ;j if key down
*
* No key down. Timer expired?
*
LDA TICKER
BNE WAI200 ;j if not
WAI700 RTS ;else exit
*
* Had a keypress here.
*
WAI800 TXA
WAI820 CMP #$1B ;is it ESCAPE?
BEQ WAI900 ;j if it was
RTS ;ele we exit
*
* Had an ESCAPE key, so abort command, force input back to keyboard and exit
* Since ESCAPE here never generates an ESCAPE condition we'll close EXEC file
* by hand
*
WAI900 JSR KBDSRC ;close TAKE and EXEC files
JMP RDL131 ;and BRK
***************************************
*
* WTKEY
* =====
*
* Waits indefinitely till key press,
* checking for ESCAPE
*
***************************************
WTKEY JSR FLSHKB ;clear keyboard buffer
JSR KEYRD ;read character, bypassing EXEC file
JMP WAI820
***************************************
*
* COUNTF
* ======
*
* Adds to count of filenames in a group
*
***************************************
COUNTF INC FCOUNT ;step counter
LDA #31
JSR MESS ;position cursor
LDA FCOUNT
JMP PRBYTE ;display it
***************************************
*
* TSTESC
* ======
*
* Checks for ESCAPE and closes TAKE file
* if we find one
*
***************************************
TSTESC BIT $FF ;poll ESCAPE flag
BPL WAI700 ;j if not set
JMP WAI900 ;force TAKE and EXEC files to close and then BRK
***************************************
*
* ACKESC
* ======
*
* Acknowledges an ESCAPE condition
*
***************************************
ACKESC LDA #$7E
JMP OSBYTE
***************************************
*
* CLTAKE
* ======
*
* Closes a TAKE file if one is open
*
***************************************
CLTAKE LDY TKHAND ;is TAKE file open?
BEQ CLT900 ;j if not
JSR CLOSEY ;else close it
LDA #0
STA TKHAND ;clear the handle out
STA CSOURCE ;make command source keyboard
CLT900 RTS
***************************************
*
* DEFAULT
* =======
*
* Returns SET values to their default
* state
*
***************************************
DEFAULT LDY #DEFCNT-1
DEF100 LDA DEFTAB,Y ;copy from ROM table
STA DFBASE,Y
DEY
BPL DEF100
*
* Then set dependant values
*
DEF500 JSR SETEOR ;end of record
JMP SETPTY ;parity
***************************************
*
* SETEOR
* ======
*
* Sets end-of-record values from the
* SET parameters
*
***************************************
SETEOR LDA EORTYPE ;get type of EOR
JMP SAS300 ;set dependencies
***************************************
*
* SETPTY
* ======
*
* Sets up parity values, etc
*
***************************************
SETPTY LDY PARITY ;get the SET value
JMP SPY100 ;set things up
***************************************
*
* VALEBQ
* ======
*
* Tests if a character is legal as an
* 8 bit prefix
*
***************************************
VALEBQ CMP #'!'
BCC VAL900 ;j if not legal
CMP #'>'+1
BCC VAL800 ;j if legal
CMP #97
BCC VAL900 ;j if not legal
CMP #'~'+1
BCS VAL900 ;j if not legal
*
* Here it's legal
*
VAL800 CLC
RTS
*
* Here it's not legal
*
VAL900 SEC
RTS
***************************************
*
* STDVEC
* ======
*
* Restores all OS vectors apart from
* those used by DFS to their default
* settings
*
***************************************
STDVEC PHP
SEI
*
* Get pointer to the defaults table in the OS ROM
*
LDA STDVPTR
STA PTR0
LDA STDVPTR+1
STA PTR0+1
*
* Reset the low non-filing-system vectors first
* (USERV to RDCHV inclusive)
*
LDY #$11
STV200 LDA (PTR0),Y ;copy byte down
STA $0200,Y
DEY
BPL STV200 ;j till all done
*
* Now the high non-filing system vectors
* (EVENTV to IND3V inclusive)
*
LDY #$35
STV300 LDA (PTR0),Y ;copy byte down
STA $0200,Y
DEY
CPY #$1F
BNE STV300 ;j till all done
*
* And finish
*
PLP
RTS
***************************************
*
* GETSYS
* ======
*
* Sets up system control values
*
***************************************
GETSYS PHP
SEI
IF ROM
JSR GETEV ;take EVENT vector
ELSE
JSR GETEV ;take EVENT vector
LDA IRQ1V ;take a copy of IRQ1
STA OLDIRQ
LDA IRQ1V+1
STA OLDIRQ+1
LDA #>IRQENT ;then point it to us
STA IRQ1V
LDA #<IRQENT
STA IRQ1V+1
FI
*
* Take the BRK vector
*
JSR GETBRK
*
* Enable timer events
*
LDA #14
LDX #5
JSR OBX0 ;turn event on
*
* And finish
*
PLP
RTS
***************************************
*
* LOSESYS
* =======
*
* Restores system to normal state
*
***************************************
LOSESYS EQU *
*
* Disable timer events
*
LDA #13
LDX #5
JSR OBX0
*
* Reset vectors to normal
*
JMP STDVEC
***************************************
*
* LSTMPAR
* =======
*
* Gets mandatory parameter and checks
* it's the last
*
***************************************
LSTMPAR JSR SETHLP ;set help text
JSR MPARAM ;get parameter
JMP CONFIRM ;check no more
***************************************
*
* LSTMNP
* ======
*
* Gets mandatory numeric parameter and
* checks it's the last
*
***************************************
LSTMNP JSR GETMPAR ;get the parameter
JSR NUMPAR ;convert to binary
JMP CONFIRM ;check no more
***************************************
*
* LSTPAR
* ======
*
* Gets optional parameter and checks there
* are no more
*
***************************************
LSTPAR JSR GETPAR ;see if param is there
BCS LPR900 ;j if not
JSR CONFIRM ;else check no more
CLC
LPR900 RTS
***************************************
*
* GETPAR
* ======
*
* Gets optional parameter
*
***************************************
GETPAR JSR SETHLP ;set help text
JMP PARAM ;see if param there
***************************************
*
* GETMPAR
* =======
*
* Gets mandatory parameter
*
***************************************
GETMPAR JSR SETHLP ;set help text
JMP MPARAM ;get the parameter
***************************************
*
* GMPAS
* =====
*
* Gets mandatory parameter and validates
* it
*
***************************************
GMPAS JSR MPARTAB ;get parameter
CLC ;allow abbreviations
JMP SCANTAB ;and validate it
***************************************
*
* GETMFN
* ======
*
* Gets mandatory filename parameter and
* checks the length
*
***************************************
GETMFN JSR GETMPAR ;get parameter
JMP CHKFNL ;check the length is OK
***************************************
*
* GETFN
* =====
*
* Gets optional filename parameter and
* checks the length
*
***************************************
GETFN JSR GETPAR ;is parameter there?
BCS GFN900 ;j if not
JSR CHKFNL ;else validate length
CLC
GFN900 RTS
***************************************
*
* MPARTAB
* =======
*
* Gets mandatory parameter using an
* option table
*
***************************************
MPARTAB JSR SELTAB ;set up the table
JMP MPARAM ;get the parameter
***************************************
*
* PARTAB
* ======
*
* Gets optional parameter using an
* option table
*
***************************************
PARTAB JSR SELTAB ;set up table
JMP PARAM ;see if param is there
***************************************
*
* LSTMSWP
* =======
*
* Gets mandatory ON/OFF parameter and
* checks there are no more
*
***************************************
LSTMSWP JSR ONOFPAR ;get the parameter
JMP CONFIRM ;check no more
***************************************
*
* LSTMCP
* ======
*
* Gets a mandatory single-character
* parameter and checks it's the last
*
***************************************
LSTMCP JSR GETMPAR ;get parameter
JSR CHRPAR ;check it's one character
JMP CONFIRM ;check no more there
***************************************
*
* CLOSEY
* ======
*
* Closes file whose handle is in Y
*
***************************************
CLOSEY LDA #0
JMP OSFIND
***************************************
*
* GETEV
* =====
*
* Takes control of the EVENT vector
*
***************************************
GETEV PHP
SEI
IF ROM
LDA #$FF ;point $200 vector to extended area
STA EVENTV+1
LDA #3*(EVENTV-$200)/2
STA EVENTV
LDY #3*(EVENTV-$200)/2 ;point extended vector to us
LDA #>EVENT
STA (EVECTB),Y
LDA #<EVENT
INY
STA (EVECTB),Y
INY
LDA $F4 ;and put in our ROM number
STA (EVECTB),Y
ELSE
LDA #>EVENT
STA EVENTV
LDA #<EVENT
STA EVENTV+1
FI
PLP
RTS
***************************************
*
* KBDSRC
* ======
*
* Closes any TAKE and EXEC files open
*
***************************************
KBDSRC LDA #$77
JSR OSBYTE ;close EXEC file
JMP CLTAKE ;and TAKE file
***************************************
*
* RDEXH
* =====
*
* Reads and checks EXEC file handle
*
***************************************
RDEXH PHA ;save A
LDA #$C6
JSR RSYSVAL ;read EXEC handle
PLA ;restore A
CPX #0 ;test EXEC handle
RTS
NEXT BBCTX1
****** File BBCSHW *************************************************************
START SHW
* BBCSHW: Updated 05/05/86 @ 1800
***************************************
*
* SHOW
* ====
*
* Displays current parameters
*
***************************************
SHOW JSR CONFIRM ;check no more params
*
* SHOW output uses a MODE 7 screen, whether or not user has a MODE 3 screen
* selected
*
LDA #2 ;set system mode to 2 to force a
STA MODE ;change back to original MODE at end
LDA #110
JSR MESS ;put up the MODE 7 command screen
*
* GENERAL PARAMETERS
* ------------------
*
LDA #76
JSR MESS ;first the header
*
* Receive baud rate
*
LDX #63 ;header text number
LDA RXBAUD ;get the rate
JSR SHBAUD ;print the entry (formatted)
*
* Transmit baud rate
*
LDX #30 ;header text number
LDA TXBAUD ;get the value
JSR SHBAUD ;print it
*
* Parity
*
LDA #66
JSR MESS ;print header
LDA #5
JSR SETPEF ;set field width of 5
LDA PARITY ;get the value
LDX #>SPATB1+2
LDY #<SPATB1+2
JSR PRTEF ;print table entry (formatted)
*
* Debugging
*
LDX #64 ;header text number
LDA DEBUG ;get value
JSR SHSW ;print OFF/ON
*
* Retry limit
*
LDX #67 ;header text number
LDA MAXTRY ;get the value
JSR SHBYTE ;print in decimal
*
* Timer switch
*
LDX #80 ;header text number
LDA TIMER ;get value
JSR SHSW ;print OFF/ON
*
* 8 bit prefix character
*
LDX #41 ;header text
LDA CUREBQ ;get the character
JSR SHCHAR ;print it
*
* Delay after SEND command
*
LDX #69 ;header text number
LDA DELAY ;get the value
JSR SHBYTE ;print in decimal
*
* Pause before packet send
*
LDX #68 ;header text number
LDA PAUSE ;get value
JSR SHBYTE ;print in decimal
*
* TAKE file echoing
*
LDX #118 ;header text number
LDA TKECHO ;get the value
JSR SHSW ;print as ON/OFF
*
* Help trigger
*
LDX #146 ;header text value
LDA HLPTRG ;get the character
JSR SHCHAR ;and print it
*
* Flow control
*
LDA #129 ;print header
JSR MESS
LDA #8
JSR SETPEF ;select field width of 8
LDA FLOW ;get the flow-control type
LDX #>SFCTAB+2 ;point command table
LDY #<SFCTAB+2
JSR PRTEF ;print table entry (formatted)
*
* MUX wait period
*
LDX #57 ;header text number
LDA MUXWT ;get the value
JSR SHBYTE ;print in decimal
*
* Handshake type
*
LDA #55
JSR MESS ;print the header
LDA #4
JSR SETPEF ;select field width
LDA HSHAKE ;get handshake type in use
LDX #>SKTAB+2 ;point to table
LDY #<SKTAB+2
JSR PRTEF ;print table entry (formatted)
*
* RECEIVE PARAMETERS
* ------------------
*
LDA #77
JSR MESS ;print the title
*
* Packet length
*
LDX #18 ;header text number
LDA RMAXL ;get the value
JSR SHBYTE ;print in decimal
*
* Pad character
*
LDX #82 ;header text number
LDA RPADC ;get the character
JSR SHHEX ;print in hex
*
* Start of packet marker
*
LDX #83 ;header text number
LDA RSOP ;get the character
JSR SHHEX ;print in hex
*
* Padding count
*
LDX #88 ;header text number
LDA RNPAD ;get the value
JSR SHBYTE ;print in decimal
*
* Timeout
*
LDX #89 ;header text number
LDA RTIME ;get the value
JSR SHBYTE ;print in decimal
*
* SEND PARAMETERS
* ---------------
*
LDA #78
JSR MESS ;print the title
*
* Quote character
*
LDX #71 ;header text number
LDA SQUOTE ;get the character
JSR SHCHAR ;print it
*
* Pad character
*
LDX #82 ;header text number
LDA SPADC ;get the character
JSR SHHEX ;print in hex
*
* Start-of-packet marker
*
LDX #83 ;header text number
LDA SSOP ;get the character
JSR SHHEX ;print in hex
*
* Padding count
*
LDX #88 ;header text value
LDA SNPAD ;get the value
JSR SHBYTE ;print in decimal
*
* Timeout
*
LDX #89 ;header tet number
LDA STIME ;get the value
JSR SHBYTE ;print in decimal
*
*
* PAGE BREAK
* ----------
* Screen is full here, so wait for key
*
LDA #14
JSR MESS ;tell user
JSR FLSHKB ;flush keyboard buffer
SHW200 JSR KEYRD ;read a character, bypassing EXEC file
CMP #$0D
BEQ SHW205 ;j if CR - carry on
CMP #$1B
BNE SHW200 ;j if not ESCAPE - ignore
*
* ESCAPE pressed, so finish
*
LDA #$0C
JSR OSWRCH ;clear screen
RTS ;and exit
*
* CR pressed, so clear screen and carry on
*
SHW205 LDA #$0C
JSR OSWRCH ;clear screen
*
*
* TERMINAL EMULATION PARAMETERS
* -----------------------------
*
LDA #79
JSR MESS ;print the title
*
* Terminal type
*
LDA #70
JSR MESS ;print header
LDA #6 ;select field width
JSR SETPEF
LDX #>STTAB+2 ;point to table
LDY #<STTAB+2
LDA TTYPE ;get value
JSR PRTEF ;print table entry (formatted)
*
* *TV paraneters
*
LDA #140
JSR MESS ;print the header
LDA TVFLAG ;is facility on?
BEQ SHW210 ;j if not
LDA TVPAR1
JSR PRBYTE ;else print the first param
LDA #' '
JSR OSWRCH ;then a space
LDA TVPAR2
JSR PRBYTE ;print the second param
JMP SHW220
SHW210 JSR OSNEWL ;facility off, so end line here
*
* Local echo
*
SHW220 LDX #74 ;header text number
LDA ECHO
JSR SHSW ;print OFF/ON
*
* Terminal session logging
*
LDA LHAND ;get file handle
BEQ SHW240 ;j if no file open
LDA #1 ;else value is 1 for ON
SHW240 LDX #112 ;header tet number
JSR SHSW ;print as ON/OFF
*
* Key click
*
LDX #121 ;header text number
LDA CLICK ;get value
JSR SHSW ;print as ON/OFF
*
* Text colour
*
LDA #133 ;if we're ROM version...
JSR MESS ;...print the header
LDA #7
JSR SETPEF ;select field width of 7
LDX VDUCOL ;get actual colour used
DEX ;one less for table entry
TXA
LDX #>SVDCTB+2 ;point to table
LDY #<SVDCTB+2
JSR PRTEF ;print entry (formatted)
*
* Ignore character
*
LDA #139
JSR MESS ;print the header
LDA IGNFLG ;is a character defined?
BEQ SHW260 ;j if not
LDA #'&'
JSR OSWRCH ;else print an &
LDA IGNCHR ;get the character
JSR PRHEX ;print it in hex
JMP SHW290
SHW260 LDA #' ' ;char not defined, so 3 spaces
JSR OSWRCH
JSR OSWRCH
JSR OSWRCH
*
* FILE PARAMETERS
* ---------------
*
SHW290 LDA #84
JSR MESS ;print the title
*
* File type
*
LDA #85
JSR MESS ;print header
LDA #6
JSR SETPEF ;select field of 6
LDA FTYPE ;get value
LDX #>STYTAB+2 ;select table
LDY #<STYTAB+2
JSR PRTEF ;print entry (formatted)
*
* End of record indicator
*
LDA #108
JSR MESS ;print header
LDA FTYPE ;look at file type
BEQ SHW300 ;j if ASCII
JSR OSNEWL ;else leave entry blank
JMP SHW320
SHW300 LDA #4 ;Type is ASCII, so set field of 4
JSR SETPEF
LDA EORTYPE ;get the value
LDX #>SASTAB+2 ;select the table
LDY #<SASTAB+2
JSR PRTEF ;print entry (formatted)
*
* Incomplete file disposition
*
SHW320 LDA #105
JSR MESS ;print the title
LDA #6
JSR SETPEF ;select field width of 6
LDA FINCOM ;get the action
LDX #>SITAB+2
LDY #<SITAB+2
JSR PRTEF ;print entry (formatted)
*
* File warning
*
LDX #106 ;header text number
LDA FWARN ;get the action
JSR SHSW ;print as ON/OFF
*
* File buffer size
*
LDX #109 ;header text number
IF ROM
LDA FBPAGES ;get value
ELSE
LDA #8
FI
JSR SHBYTE ;print in decimal
*
* File suffix
*
LDA #115
JSR MESS ;print header
LDA #8
SEC
SBC SUFLEN ;calculate padding needed
BEQ SHW340 ;j if none
TAY ;else pad with spaces
LDA #' '
SHW330 JSR OSWRCH
DEY
BNE SHW330
SHW340 LDX SUFLEN ;look at suffix size
BEQ SHW360 ;j if null string
LDY #0 ;else print it
SHW350 LDA SUFFIX,Y
JSR OSWRCH
INY
DEX
BNE SHW350
SHW360 EQU *
*
* File name translation mode
*
LDA #215
JSR MESS ;print header
LDA #12
JSR SETPEF ;set field width of 12
LDA FNTYPE ;get current value
LDX #>SFNTAB+2 ;point to table
LDY #<SFNTAB+2
JSR PRTEF ;and print the value
*
*
* TRANSFER PARAMETERS
* -------------------
*
LDA #13
JSR MESS ;print the title
IF ROM
*
* Data source
*
LDA #86
JSR MESS ;print the header
LDA SOURCE ;get the value
LDX #>SSRTAB+2
LDY #<SSRTAB+2
JSR PRTENT ;print value in free format
LDA SOURCE
BEQ SHW600 ;j if FILE - no more here
LDA #' '
JSR OSWRCH ;else print a space
LDX MSBASE ;get the base address
LDY MSBASE+1
JSR PRWHEX ;print in hex
LDA #' '
JSR OSWRCH ;add a space
LDX MSTOP ;get the top address
LDY MSTOP+1
JSR PRWHEX ;print in hex
FI
*
* Data destination
*
SHW600 LDA #87
JSR MESS ;print the header
LDA DESTIN ;get the value
IF RAM
BEQ SHW610 ;if RAM, value 0 is OK
LDA #1 ;else convert 2 to 1 to match weird table
SHW610 EQU *
FI
LDX #>SDETAB+2
LDY #<SDETAB+2
JSR PRTENT ;print entry in free format
LDA DESTIN
CMP #1
BNE SHW620 ;j if not MEMORY - no more to do
LDA #' '
JSR OSWRCH ;else add a space
LDX MDBASE ;get the base address
LDY MDBASE+1
JSR PRWHEX ;print in hex
*
* Now wait for user to press a key
*
SHW620 LDA #178
JSR MESS ;prompt him
JMP WTKEY ;and wait on key
***************************************
*
* SHBAUD
* ======
*
* Outputs the entry for baud rate
*
**************************************
SHBAUD PHA ;save setting
JSR SHHDR ;print header text
LDA #5
JSR SETPEF ;select field width of 5
PLA ;reload setting
TAX
DEX ;adjust to be table entry
TXA
LDX #>SBATAB+2 ;point to table
LDY #<SBATAB+2
JMP PRTEF ;print formatted entry
***************************************
*
* SHSW
* ====
*
* Prints an ON/OFF setting
*
***************************************
SHSW JSR SHHDR ;print header text
JMP PRTSWF ;and print it
***************************************
*
* SHBYTE
* ======
*
* Prints a one-byte numeric value in decimal
*
***************************************
SHBYTE JSR SHHDR ;print header
JMP PRBYTE ;print the value
***************************************
*
* SHCHAR
* ======
*
* Prints a character value
*
***************************************
SHCHAR JSR SHHDR ;print header
JMP OSWRCH ;then the character
***************************************
*
* SHHEX
* =====
*
* Prints a one-byte value in hex
*
***************************************
SHHEX JSR SHHDR ;print header
JMP PRHEX ;print the byte
***************************************
*
* SHHDR
* =====
*
* Prints the header text whose number is
* in X
*
***************************************
SHHDR PHA
TXA
JSR MESS
PLA
RTS
CHN BBCREC
****** File BBCSND *************************************************************
START SND
* BBCSND: Updated 05/05/86 @ 2145
***************************************
*
* SENDSW
* ======
*
* The state table switcher for file
* sending
*
***************************************
SENDSW EQU *
*
* If source is a TAKE file, we do a short delay
*
JSR TAKDEL
*
* Initialise buffer for current source of data
*
LDA SOURCE ;select source
LDX #1 ;mode is send
JSR FBINIT
*
* Set initial state to SEND_INIT
*
LDA #'S'
STA STATE
*
* Ensure comms buffer is clear
*
JSR FLUSH
*
* Initialise protocol values and counts
*
JSR KINIT
*
* Log new position and state
*
SSW050 LDA #8 ;get text number
JSR LOGST ;log it
*
* Switch on our current state to the correct handler
*
LDA STATE
CMP #'S'
BEQ SSW100 ;j if SEND_INIT
CMP #'F'
BEQ SSW200 ;j if SEND_FILE
CMP #'D'
BEQ SSW300 ;j if SEND_DATA
CMP #'Z'
BEQ SSW400 ;j if SEND_EOF
CMP #'B'
BEQ SSW500 ;j if SEND_BREAK
CMP #'C'
BEQ SSW600 ;j if COMPLETE
*
* Here we're in an unknown state, so break
*
JMP RSW090
*
*
*
* State SEND_INIT
* ---------------
*
SSW100 JSR SINIT
JMP SSW050
*
*
* State SEND_FILE
* ---------------
*
SSW200 JSR SFILE
JMP SSW050
*
*
* State SEND_DATA
* ---------------
*
SSW300 JSR SDATA
JMP SSW050
*
*
* State SEND_EOF
* --------------
*
SSW400 JSR SEOF
JMP SSW050
*
*
* State SEND_BREAK
* ----------------
*
SSW500 JSR SBREAK
JMP SSW050
*
*
* State COMPLETE
* --------------
*
SSW600 RTS
***************************************
*
* STATE SEND_INIT
* ---------------
*
***************************************
SINIT JSR CHKTRY ;check retry limit
*
* Build our parameters and send an S packet
*
SEC ;note we're sending
JSR SPAR ;set up parameters
LDA #'S' ;type is 'S'
LDX #0 ;sequence number 0
JSR SPACK ;and send it
*
* Read the reply from the host
*
JSR RPACK
BCC SIN040 ;j if read it OK
RTS ;else stay in this state to re-send
*
* Branch on packet type
*
SIN040 CMP #'N'
BEQ SIN200 ;j if N
CMP #'Y'
BEQ SIN300 ;j if Y
CMP #'E'
BEQ SIN400 ;j if E
*
* Packet type invalid here, so abort
*
SIN050 JMP ABORT
*
*
* NAK received
* ------------
*
SIN200 RTS ;stay in this state
*
*
* ACK received
* ------------
*
SIN300 JSR VALSEQ ;is it the expected one?
BCS SIN200 ;j if not - stay in this state
JSR INPARS ;else analyse what host sent
*
* Clear count of files in group
*
SIN340 LDA #0
STA FCOUNT
*
* Then we go to state SEND_FILE
*
LDA #'F'
STA STATE
RTS
*
*
* ERROR received
* --------------
*
SIN400 JMP ERRPKT
***************************************
*
* STATE SEND_FILE
* ===============
*
***************************************
SFILE JSR CHKTRY ;check retry limit
*
* Retries OK so far. Is a file open yet?
*
LDA FHAND
BNE SFI190 ;j if one is open
*
* File not yet open, so open it
*
LDX #>LFNAME ;point to name
LDY #<LFNAME
LDA #$40 ;read mode
JSR FOPEN ;try to open it
*
* Now build an F packet to send to the other end
*
SFI190 LDY #0
SFI200 LDA RFNAME,Y ;take name from remote name buffer
CMP #$0D
BEQ SFI220 ;stop when CR reached
STA TXBUFF,Y
INY
BNE SFI200
*
* Y holds length of name now, so save as packet data size
*
SFI220 STY DATLEN
*
* Now send the F packet
*
LDA #'F' ;set type
LDX NXTPAK ;and number
JSR SPACK
*
* Get the reply in
*
JSR RPACK
BCC SFI240 ;j if read it OK
RTS ;else stay in this state to resend
*
* Branch on packet type
*
SFI240 CMP #'E'
BEQ SFI800 ;j if E
CMP #'Y'
BEQ SFI700 ;j if Y
CMP #'N'
BEQ SFI600 ;j if N
*
* Packet type not expected, so abort
*
SFI400 JMP ABORT
*
*
*
* NAK received
* ------------
*
SFI600 JSR VALNAK ;can we take it as ACK?
BCC SFI705 ;j if we can
SFI620 RTS ;no, so stay in current state
*
*
* ACK received
* ------------
*
SFI700 JSR VALSEQ ;see if it's expected ACK
BCS SFI620 ;j if not - stay in current state
*
* Clear flags out now
*
LDA #0
STA EORSEQ ;not in EOR sequence
STA PENDFLG ;no char to inject
STA TFSTOP ;not interrupted
*
* Clear flag for 'non ASCII warning given'
*
STA BINWRN
LDA #97
JSR MESS ;position cursor
JSR SPFILL ;ensure text isn't on screen
JSR CLRINT ;clear interrupt status line
*
* Count this file and clear current Kbyte count
*
JSR COUNTF
JSR CLRKBC
*
* So set up the first data packet from the file
*
SFI705 JSR BUFILL ;try to set up D packet
BCS SFI720 ;j if file is empty
LDA #'D'
SFI710 STA STATE ;else go to state SEND_DATA
RTS ;and exit
*
* File is empty, so go straight to state SEND_EOF
*
SFI720 LDA #'Z'
BNE SFI710
*
*
* ERROR received
* --------------
*
SFI800 JMP ERRPKT
***************************************
*
* STATE SEND_DATA
* ===============
*
***************************************
SDATA JSR CHKTRY ;check retry limit
*
* Have we had CTRL-X or CTRL-Z on the keyboard?
*
BIT TFSTOP
BPL SDA020 ;j if not
SDA010 CLC ;we have, so close file
JSR FCLOSE
LDA #0
STA NUMTRY ;clear try counter again
JMP SDA780 ;go to state SEND_EOF
*
* OK to go ahead. Send the pre-built D packet
*
SDA020 LDA #'D' ;set type
LDX NXTPAK ;and number
LDY TXDLEN ;if retry, DATLEN has changed, so set it
STY DATLEN ;up properly again
JSR SPACK
*
* Get the reply in
*
JSR RPACK
BCC SDA040 ;j if read OK
RTS ;else stay in this state to resend
*
* Branch on packet type
*
SDA040 CMP #'N'
BEQ SDA600 ;j if N
CMP #'Y'
BEQ SDA700 ;j if Y
CMP #'E'
BEQ SDA800 ;j if E
*
* Packet type not expected, so abort
*
SDA050 JMP ABORT
*
*
* NAK received
* ------------
*
SDA600 JSR VALNAK ;can we take it as ACK?
BCC SDA720 ;j if so
SDA620 RTS ;else stay in this state
*
*
* ACK received
* ------------
*
SDA700 JSR VALSEQ ;is it the expected one?
BCS SDA620 ;j if not - stay in same state
*
* Is this an ACK/Z or ACK/X?
*
LDA DATLEN ;get packet data size
BEQ SDA720 ;j if no data - ordinary ACK
LDA RXBUFF ;else get the first data byte
CMP #'X'
BEQ SDA705 ;j if ACK/X
CMP #'Z'
BNE SDA720 ;j if not then ACK/Z
*
* Other end sent ACK/X or ACK/Z to interrupt us
*
LDA #%11000000
STA TFSTOP ;ACK/Z
BMI SDA010
SDA705 LDA #%10000000
STA TFSTOP ;ACK/X
BMI SDA010
*
* Ordinary ACK from other end. Try to packet up some more data
*
SDA720 JSR BUFILL ;try to build a D packet
BCS SDA780 ;j if no more data in file
LDA #'D'
SDA760 STA STATE ;ensure we're in state SEND_DATA
RTS ;and finish
*
* Here file has reached EOF, so we've done
*
SDA780 LDA #'Z' ;go to state SEND_EOF
BNE SDA760
*
*
* ERROR received
* --------------
*
SDA800 JMP ERRPKT
***************************************
*
* STATE SEND_BREAK
* ================
*
***************************************
SBREAK JSR CHKTRY ;check retry limit
*
* Send the B packet
*
JSR STDBREAK
*
* Get the reply in
*
JSR RPACK
BCC SBR040 ;j if read OK
RTS ;else stay in this state to resend
*
* Branch on packet type
*
SBR040 CMP #'N'
BEQ SBR600 ;j if N
CMP #'Y'
BEQ SBR700 ;j if Y
CMP #'E'
BEQ SBR800 ;j if E
*
* Packet type unexpected, so abort
*
SBR050 JMP ABORT
*
*
*
* NAK received
* ------------
*
SBR600 JSR VALNAK ;can we treat as ACK?
BCC SBR700 ;j if we can
SBR620 RTS ;else stay in this state
*
*
* ACK received
* ------------
*
SBR700 JSR VALSEQ ;is it the expected one?
BCS SBR620 ;j if not - stay in same state
LDA #'C' ;else set state to COMPLETE
STA STATE
RTS ;and finish
*
*
* ERROR received
* --------------
*
SBR800 JMP ERRPKT
***************************************
*
* STATE SEND_EOF
* ==============
*
***************************************
SEOF JSR CHKTRY ;check retry limit
*
* Send a Z packet to the other end
*
BIT TFSTOP ;want Z/D?
BPL SEF020 ;j if not
JSR SDCEOF ;else Z/D
JMP SEF030
SEF020 JSR STDEOF ;Ordinary
*
* Read the reply in
*
SEF030 JSR RPACK
BCC SEF040 ;j if read OK
RTS ;else stay in this state to resend
*
* Branch on packet type
*
SEF040 CMP #'N'
BEQ SEF300 ;j if N
CMP #'Y'
BEQ SEF400 ;j if Y
CMP #'E'
BEQ SEF500 ;j if E
*
* Packet type is invalid here, so abort
*
SEF050 JMP ABORT
*
*
*
* NAK received
* ------------
*
SEF300 JSR VALNAK ;can we take it as ACK?
BCC SEF400 ;j if we can
SEF320 RTS ;no, so stay in this state
*
*
* ACK received
* ------------
*
SEF400 JSR VALSEQ ;is it the expected one?
BCS SEF320 ;j if not
*
* That file is now done and closed. Are we sending a group?
*
LDA WCLEN
BEQ SEF480 ;j if name not wildcarded
*
* We're doing a group, so see if there's another to go
*
BIT TFSTOP ;had CTRL-Z to stop group?
BVS SEF480 ;j if so - do no more
JSR GNXTFIL ;else find next file
BCS SEF480 ;j if no more
JSR STOTCT ;else clear counters
LDA #'F'
BNE SEF490 ;and go to state SEND_FILE
*
* We've finished
*
SEF480 LDA #'B' ;go to state SEND_BREAK
SEF490 STA STATE
RTS
*
*
* ERROR received
* --------------
*
SEF500 JMP ERRPKT
NEXT BBCCOM
****** File BBCST1 *************************************************************
START ST1
* BBCST1 : Updated 09/05/86 @ 1730
***************************************
*
* SET
* ===
*
* Implements the SET command
*
***************************************
SET EQU *
*
* Select the table for the options and get the option parameter
*
LDX #>SETOPT ;point to table
LDY #<SETOPT
JSR GMPAS ;get parameter and validate it
JMP ACTION ;yes, so service it
SETOPT DW SETJMP ;jump table address
CMD 4,'BAUD'
CMD 6,'PARITY'
CMD 2,'TV'
CMD 4,'FILE'
CMD 4,'SEND'
CMD 7,'RECEIVE'
CMD 5,'TIMER'
CMD 5,'DELAY'
CMD 5,'PAUSE'
CMD 6,'IGNORE'
IF ROM
CMD 6,'SOURCE'
FI
CMD 11,'DESTINATION'
CMD 7,'RETRIES'
CMD 8,'MUX-WAIT'
CMD 8,'TERMINAL'
CMD 10,'LOCAL-ECHO'
CMD 9,'DEBUGGING'
CMD 9,'KEY-CLICK'
CMD 9,'TAKE-ECHO'
CMD 9,'HANDSHAKE'
CMD 10,'VDU-COLOUR'
CMD 10,'INCOMPLETE'
CMD 12,'FLOW-CONTROL'
CMD 12,'HELP-TRIGGER'
CMD 16,'EIGHT-BIT-PREFIX'
DFB 0
SETJMP DW SBAUD ;SET BAUD
DW SPARIT ;SET PARITY
DW STV ;SET TV
DW STFILE ;SET FILE
DW SSEND ;SET SEND
DW SRECV ;SET RECEIVE
DW STIMER ;SET TIMER
DW SDELAY ;SET DELAY
DW SPAUSE ;SET PAUSE
DW SIGNRE ;SET IGNORE
IF ROM
DW SSOURCE ;SET SOURCE
FI
DW SDEST ;SET DESTINATION
DW SRTRY ;SET RETRIES
DW SMUXWT ;SET MUX-WAIT
DW STERM ;SET TERMINAL
DW SLECHO ;SET LOCAL-ECHO
DW SDEBUG ;SET DEBUGGING
DW STKCLK ;SET KEY-CLICK
DW STKECH ;SET TAKE-ECHO
DW SHSHAK ;SET HANDSHAKE
DW SVDCOL ;SET VDU-COLOUR
DW SINCFD ;SET INCOMPLETE
DW SFCON ;SET FLOW-CONTROL
DW SHTRG ;SET HELP-TRIGGER
DW SEBQ ;SET EIGHT-BIT-PREFIX
***************************************
*
* SET BAUD
* ========
*
* Sets baud rate for comms line
*
***************************************
SBAUD EQU *
*
* Select the options table and get the next parameter
*
LDX #>SBATAB ;point to table
LDY #<SBATAB
JSR MPARTAB ;get parameter
*
* Look for the string in the options table
*
SEC ;no abbreviations
JSR SCANTAB
TAX
INX ;actual rate is value plus 1
STX WORK0 ;save baud rate setting
*
* Next (optional) parameter gives the direction we set for
*
LDX #>SBATB2 ;point to table
LDY #<SBATB2
JSR PARTAB ;look for parameter
BCS SBA800 ;j if defaulted
JSR SCANTAB ;else check it (C clear for abb. allowed)
JSR CONFIRM ;check no more parameters
JMP ACTION ;and handle it
*
* Here we set the RECEIVE rate
*
SBA600 LDX WORK0 ;reload value
STX RXBAUD ;note it
JMP SBA900
*
* Here we set the TRANSMIT rate
*
SBA700 LDX WORK0 ;reload value
STX TXBAUD ;note it
JMP SBA900
*
* Here we set BOTH (the default case)
*
SBA800 LDX WORK0 ;get value back
STX TXBAUD
STX RXBAUD
*
* Then reinitialise the 6850
*
SBA900 JMP SETACIA
SBATAB DW 0 ;no jump table
CMD 2,'75'
CMD 3,'150'
CMD 3,'300'
CMD 4,'1200'
CMD 4,'2400'
CMD 4,'4800'
CMD 4,'9600'
DFB 0
SBATB2 DW SBATB3 ;jump table
CMD 7,'RECEIVE'
CMD 8,'TRANSMIT'
CMD 4,'BOTH'
DFB 0
SBATB3 DW SBA600 ;RECEIVE
DW SBA700 ;TRANSMIT
DW SBA800 ;BOTH
***************************************
*
* SET TIMER
* =========
*
* Enables/disables our timeout
*
***************************************
STIMER JSR LSTMSWP ;get ON/OFF, check no more params
STA TIMER ;note the value
RTS
***************************************
*
* SET DEBUGGING
* =============
*
* Turns debugging on or off
*
***************************************
SDEBUG JSR LSTMSWP ;get ON/OFF, check no more params
STA DEBUG ;set the flag
STA DEBTOG ;and the toggle
SDB900 RTS
***************************************
*
* SET LOCAL-ECHO
* ==============
*
* Turns terminal mode local echo on or
* off
*
***************************************
SLECHO JSR LSTMSWP ;get ON/OFF, check no more params
STA ECHO ;set the flag
SEC900 RTS
***************************************
*
* SET DELAY
* =========
*
* Sets wait interval after SEND command
* before we actually do anything
*
***************************************
SDELAY EQU *
*
* Parameter is the delay in seconds
*
LDA #58 ;select help text
JSR LSTMNP ;get numeric par, check no more
STA DELAY ;save the value
RTS
***************************************
*
* SET EIGHT-BIT-PREFIX
* ====================
*
* Defines character we prefer to use for
* eight-bit prefix
*
***************************************
SEBQ EQU *
*
* Next parameter is the character we use
*
LDA #125 ;select help text
JSR LSTMCP ;get char param, check no more
*
* Check character is legal and doesn't clash with the
* quote character
*
JSR VALEBQ ;is it valid?
BCS SBQ900 ;j if not
CMP SQUOTE ;clash with quote?
BEQ SBQ920 ;j if it does
*
* Character is acceptable
*
STA CUREBQ ;save it
RTS
*
* Here character isn't a legal prefix
*
SBQ900 LDA #186 ;get error text
SBQ902 JMP PARMERR ;and report
*
* Here it clashed with the quote character
*
SBQ920 LDA #188 ;get error text
BNE SBQ902 ;and report
***************************************
*
* SET PARITY
* ==========
*
* Sets the parity used on the comms line
*
***************************************
SPARIT EQU *
*
* Parameter is the parity setting wanted
*
LDX #>SPATB1 ;point to table
LDY #<SPATB1
JSR GMPAS ;get parameter and validate it
JSR CONFIRM ;check no more params
*
* Save the setting value and note the corrseponding 6850 setting
* and inward byte mask
*
STA PARITY
TAY
SPY100 LDA SPATB2,Y
STA PARSET ;6850 setting
LDA SPATB3,Y
STA PARMSK ;inward byte mask
*
* Then put the 6850 to the new setting
*
JMP SETACIA
SPATB1 DW 0 ;no jump table
CMD 4,'MARK'
CMD 5,'SPACE'
CMD 4,'EVEN'
CMD 3,'ODD'
CMD 4,'NONE'
DFB 0
SPATB2 DFB %10010010 ;MARK -use 8 bit
DFB %10010010 ;SPACE - use 8 bit
DFB %10000010 ;EVEN - use 7 bit
DFB %10000110 ;ODD - use 7 bit
DFB %10010010 ;NONE - use 8 bit
SPATB3 DFB %01111111 ;MARK
DFB %01111111 ;SPACE
DFB %01111111 ;EVEN
DFB %01111111 ;ODD
DFB %11111111 ;NONE
***************************************
*
* SET PAUSE
* =========
*
* Sets the wait interval on packet
* turnround
*
***************************************
SPAUSE EQU *
*
* Parameter is the delay in seconds
*
LDA #60 ;select help text
JSR LSTMNP ;get numeric par, check no more
STA PAUSE ;save the value
RTS
***************************************
*
* SET FILE
* ========
*
* Entry to the SET FILE group of commands
*
***************************************
STFILE EQU *
*
* First parameter gives what we set
*
LDX #>SFTAB ;point to table
LDY #<SFTAB
JSR GMPAS ;get the parameter and validate it
JMP ACTION ;and execute it
SFTAB DW SFJMP
CMD 4,'TYPE'
CMD 4,'NAME'
IF ROM
CMD 11,'BUFFER-SIZE'
FI
CMD 7,'WARNING'
CMD 6,'SUFFIX'
DFB 0
SFJMP DW SFTYPE ;SET FILE TYPE
DW SFNAME ;SET FILE NAME
IF ROM
DW SFBUFF ;SET FILE BUFFER-SIZE
FI
DW SFWARN ;SET FILE WARNING
DW SFSUFF ;SET FILE SUFFIX
***************************************
*
* SET FILE TYPE
* =============
*
* Defines whether we treat files as
* binary or ASCII text
*
***************************************
SFTYPE EQU *
*
* Next parameter is the type required
*
LDX #>STYTAB ;point to table
LDY #<STYTAB
JSR GMPAS ;get parameter and validate it
JMP ACTION ;and execute it
STYTAB DW STYJMP
CMD 5,'ASCII'
CMD 6,'BINARY'
DFB 0
STYJMP DW SASCII ;SET FILE TYPE ASCII
DW SBIN ;SET FILE TYPE BINARY
***************************************
*
* SET FILE TYPE ASCII
* ===================
*
* Sets files to be ASCII text and defines
* how end-of-record is to be held
*
***************************************
SASCII EQU *
*
* Next parameter (optional) is the EOR type to use
*
LDX #>SASTAB
LDY #<SASTAB
JSR PARTAB ;look for parameter
BCS SAS800 ;j if absent
SEC ;no abbreviations
JSR SCANTAB ;look for it in the table
SAS100 JSR CONFIRM ;check no more params
SAS120 STA EORTYP ;note the type selected
LDX #0
STX FTYPE ;file type is ASCII
SAS300 ASL A
TAY ;get table offset
LDA SASTB2,Y
STA EOR ;note first byte in EOR sequence
LDA SASTB2+1,Y
STA EOR+1 ;...and the second
RTS ;and finish
*
* Here type is omitted, so default to LFCR
*
SAS800 LDA #0
BEQ SAS120
SASTAB DW 0 ;no jump table
CMD 4,'LFCR'
CMD 4,'CRLF'
CMD 2,'LF'
CMD 2,'CR'
DFB 0
SASTB2 DFB $0A,$0D ;LFCR
DFB $0D,$0A ;CRLF
DFB $0A,0 ;LF
DFB $0D,0 ;CR
***************************************
*
* SET FILE TYPE BINARY
* ====================
*
* Sets files to be binary
*
***************************************
SBIN JSR CONFIRM ;no more parameters
LDA #1
STA FTYPE
RTS
***************************************
*
* SET FILE NAME
* =============
*
* Sets name translation mode to be used
*
***************************************
SFNAME LDX #>SFNTAB ;point to table
LDY #<SFNTAB
JSR GMPAS ;get parameter and validate it
JSR CONFIRM ;check no more parameters
STA FNTYPE ;and save the result
RTS
SFNTAB DW 0 ;no jump table
CMD 6,'NORMAL'
CMD 12,'UNTRANSLATED'
DFB 0
IF ROM
***************************************
*
* SET FILE BUFFER-SIZE
* ====================
*
* Specifies size of the buffer area used
*
***************************************
SFBUFF LDA #103 ;select help text
JSR LSTMNP ;get num par, check no more
*
* Value must be in range 1..64
*
LDA NUM ;get value
BEQ SBF900 ;j if 0
CMP #65
BCS SBF900 ;j if > 64
STA FBPAGES ;else note it
RTS
*
* Parameter is out of range
*
SBF900 JMP SRS900
FI
***************************************
*
* SET FILE WARNING
* ================
*
* Specifies action taken if file names
* clash on receive
*
***************************************
SFWARN JSR LSTMSWP ;get ON/OFF, check no more
STA FWARN ;save the value
RTS
***************************************
*
* SET FILE SUFFIX
* ===============
*
* Defines string we add to make a remote
* filename
*
***************************************
SFSUFF EQU *
*
* Next parameter is the optional suffix string
*
LDA #114 ;select help text
JSR LSTPAR ;get param, check no more
BCS SFF800 ;j if not there
*
* Check size of the parameter
*
LDY CURLEN
CPY #9
BCS SFF900 ;j if too long
*
* Note size, and the string itself
*
STY SUFLEN ;note size
DEY
SFF200 LDA (CURPAR),Y ;else copy string over
STA SUFFIX,Y
DEY
BPL SFF200
RTS ;and finish
*
* Here parameter is null
*
SFF800 LDY #0 ;mark size as zero
STY SUFLEN
RTS
*
* Here string is too long
*
SFF900 LDA #189 ;get error text
JMP PARMERR ;and report
***************************************
*
* SET FLOW-CONTROL
* ================
*
* Selects XON/XOFF or CTS/RTS control
*
***************************************
SFCON EQU *
*
* Next parameter is the flow control type
*
LDX #>SFCTAB ;select option table
LDY #<SFCTAB
JSR GMPAS ;get parameter and validate it
JSR CONFIRM ;check it's the only one
STA FLOW ;save the new value
RTS
SFCTAB DW 0 ;no jump table
CMD 8,'XON/XOFF'
CMD 7,'CTS/RTS'
DFB 0
***************************************
*
* SET KEY-CLICK
* =============
*
* Controls whether keys click in terminal
* mode
*
***************************************
STKCLK JSR LSTMSWP ;get ON/OFF, check no more
STA CLICK ;and save the value
RTS
***************************************
*
* SET MUX-WAIT
* ============
*
* Defines delay before testing CTS when
* talking to a slow MUX system
*
***************************************
SMUXWT EQU *
*
* Next parameter is time in byte periods
*
LDA #21 ;select help text
JSR LSTMNP ;get num par, check no more
STA MUXWT ;and save the value
RTS
***************************************
*
* SET HELP-TRIGGER
* ================
*
* Changes command line character that
* triggers autohelp output
*
***************************************
SHTRG EQU *
*
* Next param is mandatory, and is the character
*
LDX #>SHTTB ;point to table
LDY #<SHTTB
JSR GMPAS ;get parameter and validate it
LDY #0
LDA (CURPAR),Y ;get the actual character
JSR CONFIRM ;check no more parameters
STA HLPTRG ;save the new value
RTS ;and finish
SHTTB DW 0 ;no jump table
CMD 1,'?'
CMD 1,'&'
CMD 1,'/'
CMD 1,'#'
CMD 1,'@'
DFB 0
CHN BBCST2
****** File BBCST2 *************************************************************
START ST2
* BBCST2: Updated 09/05/86 @ 1730
***************************************
*
* SET TERMINAL
* ============
*
* Selects terminal type
*
***************************************
STERM LDX #>STTAB ;point to table
LDY #<STTAB
JSR GMPAS ;get parameter and validae it
JSR CONFIRM ;check no more parameters
STA TTYPE ;and note the new type
RTS
STTAB DW 0 ;no jump table
CMD 4,'TT40' ;the first 5 entries must not be moved
CMD 4,'TT80' ;or changed as the numbers and types are known
CMD 4,'VT52' ;to TXRs
CMD 5,'VT100'
CMD 3,'TEK'
CMD 1,'A' ;change these names if you wish
CMD 1,'B'
DFB 0
***************************************
*
* SET VDU-COLOUR
* ==============
*
* Selects text colour for 80 column VDU
* or 80 column command mode screens
*
***************************************
SVDCOL EQU *
IF RAM
JSR CKSHAD ;BRK if no shadow RAM
FI
*
* Next parameter is the colour
*
LDX #>SVDCTB ;point to table
LDY #<SVDCTB
JSR GMPAS ;get parameter and validate it
JSR CONFIRM ;check no more
*
* Value is OK. Colour we store is table value plus 1 (since we
* don't allow colour 0 which is BLACK)
*
TAX
INX
STX VDUCOL
*
* We might be an 80 column command screen, so change colour now in case
*
JMP SMD200
SVDCTB DW 0 ;no jump table
CMD 3,'RED'
CMD 5,'GREEN'
CMD 6,'YELLOW'
CMD 4,'BLUE'
CMD 7,'MAGENTA'
CMD 4,'CYAN'
CMD 5,'WHITE'
DFB 0
IF ROM
***************************************
*
* SET SOURCE
* ==========
*
* Sets source of data we transmit
*
***************************************
SSOURCE EQU *
*
* Next parameter specifies the source
*
LDX #>SSRTAB ;point to table
LDY #<SSRTAB
JSR GMPAS ;get the parameter and validate it
JMP ACTION ;action it if it is
SSRTAB DW SSRJMP
CMD 4,'FILE'
CMD 6,'MEMORY'
DFB 0
SSRJMP DW SSFILE ;SET SOURCE FILE
DW SSMEM ;SET SOURCE MEMORY
FI
IF ROM
***************************************
*
* SET SOURCE FILE
* ===============
*
* Sets data source for transmit to be
* the filestore
*
***************************************
SSFILE JSR CONFIRM ;check no more params
LDA #0
STA SOURCE
RTS
FI
IF ROM
***************************************
*
* SET SOURCE MEMORY
* =================
*
* Sets data source to main memory
*
***************************************
SSMEM EQU *
*
* Next param is start address in hex
*
LDA #102 ;select help text
JSR GETMPAR ;get parameter
JSR HEXPAR ;convert to binary
LDA NUM
STA MSBASE ;and note it
LDA NUM+1
STA MSBASE+1
*
* Then comes the address of last byte + 1
*
JSR MPARAM ;is it there?
JSR HEXPAR ;yes, so convert it
JSR CONFIRM ;make sure no more params
LDA NUM ;note the value
STA MSTOP
LDA NUM+1
STA MSTOP+1
*
* Note source is MEMORY
*
LDA #1
STA SOURCE
RTS
FI
***************************************
*
* SET DESTINATION
* ===============
*
* Sets destination of data we receive
*
***************************************
SDEST EQU *
*
* Next parameter specifies the source
*
LDX #>SDETAB ;point to table
LDY #<SDETAB
JSR GMPAS ;get parameter and validate it
JMP ACTION ;action it if it is
SDETAB DW SDEJMP
CMD 4,'FILE'
IF ROM
CMD 6,'MEMORY'
FI
CMD 7,'PRINTER'
DFB 0
SDEJMP DW SDFILE ;SET DESTINATION FILE
IF ROM
DW SDMEM ;SET DESTINATION MEMORY
FI
DW SDPRT ;SET DESTINATION PRINTER
***************************************
*
* SET DESTINATION FILE
* ====================
*
* Sets destination for received data to
* be the filestore
*
***************************************
SDFILE JSR CONFIRM ;check no more params
LDA #0
SDF200 STA DESTIN
RTS
***************************************
*
* SET DESTINATION PRINTER
* =======================
*
* Routes data direct to parallel printer
*
***************************************
SDPRT JSR CONFIRM ;check no more parameters
LDA #2 ;and set flag
BNE SDF200
IF ROM
***************************************
*
* SET DESTINATION MEMORY
* ======================
*
* Sets data destination to memory starting
* at the specified address
*
***************************************
SDMEM EQU *
*
* next parameter is start address in hex
*
LDA #102 ;set help text
JSR GETMPAR ;get the parameter
JSR HEXPAR ;yes, so convert to hex
JSR CONFIRM ;check no more params
*
* Set up start of buffer address
*
LDA NUM
STA MDBASE
LDA NUM+1
STA MDBASE+1
*
* Set top of buffer to the base of a MODE 7 screen
*
LDX #$7C
STX MDTOP+1
LDX #0
STX MDTOP
*
* Mark destination as MEMORY
*
INX
STX DESTIN
RTS
FI
***************************************
*
* SET SEND
* ========
*
* Sets parameters affecting sending
*
***************************************
SSEND EQU *
*
* Next parameter is the option to set
*
LDX #>SSNTAB ;point to table
LDY #<SSNTAB
JSR GMPAS ;get parameter and validate it
JMP ACTION ;and do it
SSNTAB DW SSNJMP
CMD 15,'START-OF-PACKET'
CMD 7,'PADCHAR'
CMD 7,'PADDING'
CMD 7,'TIMEOUT'
CMD 5,'QUOTE'
CMD 11,'END-OF-LINE'
DFB 0
SSNJMP DW SSSOP ;SET SEND START-OF-PACKET
DW SSPADC ;SET SEND PADCHAR
DW SSNPAD ;SET SEND PADDING
DW SSTIME ;SET SEND TIMEOUT
DW SSQUOTE ;SET SEND QUOTE
DW SSEOL ;SET SEND END-OF-LINE
***************************************
*
* SET SEND START-OF-PACKET
* ========================
*
* Defines value we send as start of
* packet flag
*
***************************************
SSSOP LDA #93 ;select help text
JSR LSTMNP ;get num par, check no more
CMP #$20
BCS SSS900 ;j if > $1F
STA SSOP ;else note it
RTS
*
* Here parameter is out of range
*
SSS900 JMP SRP900
***************************************
*
* SET SEND TIMEOUT
* ================
*
* Defines timeout we ask remote to use
*
***************************************
SSTIME LDA #101 ;select help text
JSR LSTMNP ;get num par, check no more
CMP #95
BCS SSS900 ;j if not 0..94
STA STIME ;else set it
RTS
***************************************
*
* SET SEND PADCHAR
* ================
*
* Defines the pad character we send
* initially
*
***************************************
SSPADC LDA #94 ;select help text
JSR LSTMNP ;get num par, check no more
CMP #32
BCS SSS900 ;j if not 0-31
STA SPADC ;else save it
RTS
***************************************
*
* SET SEND PADDING
* ================
*
* Defines number of pads we send initially
*
***************************************
SSNPAD LDA #95 ;select help text
JSR LSTMNP ;get num par, check no more
STA SNPAD ;note it
RTS
***************************************
*
* SET SEND QUOTE
* ==============
*
* Defines how we quote control characters
*
***************************************
SSQUOTE LDA #73 ;select help text
JSR LSTMCP ;get char par, check no more
*
* Check character doesn't clash with the 8 bit prefix
*
CMP CUREBQ
BEQ SSQ900 ;j if it does
STA SQUOTE ;else save the value
RTS
*
* Here character clashes with the 8 bit prefix
*
SSQ900 LDA #192 ;select error text
JMP PARMERR ;and report
***************************************
*
* SET SEND END-OF-LINE
* ====================
*
* Defines EOLN we use initially
*
***************************************
SSEOL LDA #124 ;set help text
JSR LSTMNP ;get num par, check no more
CMP #$20
BCS SSE900 ;j if not 0..31
STA SEOLN ;else note new value
RTS
SSE900 JMP SRS900
***************************************
*
* SET RECEIVE
* ===========
*
* Sets parameters affecting reception
*
***************************************
SRECV EQU *
*
* Next parameter is the option to set
*
LDX #>SRCTAB ;point to table
LDY #<SRCTAB
JSR GMPAS ;get parameter and validate it
JMP ACTION ;and do it
SRCTAB DW SRCJMP
CMD 15,'START-OF-PACKET'
CMD 7,'PADCHAR'
CMD 7,'PADDING'
CMD 7,'TIMEOUT'
CMD 13,'PACKET-LENGTH'
CMD 11,'END-OF-LINE'
DFB 0
SRCJMP DW SRSOP ;SET RECEIVE START-OF-PACKET
DW SRPADC ;SET RECEIVE PADCHAR
DW SRNPAD ;SET RECEIVE PADDING
DW SRTIME ;SET RECEIVE TIMEOUT
DW SRPLEN ;SET RECEIVE PACKET-LENGTH
DW SREOL ;SET RECEIVE END-OF-LINE
***************************************
*
* SET RECEIVE START-OF-PACKET
* ===========================
*
* Defines value we receive as start of
* packet flag
*
***************************************
SRSOP LDA #98 ;select help text
JSR LSTMNP ;get num par, check no more
CMP #$20
BCS SRS900 ;j if > $1F
STA RSOP ;else note it
RTS
*
* Here parameter is out of range
*
SRS900 LDA #194 ;get error text
JMP PARMERR ;and report
***************************************
*
* SET RECEIVE TIMEOUT
* ===================
*
* Defines timeout we use on remote
* sending to us if TIMER is on
*
***************************************
SRTIME LDA #92 ;select help text
JSR LSTMNP ;get num par, check no more
STA RTIME ;and set the value
RTS
***************************************
*
* SET RECEIVE PADCHAR
* ===================
*
* Defines the pad character we ask
* other side to send
*
***************************************
SRPADC LDA #99 ;select help text
JSR LSTMNP ;get num par, check no more
CMP #32
BCS SRS900 ;j if not 0-31
STA RPADC ;else save it
RTS
***************************************
*
* SET RECEIVE PADDING
* ===================
*
* Defines number of pads we ask other
* side to send
*
***************************************
SRNPAD LDA #100 ;select help text
JSR LSTMNP ;get num par, check no more
CMP #95
BCS SRS900 ;j if not 0..94
STA RNPAD ;else note it
RTS
***************************************
*
* SET RECEIVE PACKET-LENGTH
* =========================
*
* Sets value we ask other end to use as
* maximum packet length
*
****************************************
SRPLEN LDA #122 ;select help text
JSR LSTMNP ;get num par, check no more
CMP #95
BCS SRP900 ;j if too big
CMP #35
BCC SRP900 ;j if too small
STA RMAXL ;else note the value
RTS
*
* Here value is out of range
*
SRP900 JMP SRS900
***************************************
*
* SET RECEIVE END-OF-LINE
* =======================
*
* Defines value we ask other end to use
* as end-of-line
*
***************************************
SREOL LDA #123 ;select help text
JSR LSTMNP ;get num par, check no more
CMP #$20 ;is value > 31?
BCS SRP900 ;j if not
STA REOLN ;else note it
RTS
****************************************
*
* SET INCOMPLETE
* ==============
*
* Specifies fate of incomplete received
* files
*
***************************************
SINCFD EQU *
*
* Next parameter is the action to take
*
LDX #>SITAB ;select option table
LDY #<SITAB
JSR GMPAS ;get parameter and validate it
JSR CONFIRM ;check no more params
STA FINCOM ;and save the value
RTS
SITAB DW 0 ;no jump table
CMD 6,'DELETE'
CMD 4,'KEEP'
DFB 0
***************************************
*
* SET TAKE-ECHO
* =============
*
* Controls whether TAKE file input is
* echoed to the screen or not
*
***************************************
STKECH JSR LSTMSWP ;get ON/OFF, check no more params
STA TKECHO ;note the value
RTS
***************************************
*
* SET TV
* ======
*
* Selects/deselects auto *TV on entering
* terminal mode
*
***************************************
STV EQU *
*
* Next parameter is optioanl, and is the first *TV param
*
LDA #143 ;select help text
JSR GETPAR ;get parameter
BCS STV800 ;j if no param - turn facility off then
JSR NUMPAR ;else convert to binary
PHA ;and save for a bit
*
* Next is the second *TV parameter, which is mandatory now
*
LDA #143 ;select help text
JSR LSTMNP ;get num par, check no more
*
* Now save values in table and note we're to do a *TV
*
STA TVPAR2 ;save param 2
PLA
STA TVPAR1 ;save param 1
LDA #1
STV700 STA TVFLAG ;note we do it
RTS
*
* Here there were no parameters, so turn the facility off
*
STV800 LDA #0
BEQ STV700
***************************************
*
* SET IGNORE
* ==========
*
* Defines the incoming byte ignored in
* terminal mode
*
***************************************
SIGNRE EQU *
*
* Next parameter is optional, and is the byte to ignore
*
LDA #141 ;select help text
JSR GETPAR ;get parameter
BCS SGN400 ;j if not there - turn facility off
*
* Param is there, so note it
*
JSR NUMPAR ;convert to binary
JSR CONFIRM ;check no more parameters
STA IGNCHR ;note character
LDA #$01
SGN300 STA IGNFLG ;note facility is on
RTS
*
* Here there's no parameter, so turn the facility off
*
SGN400 LDA #0
BEQ SGN300
***************************************
*
* SET RETRIES
* ===========
*
* Sets max no of packet retransmissions
* allowed
*
***************************************
SRTRY EQU *
*
* Next parameter is a number, 1..255
*
LDA #150 ;select help text
JSR LSTMNP ;get num par, check no more
CMP #0
BEQ SRT900 ;j if value is 0
STA MAXTRY ;else note it
RTS
*
* Here value is out of range
*
SRT900 JMP SRP900
***************************************
*
* SET HANDSHAKE
* =============
*
* Sets the turnround character for some
* IBM systems
*
***************************************
SHSHAK EQU *
*
* Parameter is the handshake type
*
LDX #>SKTAB ;point to table
LDY #<SKTAB
JSR GMPAS ;get parameter and validate it
JSR CONFIRM ;make sure no more parameters
STA HSHAKE ;and note the handshake type
RTS
SKTAB DW 0 ;no jump table
CMD 4,'NONE'
CMD 4,'BELL'
CMD 2,'CR'
CMD 2,'LF'
CMD 3,'XON'
CMD 4,'XOFF'
DFB 0
SKTAB2 DFB 0,$07,$0D,$0A,XON,XOFF
CHN BBCSHW
****** File BBCTM1 *************************************************************
START TM1
* BBCTM1: Updated 10/01/87 @ 1730
***************************************
*
* TERMINAL EMULATION
* ==================
*
* This provides 40 byte and 80 byte
* teletype modes, and VT52 mode.
*
***************************************
CONNECT EQU *
*
* Check there are no more command line parameters
*
JSR CONFIRM
*
* Do we support the selected terminal type in this program image?
*
LDA TTYPE ;get the type code
CMP #3
BCS CON040 ;j if not type 0..2
*
* Type is 0..2, so we handle terminal ourselves
*
IF ROM
*
* ROM version always supports 0..2
*
BCC CON070 ;all of 0..2 OK in ROM version
ELSE
*
* RAM version needs B+ or Master for 1 or 2
*
CMP #0
BEQ CON070 ;j if type 0 (TT40) - always OK
BIT SHADOW ;else we need shadow RAM
BMI CON070 ;j if we've got it
BPL CON060 ;else error
FI
*
* Type is not 0..2, so we need help from a TXR. We'll pass the job
* over and see if one picks it up
*
CON040 LDX #$82
JSR DOKOSB ;ask TXR to take over
BVS CON060 ;j if it didn't want to or wasn't there
RTS ;else all done
*
* No TXR fitted and we don't do this type ourselves, so error
*
CON060 BRK
DFB 0
ASC 'Terminal not supported'
DFB 0
*
* Type is supported here, so note we're providing the terminal mode
*
CON070 LDX #0
STX TXRACT ;TXR not active
*
* Set cursor keys as function keys or edit keys
*
LSR A
ASL A ;0=TT40 or TT80, 2=VT52
TAX
STA EDCRSR ;note as cursor state flag
LDA #4 ;set cursor keys so they are
JSR OBX0 ;function for VT52, edit for other
*
* Make function keys return codes
*
LDX #>CONTB1 ;point table of base values
LDY #<CONTB1
JSR SETKEY ;and set them up
LDX #245 ;set Master keypad to give distinct code
JSR SETPAD
*
* Do we need to define graphics characters 128-159 and set things to
* handle VT52 graphics?
*
LDA TTYPE ;get terminal type
CMP #2
BNE CON120 ;j if not VT52
*
* Yes we do. Define characters by VDU 23 - block copy to
* $C00 won't work on Master128
*
LDY #0
STY GRMODE ;clear graphics mode flag first
LDA #128
STA WORK0 ;start character code value
CON080 LDA #23
JSR OSWRCH ;VDU 23...
LDA WORK0
JSR OSWRCH ;..then character value
LDX #8 ;start count for 8 bytes of definition
CON085 LDA GRCHAR,Y ;get byte from definition
JSR OSWRCH ;add to VDU 23
INY ;step to next byte in block
BEQ CON130 ;j if totally finished
DEX
BNE CON085 ;j if this character not finished
INC WORK0 ;step character value on
BNE CON080 ;j always
*
* If we're a 40 column screen we go to mode 7
*
CON120 LDA TTYPE ;get terminal type
BNE CON130 ;j if 80 column
LDA #211
JSR MESS ;else set up MODE 7 screen
JMP CON150 ;and set up terminal
*
* Here we're going into MODE 3.
*
CON130 JSR STMDE3 ;into MODE 3 (with *TV if needed)
LDA #135
JSR MESS ;output the status line
*
* Now we need to snapshot the status line for the first
* time, so set up the pointer to where this goes
*
LDA #&84
JSR OSBYTE ;read bottom of display RAM
STX STCOPY ;lsb is OK as it
TYA
SEC
SBC #4
STA STCOPY+1 ;but lower msb by 4 pages
JSR SNAPSL ;then snapshot it
*
* Now note we're in terminal mode
*
CON150 LDA #1
STA MODE ;and note we're a terminal now
*
* Note stack and address for a restart
*
TSX
STX STKRST
LDA #>CON800
STA RESTART
LDA #<CON800
STA RESTART+1
*
* Set initial state to printer off, logging off, and noscroll clear
*
CON180 LDA #0
STA SCROLL ;clear noscroll
STA PRINTER ;clear printer flag
STA LOGON ;clear logging flag
JSR PRTOFF ;ensure printer is off...
JSR HOSTON ;..and host is on
*
* Initialise LF suppress flag and line counts
*
JSR VDUINI
*
* And set up the standard character disposition vector to handle incoming bytes
*
JSR INICDV
*
* Now the terminal loop. Is anything happening?
*
JSR FLSHKB ;flush keyboard buffer first time in
CON200 JSR RXBYTE ;look at comms and keyboard
BCC CON230 ;j if from host
JMP CON400 ;else it's keyboard
*
* Byte is in from the host. Do we ignore it?
*
CON230 AND #%01111111 ;remove B7 from received byte
LDY IGNFLG ;look at the ignore flag
BEQ CON280 ;j if no ignore char defined
CMP IGNCHR ;else check this character
BEQ CON200 ;j if we do ignore it
*
* Log byte to file if necessary
*
CON280 JSR TXE500
*
* And go to where the character disposition vector points
*
CON300 JSR CON310
JMP CON200 ;and round again
CON310 JMP (CHARIN)
*
* Had a keypress. Shall we click discretely?
*
CON400 PHA ;save the key
LDA CLICK ;get click flag
BEQ CON420 ;j if not wanted
LDA #7
LDX #>CLKBLK
LDY #<CLKBLK
JSR OSWORD ;else click
CON420 PLA ;restore key code
*
* Now check to see if code is from the Master keypad
*
CMP #$D2
BCS CON460 ;j if so
*
* Is it a CONTROL-F key then?
*
CMP #CFKEY
BCC CON450 ;j if not
CMP #CFKEY+10
BCS CON450 ;j if not
SEC
SBC #CFKEY ;else scale to 0..9
LDX #>CFJTAB ; point to jump table
STX JMPTBL
LDX #<CFJTAB
STX JMPTBL+1
JSR ACTION ;handle the key
JMP CON200 ;and round for the next
*
* Not a CONTROL-F key, so check for F and SHIFT-F and CURSOR
*
CON450 CMP #FKEY
BCC CON600 ;j if not
*
* It's either cursor key, F key, SHIFT-F key or keypad key
*
CON460 LDX TTYPE ;are we a VT52?
CPX #2
BNE CON465 ;j if not - ignore the key
JSR CFSF ;else action it
CON465 JMP CON200
*
* Here we're ready to send the byte to the host and maybe
* echo and log it
*
CON600 LDX TXHAND ;are we using a TRANSMIT file?
BNE CON650 ;j if we are
JSR TXECHO ;else simply send the byte
CON630 JMP CON200 ;and round again
*
* Here the byte is from a TRANSMIT file, so we have to look at what it is
*
CON650 CMP #$0A
BNE CON670 ;j if not LF
*
* It's an LF from a TRANSMIT file - maybe we ignore this one
*
LDX FTYPE ;otherwise, are we file type ASCII?
BNE CON670 ;j if not
LDX EORTYP ;else are we ASCII CR?
CPX #3
BEQ CON630 ;j if we are - we ignore the LF
*
* We're OK to send the TRANSMIT file byte here
*
CON670 PHA ;save it for a bit
JSR TXECHO ;send it
PLA ;and get it back
*
* If we just sent a CR, pause for the host to catch up
*
CMP #$0D
BNE CON630 ;j if not CR
JSR TIMBRK ;else wait about half a second
JSR TIMBRK
BEQ CON630 ;then carry on
*
* We come here after a BRK restart. Are we providing the terminal
* emulation ourselves?
*
CON800 BIT TXRACT
BMI CON810 ;j if TXR is doing it
JMP CON180 ;else restart ourselves
*
* Here a TXR is doing the terminal emulation, so restart him
*
CON810 LDX #$83
JMP DOKOSB
CLKBLK DW &11 ;click on channel 1 with flush
DW -8 ;amplitude -8
DW 20 ;pitch 20
DW 1 ;duration 1
CONTB1 DFB FKEY,SFKEY,CFKEY,1 ;function key base values
***************************************
*
* STDCHR
* ======
*
* Handles an incoming (or local echoed)
* character that isn't in an ESCAPE
* sequence
*
***************************************
STDCHR CMP #$1B ;is the character ESCAPE?
BNE SCR500 ;j if not
LDY TTYPE ;else get terminal type
CPY #2
BNE SCR500 ;we're not VT52, so ignore ESCAPE
LDA #>ESC100 ;set up address of handler for next time
STA CHARIN
LDA #<ESC100
STA CHARIN+1
RTS
*
* Not an ESCAPE, so echo to the screen
*
SCR500 JMP ECHOCH
***************************************
*
* TXECHO
* ======
*
* Transmits byte to host, maybe with
* echo and log
*
***************************************
TXECHO JSR TXBYTE ;send the byte to host
LDX ECHO
BEQ TXE900 ;j if not in local echo mode
PHA ;else save the byte
JSR CON310 ;put it through std character handler for echo
PLA ;reload the byte
TXE500 BIT LOGON ;is logging to disc on?
BPL TXE900 ;j if not
JMP TOLOG ;else log the byte as well
TXE900 RTS
***************************************
*
* ECHOCH
* ======
*
* Echoes character to the terminal screen
*
***************************************
ECHOCH CMP #$0A
BNE ECH500 ;j if not LF
*
* It is LF. Don't display if suppression flag set
*
JSR LFOUT ;output it if we need to
BCS ECH200 ;j if output was suppressed
JMP RFSHSL ;refresh status line
*
* LF was suppressed on screen, so if printer is on we send
* it to there alone
*
ECH200 BIT PRINTER ;printer on?
BPL ECH510 ;j if not
LDA #1
JSR OSWRCH ;else VDU 1
LDA #$0A
ECH450 JMP OSWRCH ;and the LF
*
* Not an LF. Look for DEL, BEL, BS, CR, FF and TAB now
*
ECH500 CMP #$7F
BEQ ECH520 ;j if DEL
CMP #$07
BEQ ECH450 ;j if BEL
CMP #$08
BEQ ECH520 ;j if BS
CMP #$0C
BEQ ECH560 ;j if FF
CMP #$0D
BEQ ECH540 ;j if CR
CMP #$09
BEQ ECH800 ;j if TAB
*
* Any other control characters are ignored
*
CMP #32
BCS ECH600 ;j if not contol char
ECH510 RTS
*
* Here character is DEL or BS
*
ECH520 JMP DELOUT
*
* Here character is CR
*
ECH540 JMP CROUT
*
* Here it's FF, so clear the screen
*
ECH560 LDX TTYPE ;get terminal type
BNE ECH580 ;j if 80 bytes wide
JMP FFOUT ;for 40 byte terminal simply write $0C
*
* For 80 byte terminal we do it in a window
*
ECH580 LDA #48
JSR MESS ;set window and clear
JMP VDUINI ;reset VDU counters
*
* Do we need to transform character into a VT52 graphics character?
*
ECH600 BIT GRMODE ;in VT52 graphics mode?
BPL ECH700 ;j if not
CMP #95 ;else check fro graphics character
BCC ECH700 ;j if not graphics
CMP #128
BCS ECH700 ;j if not graphics
ADC #33 ;else scale char to 128..159
*
* Character is now ready for output
*
ECH700 JSR CHROUT ;output it
BEQ ECH790 ;j if not last on line
ECH750 JSR RFSHSL ;else refresh status line
ECH790 RTS
*
* Here character was TAB
*
ECH800 JSR TABOUT ;handle it
BCS ECH750 ;j if new line was started
RTS
***************************************
*
* TOLOG
* =====
*
* Writes byte to terminal log file
*
***************************************
TOLOG EQU *
*
* Put byte into buffer and see if it's full
*
PHA ;save the byte
LDY LOGCNT
STA LOGBUF,Y ;store byte
INC LOGCNT ;move pointer
BNE TLG900 ;j if buffer not full
*
* Disc write needed, so ensure host is stopped
*
LDA IOSTOP ;stopped already?
STA WORK6 ;note this
BNE TLG200 ;j if stopped
JSR HOSTOFF ;else stop him
*
* Now delay to let bytes in transit trickle through
*
TLG200 LDX #3 ;3 byte period delay
LDY RXBAUD ;at receive baud rate
JSR BYTEWT
*
* We should be safe to write the disc now without missing any
* bytes in due to NMI
*
LDA #0 ;byte count is 256 (=0)
JSR WLOGB ;write buffer to disc
*
* Restore host to the state it was in on entry now
*
LDA WORK6 ;get entry state
BNE TLG900 ;j if he was stopped
JSR HOSTON ;else start him
TLG900 PLA ;restore the byte we logged
RTS
***************************************
*
* RSTLIN
* ======
*
* Resets the count of characters on a
* line
*
***************************************
RSTLIN LDA MODE
BEQ RSL500 ;j if command mode
*
* We're in terminal mode, so use the terminal width value
*
LDY TTYPE
LDA RSLTBL,Y ;get size of line
RSL100 STA VDUCNT ;save character count
SEC
SBC #7
STA TABEND ;save last tab position
RTS
*
* Here we're in command mode
*
RSL500 LDA CSCRLN
BNE RSL100
RSLTBL DFB 39,79,79
***************************************
*
* INICDV
* ======
*
* Sets up the default character
* disposition vector
*
***************************************
INICDV LDA #>STDCHR
STA CHARIN
LDA #<STDCHR
STA CHARIN+1
RTS
***************************************
*
* TABOUT
* ======
*
* Outputs a TAB character
*
***************************************
TABOUT JSR LOCATE ;where are qe?
CPY TABEND
BCC DOT300 ;j if room to tab on this line
JSR OSNEWL ;else atart new line
SEC
RTS
*
* Room to tab, so output spaces to next tab stop
*
DOT300 TXA
AND #%00000111
EOR #%00000111
TAX ;spaces needed less 1
LDA #' '
DOT350 JSR OSWRCH ;print a space
DEC VDUCNT ;count it
DEX
BPL DOT350
*
* No new line started, so ensure LF suppression is off
*
JSR NOLFSP
CLC
RTS
***************************************
*
* NOLFSP
* ======
*
* Turns LF suppression flag off
*
***************************************
NOLFSP LDA #0
NSP100 STA LFSUPP
RTS
***************************************
*
* LFOUT
* =====
*
* Outputs an LF character
*
***************************************
LFOUT BIT LFSUPP ;is LF suppressed?
BMI LFT800 ;j if so
JSR OSWRCH ;else print the LF
CLC
RTS
LFT800 JSR NOLFSP ;suppression was on, so clear it
SEC
RTS
***************************************
*
* CHROUT
* ======
*
* Outputs a non-control character
*
***************************************
CHROUT JSR OSWRCH ;print the character
DEC VDUCNT ;count it
BPL NOLFSP ;j if it wasn't last on line
*
* BBC has done a CR-LF for us at end-of-line, so we suppress the
* next LF
*
JSR RSTLIN ;reset character count
LDA #$FF
BNE NSP100 ;set LF suppression flag
***************************************
*
* DELOUT
* ======
*
* Outputs a BS or DEL
*
***************************************
DELOUT JSR OSWRCH
INC VDUCNT
RTS
***************************************
*
* CROUT
* =====
*
* Outputs a CR byte
*
***************************************
CROUT JSR OSWRCH
JMP RSTLIN
***************************************
*
* FFOUT
* =====
*
* Outputs a FF byte
*
***************************************
FFOUT JSR OSWRCH ;write the $0C
JMP VDUINI ;reset VDU controls
***************************************
*
* VDUINI
* ======
*
* Initialises counts and LF suppression
* flag
*
***************************************
VDUINI JSR RSTLIN
JMP NOLFSP
NEXT BBCTM2
****** File BBCTM2 *************************************************************
START TM2
* BBCTM2: Updated 13/05/86 @ 2000
***************************************
*
* SNAPSL
* ======
*
* Copies the status line to our own
* RAM area
*
***************************************
SNAPSL JSR FNDTOP ;find address of top screen line
STX RSCPTR ;save as source pointer
STY RSCPTR+1
LDA STCOPY ;and set address of our copy area
STA PTR1 ;as destination
LDA STCOPY+1
STA PTR1+1
*
* Now move 640 bytes from screen to our copy area
*
LDA #5 ;start counts
STA WORK0
SPS200 LDA #128
STA WORK1
*
* Pick up and copy next byte
*
SPS220 BIT SHADOW ;do we have a shadow screen?
BPL SPS500 ;j if not
JSR OSRDSC ;else call OS to do it
LDY #0
SPS230 STA (PTR1),Y ;and save it
*
* Step the destination pointer
*
INC PTR1
BNE SPS300
INC PTR1+1
*
* Step source pointe, handling the wrap at the end of the screen RAM area (note that
* even in shadow mode, a MODE 3 screen runs from $4000 to $7FFF - hardware maps
* this to the right place
*
SPS300 INC RSCPTR ;step lsb
BNE SPS400
INC RSCPTR+1 ;step msb
BPL SPS400 ;j if not reached $8000
LDA RSCPTR+1 ;else subtract $4000 from address
SEC
SBC #$40
STA RSCPTR+1
*
* Any more to do?
*
SPS400 DEC WORK1
BNE SPS220 ;j if so
DEC WORK0
BNE SPS200 ;j if so
RTS ;else finish
*
* Here we're ot in shadow mode, so get byte by hand
*
SPS500 LDY #0
LDA (RSCPTR),Y
JMP SPS230
***************************************
*
* RFSHSL
* ======
*
* Rewrites the status line to screen line
* zero
*
***************************************
RFSHSL LDA TTYPE ;get terminal type
BEQ RFS900 ;j if 40 byte screen - null call
JSR FNDTOP ;X,Y point screen top line
STX WSCPTR ;save as destination for move
STY WSCPTR+1
LDA STCOPY ;set to move line from our copy area
STA PTR0
LDA STCOPY+1
STA PTR0+1
*
* Now move the data in 5 128-byte lumps (each lump is 16 display
* characters) as this minimises the times we check wrapround
*
LDX #5
RFS200 LDY #127
*
* Move next 16 display characters
*
RFS210 LDA (PTR0),Y ;get byte from copy area
BIT SHADOW ;are we in shadow mode?
BPL RFS250 ;j if not
JSR OSWRSC ;else let OS do it
JMP RFS280
*
* Not shadow mode, so we write byte by hand
*
RFS250 STA (WSCPTR),Y
RFS280 DEY
BPL RFS210
*
* Increment source address
*
LDA PTR0
CLC
ADC #128
STA PTR0
BCC RFS300
INC PTR0+1
*
* Increment destination, checking we don't fall off into the ROM area above $8000
*
RFS300 LDA WSCPTR
CLC
ADC #128
STA WSCPTR
BCC RFS380
INC WSCPTR+1
RFS350 BPL RFS380 ;j if no wrap needed
LDA WSCPTR+1
SBC #$40 ;else move back into RAM (C set here)
STA WSCPTR+1
*
* And carry on till 80 display characters have gone
*
RFS380 DEX
BNE RFS200
RFS900 RTS ;and that's it
***************************************
*
* CONTROL-FUNCTION KEY HANDLERS
* =============================
*
* CF keys in terminal mode are handled here
*
***************************************
CFJTAB DW CF0 ;CF0 - return to command mode
DW CF1 ;CF1 - disc toggle
DW CF2 ;CF2 - printer toggle
DW CF3 ;CF3 - scroll/noscroll
DW CF4 ;CF4 - cursor mode
DW NULLCF ;CF5
DW NULLCF ;CF6
DW NULLCF ;CF7
DW LNGBRK ;CF8 - long break
DW SHTBRK ;CF9 - short break level
***************************************
*
* CF0
* ---
*
* Return to command mode
*
***************************************
CF0 PLA ;lose link to this routine
PLA
RTS
***************************************
*
* CF1
* ===
*
* Toggle disc logging
*
***************************************
CF1 LDA LHAND ;is log file open?
BEQ CF1900 ;j if not
LDA LOGON
EOR #$FF
STA LOGON ;else toggle flag
TAY
INY ;form 0 or 1 from toggle
LDA CF1TAB,Y ;get letter for status line
LDX #76 ;column to use is 76
*
* Now update the status line
*
CF1400 PHA ;save the output letter
TXA ;get column number into A
PHA ;save it
JSR PRTOFF ;ensure printer is off
PLA ;reload column number
LDY TTYPE ;are we 80 byte terminal?
BNE CF1420 ;j if we are
*
* We're a 40 byte terminal here, so poke character to screen
*
SEC ;move column back 40 bytes
SBC #40
TAX
PLA ;get character back
STA $7C00,X ;poke to screen
BNE CF1700
*
* Here we're 80 bytes wide
*
CF1420 PHA ;save the column
JSR LOCATE ;find where cursor is
LDA #31
JSR OSWRCH ;start VDU 31
PLA
JSR OSWRCH ;select column
LDA #0
JSR OSWRCH ;in BBC line 0
LDA #136
JSR MESS ;go to inverse video
PLA ;get the letter we use
JSR OSWRCH ;and write it
LDA #137
JSR MESS ;and back to normal video
JSR REPOSN ;then put cursor back where it was
CF1700 BIT PRINTER ;should printer be on?
BPL CF1800 ;j if not
JSR PRTON ;else turn it back on
*
* Now snapshot the updated status line if needed
*
CF1800 EQU *
LDA TTYPE ;get terminal type
BEQ CF1900 ;j if 40 byte terminal
JSR SNAPSL ;else do the snapshot
NULLCF EQU *
CF1900 RTS
CF1TAB ASC 'D '
***************************************
*
* CF2
* ===
*
* Toggle printer logging
*
***************************************
CF2 LDA PRINTER ;toggle the flag
EOR #$FF
STA PRINTER
TAY
INY ;form 0 or 1 from toggle
LDA CF2TAB,Y ;get letter for status line
LDX #77 ;column is 77
BNE CF1400
CF2TAB ASC 'P '
***************************************
*
* CF3
* ===
*
* Scroll/noscroll toggle
*
***************************************
CF3 LDA SCROLL ;toggle the setting
EOR #$FF
STA SCROLL
BEQ CF3300 ;j if now SCROLL
JSR HOSTOFF ;else we stop host
LDA #'H' ;letter in status line is "H"
BNE CF3600
*
* Here we're now in SCROLL state, so start the host up
*
CF3300 JSR HOSTON
LDA #' ' ;get letter for status line
*
* Now do the status line
*
CF3600 LDX #78 ;column is 78
BNE CF1400
***************************************
*
* CF4
* ===
*
* Toggle cursor keys from VT52 to local
* edit mode
*
***************************************
CF4 LDA TTYPE ;get terminal type
CMP #2
BNE CF4900 ;j if not VT52 - ignore the key
LDA EDCRSR
EOR #2
STA EDCRSR ;else toggle mode from 0 to 2
TAX
LDA #4
JSR OBX0 ;set up cursor keys
LDA EDCRSR ;get mode back
LSR A
TAY ;form 0 or 1
LDA CF4TAB,Y ;get letter for status line
LDX #79 ;put it into column 79
JMP CF1400
CF4900 RTS
CF4TAB ASC 'E '
***************************************
*
* VT52 ESCAPE HANDLERS
* ====================
*
* VT52 mode ESCAPE sequences come to
* somewhere in here to be handled
*
***************************************
ESC100 EQU *
*
* Do we support the code just read?
*
LDY #ESQNUM
ESC120 CMP ESCSEQ,Y ;look in the list
BEQ ESC140 ;j if there
DEY
BPL ESC120
*
* Not supported, or it's done.
*
ESC130 JMP INICDV ;reset char disposition vector
*
* Here we do support the code, so enter its handler
*
ESC140 LDA ESCADL,Y ;set up the address
STA CHARIN
LDA ESCADH,Y
STA CHARIN+1
JMP (CHARIN) ;and do it
ESCSEQ ASC 'ABCDFGHIJKYZ=>'
ESQNUM EQU *-ESCSEQ-1
ESCADL DFB >ESCA
DFB >ESCB
DFB >ESCC
DFB >ESCD
DFB >ESCF
DFB >ESCG
DFB >ESCH
DFB >ESCI
DFB >ESCJ
DFB >ESCK
DFB >ESCY
DFB >ESCZ
DFB >ESCEQ
DFB >ESCGT
ESCADH DFB <ESCA
DFB <ESCB
DFB <ESCC
DFB <ESCD
DFB <ESCF
DFB <ESCG
DFB <ESCH
DFB <ESCI
DFB <ESCJ
DFB <ESCK
DFB <ESCY
DFB <ESCZ
DFB <ESCEQ
DFB <ESCGT
*
* ESC A : cursor up
* -----
*
ESCA JSR LOCATE ;where are we?
CPY #1
BEQ ESC130 ;no action if on top row
ESCA20 LDA #11
ESCA50 JSR OSWRCH ;else cursor up
JMP ESC130
*
*
* ESC B : Cursor down
* -----
*
ESCB JSR LOCATE ;where are we?
CPY #24
BEQ ESC130 ;no action if on bottom line
LDA #10
BNE ESCA50 ;else cursor down
*
*
* ESC C : Cursor right
* -----
*
ESCC JSR LOCATE ;where are we?
CPX #79
BEQ ESC130 ;no action if on far right
DEC VDUCNT ;else decrease chars left in line
JSR NOLFSP ;cancel lf suppression
LDA #9
BNE ESCA50 ;and cursor right
*
*
* ESC D : Cursor left
* -----
*
ESCD JSR LOCATE ;where are we?
CPX #0
BEQ ESC130 ;no action if at far left
INC VDUCNT ;else decrease chars left in line
JSR NOLFSP ;cancel lf suppression
LDA #8
BNE ESCA50 ;and cursor left
*
*
* ESC F : Enter graphics mode
* -----
*
ESCF LDA #$FF
ESCF10 STA GRMODE ;set graphics flag
JMP ESC130
*
*
* ESC G : Exit graphics mode
* -----
*
ESCG LDA #0 ;clear the flag
BEQ ESCF10
*
*
* ESC H : Home cursor
* -----
*
ESCH JSR HOME
ESCH10 LDA #$0A
JSR OSWRCH ;come down to BBC line 1
ESCH20 JSR VDUINI ;reset VDU controls
JMP ESC130
*
*
* ESC I : Reverse linefeed
* -----
*
ESCI JSR LOCATE ;find where we are now
CPY #1 ;are we on top line?
BNE ESCA20 ;j if not - just move cursor
LDA #206
JSR MESS ;clear status line and scroll screen
JSR RFSHSL ;rewrite status line
ESCI80 JSR REPOSN ;restore cursor position
JMP ESC130
*
*
* ESC J : Erase to end of screen
* -----
*
ESCJ JSR LOCATE ;find where we are
CPY #1
BNE ESCJ10 ;j if not top line
CPX #0
BNE ESCJ10 ;j if not at top left
LDA #48
JSR MESS ;else clear screen below status line
JMP ESCH20
*
* Not at top left, so clear to EOLN
*
ESCJ10 JSR SPFILL ;clear to EOLN
LDA CSRY ;what row are we on?
CMP #24
BNE ESCJ20 ;j if not on bottom line
JMP ESC130 ;else that's all
*
* Then set a window and clear below us
*
ESCJ20 LDA #61
JSR MESS ;start window sequence
LDY CSRY
INY
TYA
JSR OSWRCH ;add no of line below us
LDA #62
JSR MESS ;clear and reset window
JMP ESCI80
*
*
* ESC K : Erase to EOLN
* -----
*
ESCK JSR SPFILL
JMP ESC130
*
*
* ESC Y : Position cursor
* -----
*
ESCY LDA #>ESCY10 ; note handler for the next byte
STA CHARIN
LDA #<ESCY10
STA CHARIN+1
RTS
*
* Here the Y value has come in
*
ESCY10 SEC
SBC #31 ;form the row number
STA ESCYR ;save it
LDA #>ESCY20 ;set address for the next byte
STA CHARIN
LDA #<ESCY20
STA CHARIN+1
RTS
*
* Here the X value has come in
*
ESCY20 PHA ;save it
LDA #31
JSR OSWRCH ;start position sequence
PLA
SEC
SBC #32 ;form column number
STA WORK0 ;save the value
JSR OSWRCH
LDA ESCYR ;get row number from last time
JSR OSWRCH
*
* Now calculate the characters left on this line
*
LDA #79
SEC
SBC WORK0
STA VDUCNT ;note new value
JSR NOLFSP ;clear LF suppression
JMP ESC130
*
*
* ESC = and ESC > : Enter/exit keypad application mode
* ---------------
*
ESCEQ EQU *
ESCGT JMP ESC130 ;null command
*
*
* ESC Z : Identify terminal
* -----
*
ESCZ JSR TXESC ;send ESCAPE
LDA #'/'
JSR TXECHO ;then a "/"
LDA #'Z'
JSR TXECHO ;then a "Z"
JMP ESC130
***************************************
*
* CURSOR/F/SHIFT-F/KEYPAD HANDLER
* ===============================
*
* Sends the relevant ESCAPE sequence
* for these keys
*
***************************************
CFSF EQU *
*
* Is this a Master keypad key?
*
CMP #$D2
BCC CFF180 ;j if not
*
* It's a keypad key, so translate it into a function key value
*
LDY #24
CFF120 CMP CFFTB2,Y ;check in translate table
BEQ CFF190 ;j if found it
DEY
BPL CFF120 ;j if more to check
RTS ;else not there, so ignore the key
*
* Scale key and get final byte of sequence we send
*
CFF180 SEC
SBC #FKEY
TAY
CFF190 LDA CFFTAB,Y ;get final byte
BEQ CFF900 ;j if no sequence for this key
PHA ;else save it for a moment
*
* First we send ESCAPE
*
JSR TXESC
*
* If final character of sequence is 'l'..'y' or 'M' preced it with a '?'
*
PLA ;get final byte
CMP #'M'
BEQ CFF200 ;j if it's 'M'
CMP #'l'
BCC CFF300 ;j if not 'l'..'z'
CFF200 PHA ;else resave character
LDA #'?'
JSR TXECHO ;send the '?'
PLA ;reload character
*
* And send final byte of sequence
*
CFF300 JSR TXECHO
CFF900 RTS
CFFTAB DFB 'p' ;F0 - keypad keys 0..9
DFB 'q' ;F1
DFB 'r' ;F2
DFB 's' ;F3
DFB 't' ;F4
DFB 'u' ;F5
DFB 'v' ;F6
DFB 'w' ;F7
DFB 'x' ;F8
DFB 'y' ;F9
DFB 0 ;BREAK - not used
DFB 0 ;COPY- not used
DFB 'D' ;LEFT
DFB 'C' ;RIGHT
DFB 'B' ;DOWN
DFB 'A' ;UP
DFB 0 ;SF0 - not used
DFB 'P' ;SF1 - PF1
DFB 'Q' ;SF2 - PF2
DFB 'R' ;SF3 - PF3
DFB 'S' ;SF4 - PF4
DFB 'm' ;SF5 - MINUS
DFB 'l' ;SF6 - COMMA
DFB 'n' ;SF7 - PERIOD
DFB 'M' ;SF8 - ENTER
DFB 0 ;SF9 - not used
* This table translates the key codes
* for master keypad keys to give the number
* of the matching function key. The table
* contains the key codes ordered in F-key
* order
CFFTB2 DFB $F5 ;0
DFB $F6 ;1
DFB $F7 ;2
DFB $F8 ;3
DFB $F9 ;4
DFB $FA ;5
DFB $FB ;6
DFB $FC ;7
DFB $FD ;8
DFB $FE ;9
DFB 0,0,0,0,0,0,0 ;unused keys in the middle
DFB $F0 ;PF1 (key +)
DFB $F2 ;PF2 (key -)
DFB $F4 ;PF3 (key /)
DFB $EF ;PF4 (key *)
DFB $E8 ;MINUS (key #)
DFB $F1 ;COMMA (key ,)
DFB $F3 ;PERIOD (key .)
DFB $D2 ;ENTER (key RETURN)
***************************************
*
* TXESC
* =====
*
* Transmits ESCAPE
*
***************************************
TXESC LDA #$1B
JMP TXECHO
***************************************
*
* VT52 GRAPHICS CHARACTER SET
* ===========================
*
* These are the definitions for the
* VT52 Graphics Character set
*
***************************************
GRCHAR DFB %00111100 ;graphics character 95
DFB %01000010
DFB %10011001
DFB %10100001
DFB %10100001
DFB %10011001
DFB %01000010
DFB %00111100
DFB %00011000 ;graphics character 96
DFB %00111100
DFB %01111110
DFB %11111111
DFB %01111110
DFB %00111100
DFB %00011000
DFB %00000000
DFB %11001100 ;graphics character 97
DFB %11001100
DFB %00110011
DFB %00110011
DFB %11001100
DFB %11001100
DFB %00110011
DFB %00110011
DFB %10010000 ;graphics character 98
DFB %10010000
DFB %11110000
DFB %10010000
DFB %10011111
DFB %00000100
DFB %00000100
DFB %00000100
DFB %11110000 ;graphics character 99
DFB %10000000
DFB %11110000
DFB %10001111
DFB %10001000
DFB %00001111
DFB %00001000
DFB %00001000
DFB %11110000 ;graphics character 100
DFB %10000000
DFB %10000000
DFB %11111100
DFB %00010010
DFB %00011100
DFB %00010100
DFB %00010010
DFB %10000000 ;graphics character 101
DFB %10000000
DFB %10000000
DFB %10001111
DFB %11111000
DFB %00001110
DFB %00001000
DFB %00001000
DFB %01111000 ;graphics character 102
DFB %11001100
DFB %11001100
DFB %01111000
DFB %00000000
DFB %00000000
DFB %00000000
DFB %00000000
DFB %00011000 ;graphics character 103
DFB %00011000
DFB %01111110
DFB %00011000
DFB %00011000
DFB %00000000
DFB %01111110
DFB %00000000
DFB %10010000 ;graphics character 104
DFB %11010000
DFB %10110000
DFB %10010000
DFB %00001000
DFB %00001000
DFB %00001000
DFB %00001111
DFB %10001000 ;graphics character 105
DFB %10001000
DFB %10001000
DFB %01010000
DFB %00111111
DFB %00000100
DFB %00000100
DFB %00000100
DFB %00011000 ;graphics character 106
DFB %00011000
DFB %00011000
DFB %11111000
DFB %11111000
DFB %00000000
DFB %00000000
DFB %00000000
DFB %00000000 ;graphics character 107
DFB %00000000
DFB %00000000
DFB %11111000
DFB %11111000
DFB %00011000
DFB %00011000
DFB %00011000
DFB %00000000 ;graphics character 108
DFB %00000000
DFB %00000000
DFB %00011111
DFB %00011111
DFB %00011000
DFB %00011000
DFB %00011000
DFB %00011000 ;graphics character 109
DFB %00011000
DFB %00011000
DFB %00011111
DFB %00011111
DFB %00000000
DFB %00000000
DFB %00000000
DFB %00011000 ;graphics character 110
DFB %00011000
DFB %00011000
DFB %11111111
DFB %11111111
DFB %00011000
DFB %00011000
DFB %00011000
DFB %11111111 ;graphics character 111
DFB %11111111
DFB %00000000
DFB %00000000
DFB %00000000
DFB %00000000
DFB %00000000
DFB %00000000
DFB %00000000 ;graphics character 112
DFB %11111111
DFB %11111111
DFB %00000000
DFB %00000000
DFB %00000000
DFB %00000000
DFB %00000000
DFB %00000000 ;graphics character 113
DFB %00000000
DFB %11111111
DFB %11111111
DFB %00000000
DFB %00000000
DFB %00000000
DFB %00000000
DFB %00000000 ;graphics character 114
DFB %00000000
DFB %00000000
DFB %00000000
DFB %11111111
DFB %11111111
DFB %00000000
DFB %00000000
DFB %00000000 ;graphics character 115
DFB %00000000
DFB %00000000
DFB %00000000
DFB %00000000
DFB %00000000
DFB %11111111
DFB %11111111
DFB %00011000 ;graphics character 116
DFB %00011000
DFB %00011000
DFB %00011111
DFB %00011111
DFB %00011000
DFB %00011000
DFB %00011000
DFB %00011000 ;graphics character 117
DFB %00011000
DFB %00011000
DFB %11111000
DFB %11111000
DFB %00011000
DFB %00011000
DFB %00011000
DFB %00011000 ;graphics character 118
DFB %00011000
DFB %00011000
DFB %11111111
DFB %11111111
DFB %00000000
DFB %00000000
DFB %00000000
DFB %00000000 ;graphics character 119
DFB %00000000
DFB %00000000
DFB %11111111
DFB %11111111
DFB %00011000
DFB %00011000
DFB %00011000
DFB %00011000 ;graphics character 120
DFB %00011000
DFB %00011000
DFB %00011000
DFB %00011000
DFB %00011000
DFB %00011000
DFB %00011000
DFB %00000110 ;graphics character 121
DFB %00011000
DFB %01100000
DFB %00011000
DFB %00000110
DFB %00000000
DFB %01111110
DFB %00000000
DFB %01100000 ;graphics character 122
DFB %00011000
DFB %00000110
DFB %00011000
DFB %01100000
DFB %00000000
DFB %01111110
DFB %00000000
DFB %00000000 ;graphics character 123
DFB %00000011
DFB %11111111
DFB %01100110
DFB %01100110
DFB %01100110
DFB %01100110
DFB %00000000
DFB %00000011 ;graphics character 124
DFB %00000110
DFB %11111111
DFB %00001100
DFB %00011000
DFB %11111111
DFB %01100000
DFB %11000000
DFB %00011100 ;graphics character 125
DFB %00110110
DFB %00110000
DFB %01111100
DFB %00110000
DFB %00110000
DFB %01111110
DFB %00000000
DFB %00000000 ;graphics character 126
DFB %00000000
DFB %00000000
DFB %00011000
DFB %00011000
DFB %00000000
DFB %00000000
DFB %00000000
NEXT BBCPM1
****** File BBCTX1 *************************************************************
START TX1
* BBCTX1: Updated 10/01/87 @ 1730
***************************************
*
* TEXTS
* -----
*
* These texts are output by the message
* system.
*
* Control bytes used are:
*
* TXT <n> recurse to output text n
* MSP <n> output n spaces
* RPT <n> <m> output n copies of character m
* LIT <n> output character n as is
* XCR output byte value 13 without change to CR-LF
* MTXT <n> <m> recurse to output text m, n times
*
***************************************
M0 DFB 3,22,7,TXT,151
DFB NORMHT,TXT,120 ;version string
DFB $0D,TXT,151,$0D
DFB GREEN
DFB TXT,119 ;'By Lancaster ....'
DFB EOT
M1 ASC 'RX:'
DFB EOT
M2 DFB $0D
ASC 'SOH!'
DFB $0D
DFB EOT
M3 DFB $0D
ASC 'Early EOLN'
DFB $0D
DFB EOT
M4 DFB $0D
ASC 'Short pkt'
DFB EOT
M5 DFB $0D
ASC 'Bad len'
DFB $0D
DFB EOT
M6 DFB $0D
ASC 'Bad c/s'
DFB $0D
DFB EOT
M7 DFB $0D
ASC 'BUF oflw'
DFB $0D
DFB EOT
M8 DFB $0D
ASC 'SENDSW'
DFB TXT,153 ;' : State '
DFB EOT
M9 DFB YELLOW,TXT,158,WHITE ;'BBC>'
DFB EOT
M10 DFB TXT,0 ;main header
DFB 31,0,4,YELLOW
ASC 'ACTION:'
DFB CYAN,31,21,4,YELLOW
ASC 'STATUS :'
DFB CYAN,$0D,YELLOW
ASC 'F.TYPE:'
DFB CYAN,31,21,5,YELLOW
ASC '8BIT PFX:'
DFB CYAN,31,21,6,YELLOW
ASC 'INTRPT :'
DFB CYAN,31,0,10,YELLOW
ASC 'FILENAMES'
DFB $0D,CYAN
ASC ' Remote:'
DFB GREEN,$0D,CYAN
ASC ' Local :'
DFB GREEN,31,0,15,YELLOW
ASC 'COUNTERS'
DFB $0D,CYAN
ASC ' Packets'
DFB GREEN,31,14,16,'0',CYAN
ASC ' Files'
DFB GREEN
ASC ' 0'
DFB CYAN
ASC ' Kbytes:'
DFB $0D
DFB CYAN
ASC ' Retries'
DFB GREEN,31,14,17,'0',CYAN
DFB 31,29,17
ASC 'Current'
DFB GREEN
ASC ' 0'
DFB CYAN
ASC ' T/outs'
DFB GREEN,31,14,18,'0',CYAN
DFB 31,29,18
ASC 'Total '
DFB GREEN
ASC ' 0'
DFB EOT
M11 DFB 31,0,8,YELLOW,7,NEWBG,RED
ASC 'WARNING : Non-ASCII data '
DFB BLKBG
DFB EOT
M12 DFB 31,0,22
DFB TXT,138 ;'ERROR : '
DFB EOT
M13 DFB $0D,$0D,YELLOW
DFB TXT,216 ;'TRANSFER'
DFB TXT,65 ;' PARAMETERS'
DFB EOT
M14 DFB 31,2,20,YELLOW,NEWBG,RED
ASC 'RETURN for more; ESCAPE to quit '
DFB BLKBG
DFB EOT
M15 DFB $0D
ASC 'RECSW'
DFB TXT,153 ;' : State '
DFB EOT
M16 DFB 31,0,24
DFB TXT,148 ;'Press any key to '
ASC 'return'
DFB TXT,157 ;' to command mode'
DFB EOT
M17 DFB 31,0,20,FLASH,YELLOW
ASC ' *** '
DFB TXT,216 ;'TRANSFER'
ASC ' COMPLETED OK ***'
DFB EOT
M18 DFB ' ',CYAN
DFB 'P',TXT,217 ;'Packet size'
DFB MSP,3,GREEN
DFB EOT
M19 DFB 31,10,18
DFB EOT
M20 DFB 31,9,XCR
DFB EOT
M21 ASC 'Byte'
DFB TXT,221 ;' period'
ASC ' delay (0-255)'
DFB EOT
M22 DFB 31,32,5
ASC 'Not used'
DFB EOT
M23 ASC 'Waiting '
DFB EOT
M24 ASC 'Transmit'
DFB EOT
M25 ASC 'Receive '
DFB EOT
M26 DFB 31,32,5
ASC 'In use '
DFB EOT
M27 DFB $0D
STR 'Options are :'
DFB EOT
M28 DFB 31,10,11
DFB EOT
M29 DFB 31,10,12
DFB EOT
M30 DFB CYAN
ASC 'TX baud'
DFB MSP,6,GREEN
DFB EOT
M31 DFB 31,23,16
DFB EOT
M32 DFB TXT,154 ;'A filename on '
DFB TXT,163 ;' remote system'
DFB EOT
M33 DFB TXT,154 ;'A filename on '
ASC ' the BBC'
DFB EOT
M34 DFB 0,0,0
DFB EOT
M35 ASC 'TX:'
DFB EOT
M36 DFB 31,10,16
DFB EOT
M37 DFB 31,10,17
DFB EOT
M38 ASC 'No more '
DFB TXT,180,'s' ;' parameters'
ASC ' for this '
DFB TXT,169 ;'command'
DFB EOT
M39 DFB $0D
ASC 'FB full'
DFB $0D
DFB EOT
M40 DFB $0D
ASC 'FB out'
DFB $0D
DFB EOT
M41 DFB ' ',CYAN
ASC '8bit '
DFB TXT,220 ;'prefix'
DFB MSP,5,GREEN
DFB EOT
M42 DFB 31,32,6
DFB EOT
M43 DFB 23,1,1,RPT,7,0
DFB EOT
M44 DFB 23,1,RPT,8,0
DFB EOT
M45 ASC 'Writing'
DFB EOT
M46 ASC 'Reading'
DFB EOT
M47 DFB 22,7
DFB EOT
M48 DFB 28,0,24,79,1,12,26,$0A
DFB EOT
M49 DFB 31,9,4
ASC 'Receive'
DFB TXT,56 ;' file'
DFB EOT
M50 DFB 31,9,4
ASC 'Send'
DFB TXT,56 ;' file'
DFB EOT
M51 ASC 'Idle'
DFB MSP,4
DFB EOT
M52 ASC 'Opening '
DFB EOT
M53 ASC 'Closing '
DFB EOT
M54 DFB 31,32,4
DFB EOT
M55 DFB CYAN
ASC 'Handshake'
DFB MSP,5,GREEN
DFB EOT
M56 ASC ' file'
DFB EOT
M57 DFB ' ',CYAN
ASC 'MUX wait'
DFB MSP,6,GREEN
DFB EOT
M58 ASC 'Delay after SEND '
DFB TXT,169 ;'command'
DFB TXT,159 ;', in seconds'
DFB EOT
M59 ASC 'Pausing '
DFB EOT
M60 ASC 'Delay before '
DFB 'p',TXT,218 ;'packet'
ASC ' send'
DFB TXT,159 ;', in seconds'
DFB EOT
M61 DFB 28,0,24,79
DFB EOT
M62 DFB 12,26
DFB EOT
M63 DFB ' ',CYAN
ASC 'RX baud'
DFB MSP,5,GREEN
DFB EOT
M64 DFB CYAN
ASC 'Debugging'
DFB MSP,6,GREEN
DFB EOT
M65 STR ' PARAMETERS'
DFB EOT
M66 DFB ' ',CYAN
ASC 'Parity'
DFB MSP,6,GREEN
DFB EOT
M67 DFB ' ',CYAN
ASC 'Retries'
DFB MSP,7,GREEN
DFB EOT
M68 DFB ' ',CYAN
ASC 'TX pause(s)'
DFB MSP,3,GREEN
DFB EOT
M69 DFB CYAN
ASC 'SEND delay(s) '
DFB GREEN
DFB EOT
M70 DFB ' ',CYAN
DFB 'T',TXT,91,' ',' ' ;'Terminal '
DFB GREEN
DFB EOT
M71 DFB ' ',CYAN
DFB TXT,191,' ' ;'Quote character'
DFB GREEN
DFB EOT
M72 DFB 31,9,5
DFB EOT
M73 DFB TXT,172 ;'Character'
ASC ' we use for control quoting'
DFB EOT
M74 DFB ' ',CYAN
ASC 'Local '
DFB TXT,219 ;'echo'
DFB MSP,4,GREEN
DFB EOT
M75 ASC 'CTRL-'
DFB EOT
M76 DFB $0C,YELLOW
ASC 'GENERAL'
DFB TXT,65 ;' PARAMETERS'
DFB EOT
M77 DFB $0D,YELLOW
ASC 'RECEIVE'
DFB TXT,65 ;' PARAMETERS'
DFB EOT
M78 DFB $0D,$0D,YELLOW
ASC 'SEND'
DFB TXT,65 ;' PARAMETERS'
DFB EOT
M79 DFB YELLOW
ASC 'TERMINAL'
DFB TXT,65 ;' PARAMETERS'
DFB EOT
M80 DFB CYAN
ASC 'Timer'
DFB MSP,10,GREEN
DFB EOT
M81 DFB CYAN
ASC 'End-of-line'
DFB MSP,4,GREEN,'X'
DFB EOT
M82 DFB CYAN
DFB 'P',TXT,174 ;'Pad character'
DFB MSP,2,GREEN,'&'
DFB EOT
M83 DFB ' ',CYAN
DFB 'P',TXT,218 ;'Packet'
ASC 'start'
DFB MSP,2,GREEN,'&'
DFB EOT
M84 DFB $0D,$0D,YELLOW
ASC 'FILE'
DFB TXT,65 ;' PARAMETERS'
DFB EOT
M85 DFB ' ',CYAN
DFB TXT,170 ;'File '
ASC 'type'
DFB MSP,2,GREEN
DFB EOT
M86 DFB ' ',CYAN
ASC 'Data source'
DFB MSP,6,GREEN
DFB EOT
M87 EQU *
IF ROM
DFB $0D
FI
DFB ' ',CYAN
ASC 'Data destination '
DFB GREEN
DFB EOT
M88 DFB CYAN
ASC 'Pad count'
DFB MSP,6,GREEN
DFB EOT
M89 DFB ' ',CYAN
DFB TXT,205 ;'Timeout'
ASC '(s)'
DFB MSP,4,GREEN
DFB EOT
M90 DFB TXT,205 ;'Timeout'
DFB $0D
DFB EOT
M91 ASC 'erminal '
DFB EOT
M92 DFB TXT,205 ;'Timeout'
ASC ' we use'
DFB TXT,159 ;', in seconds'
DFB EOT
M93 DFB TXT,200 ;'Start-of-packet character'
DFB TXT,201 ;' we send to remote'
DFB TXT,202 ;' (0-31)'
DFB EOT
M94 DFB 'P',TXT,174 ;'Pad character'
DFB TXT,224 ;' we send'
DFB TXT,202 ;' (0-31)'
DFB EOT
M95 DFB TXT,213 ;'Number of '
DFB 'p',TXT,174,'s' ;'pad characters'
DFB TXT,224 ;' we send'
DFB EOT
M96 DFB TXT,203 ;'End-of-line character'
DFB TXT,201 ;' we send to remote'
DFB TXT,202 ;' (0-31)'
DFB EOT
M97 DFB 31,0,8
DFB EOT
M98 DFB TXT,200 ;'Start-of-packet character'
DFB TXT,199 ;' we wish to receive'
DFB TXT,202 ;' (0-31)'
DFB EOT
M99 DFB 'P',TXT,174 ;'Pad character'
DFB TXT,160 ;' remote is to use'
DFB TXT,202 ;' (0-31)'
DFB EOT
M100 DFB TXT,213 ;'Number of '
DFB 'p',TXT,174,'s' ;'pad characters'
DFB TXT,160 ;' remote is to use'
ASC ' (0-94)'
DFB EOT
M101 DFB TXT,205 ;'Timeout'
DFB TXT,160 ;' remote is to use'
DFB TXT,159 ;', in seconds'
DFB EOT
M102 ASC 'Hex a'
DFB TXT,226 ;'ddress'
DFB EOT
M103 DFB TXT,170 ;'File '
DFB 'b',TXT,214 ;'buffer size'
ASC ' (pages)'
DFB EOT
M104 DFB YELLOW,NEWBG,RED
ASC '(Renamed by BBC '
DFB TXT,156 ;'KERMIT'
ASC ') '
DFB BLKBG
DFB EOT
M105 DFB ' ',CYAN
ASC 'Incomplete '
DFB GREEN
DFB EOT
M106 DFB CYAN
DFB TXT,170 ;'File '
ASC 'warning'
DFB MSP,3,GREEN
DFB EOT
M107 DFB TXT,170 ;'File '
ASC 'for t'
DFB TXT,212 ;'erminal log'
DFB $0D
DFB EOT
M108 DFB CYAN
ASC 'End of record '
DFB GREEN
DFB EOT
M109 DFB ' ',CYAN
DFB 'B',TXT,214 ;'Buffer size'
ASC '(p)'
DFB GREEN
DFB EOT
M110 DFB TXT,0 ;main header
DFB 28,0,24,39,4
DFB EOT
M111 DFB 31,36,0
DFB EOT
M112 DFB CYAN
DFB 'T',TXT,212 ;'Terminal log'
DFB MSP,3,GREEN
DFB EOT
M113 DFB TXT,170 ;'File '
ASC 'for '
DFB TXT,156 ;'KERMIT'
DFB ' ',TXT,180,'s' ;' parameters'
DFB EOT
M114 DFB TXT,175 ;'Suffix '
ASC 'added to remote filenames'
DFB EOT
M115 DFB CYAN
DFB TXT,175 ;'Suffix '
DFB MSP,3,GREEN
DFB EOT
M116 DFB TXT,219,$0D ;'echo'
DFB EOT
M117 DFB TXT,170 ;'File '
ASC 'of '
DFB TXT,156 ;'KERMIT'
DFB ' ',TXT,169,'s' ;'commands'
DFB EOT
M118 DFB CYAN
ASC 'TAKE-'
DFB TXT,170 ;'File '
DFB TXT,219,' ' ;'echo '
DFB GREEN
DFB EOT
M119 ASC 'By Lancaster University Computing Dept'
DFB EOT
M120 EQU *
IF ROM
ASC 'ROM'
ELSE
ASC 'RAM'
FI
DFB TXT,222 ;' Vm.vv'
DFB EOT
M121 DFB ' ',CYAN
ASC 'Key clicks'
DFB MSP,4,GREEN
DFB EOT
M122 ASC 'Maximum '
DFB 'p',TXT,217 ;'packet size'
DFB TXT,199 ;' we wish to receive'
ASC ' (35-94)'
DFB EOT
M123 DFB TXT,203 ;'End-of-line character'
DFB TXT,201 ;' we send to remote'
DFB TXT,202 ;' (0-31)'
DFB EOT
M124 DFB TXT,203 ;'End-of-line character'
DFB TXT,199 ;' we wish to receive'
DFB TXT,202 ;' (0-31)'
DFB EOT
M125 ASC 'Eight-bit-'
DFB TXT,220 ;'prefix'
DFB TXT,152 ;' character'
DFB EOT
M126 ASC 'ON'
DFB EOT
M127 ASC 'OFF'
DFB EOT
M128 DFB TXT,207 ;'BBC Kermit'
ASC ': '
DFB TXT,119 ;'By Lancaster ... '
DFB MSP,9,TXT,120,$0D ;version string
DFB EOT
M129 DFB CYAN
ASC 'Flow ctrl '
DFB GREEN
DFB EOT
NEXT BBCTX2
****** File BBCTX2 *************************************************************
START TX2
* BBCTX2 : Updated 10/07/86 @ 1800
M130 ASC 'Wait'
DFB TXT,221 ;' period'
DFB TXT,159 ;', in seconds'
DFB EOT
M131 DFB TXT,23,$0D ;'Waiting'
DFB EOT
M132 ASC 'Text to display'
DFB EOT
M133 DFB CYAN
ASC 'VDU colour '
DFB GREEN
DFB EOT
M134 DFB 19,1
DFB EOT
M135 DFB TXT,136 ;inverse video
ASC 'C-F||0=Exit||1=Disc||2=Prnt||3=Hold||4=Crsr||5='
DFB MSP,4
ASC '||6='
DFB MSP,4
ASC '||7='
DFB MSP,4
ASC '||8=Lbrk||9=Brk ||'
DFB MSP,6
DFB TXT,137 ;normal video
DFB EOT
M136 DFB 17,129,17,0
DFB EOT
M137 DFB 17,128,17,1
DFB EOT
M138 ASC 'ERROR : '
DFB EOT
M139 DFB ' ',CYAN
ASC 'Ignore char'
DFB MSP,3,GREEN
DFB EOT
M140 DFB CYAN
ASC '*TV pars'
DFB MSP,3,GREEN
DFB EOT
M141 DFB TXT,172 ;'Character'
ASC ' to ignore'
DFB EOT
M142 DFB 3,28,0,24,79,24,12,26,31,0,24,$0A
DFB EOT
M143 ASC '*TV '
DFB TXT,180 ;'parameter'
DFB EOT
M144 ASC 'Address'
DFB EOT
M145 DFB 31,37,17
DFB EOT
M146 DFB ' ',CYAN
ASC 'Help trigger'
DFB MSP,4,GREEN
DFB EOT
M147 ASC 'Sure (Y/N)? '
DFB EOT
M148 ASC 'Press any key to '
DFB EOT
M149 DFB 31,37,18
DFB EOT
M150 ASC 'Retries allowed (1..255)'
DFB EOT
M151 DFB YELLOW,NEWBG,DOUBLE,BLUE
DFB TXT,207 ;'CUCCA KERMIT (RxM) '
DFB EOT
M152 ASC ' c'
DFB TXT,173 ;'haracter'
DFB EOT
M153 ASC ' : State '
DFB EOT
M154 ASC 'A'
DFB TXT,171 ;' filename on'
DFB EOT
M155 DFB MSP,4,TXT,75,'F' ;'CTRL-F'
DFB EOT
M156 ASC 'KERMIT'
DFB EOT
M157 ASC ' to '
DFB TXT,169 ;'command'
ASC ' mode'
DFB EOT
M158 ASC 'BBC>'
DFB EOT
M159 ASC ', in seconds'
DFB EOT
M160 DFB TXT,163 ;' remote system'
ASC ' is to use'
DFB EOT
M161 ASC 'Filespec for'
DFB TXT,163 ;' remote system'
ASC ' directory list'
DFB EOT
M162 ASC 'Old'
DFB TXT,171 ;' filename on'
DFB TXT,163 ;' remote system'
DFB EOT
M163 ASC ' remote system'
DFB EOT
M164 ASC 'New'
DFB TXT,171 ;' filename on'
DFB TXT,163 ;' remote system'
DFB EOT
M165 ASC 'Topic on'
DFB TXT,163 ;' remote system'
DFB EOT
M166 ASC 'System '
DFB TXT,169 ;'command'
ASC ' on'
DFB TXT,163 ;' remote system'
DFB EOT
M167 ASC 'Not a '
DFB EOT
M168 ASC 'Disc area on'
DFB TXT,163 ;' remote system'
DFB EOT
M169 ASC 'command'
DFB EOT
M170 ASC 'File '
DFB EOT
M171 ASC ' filename on'
DFB EOT
M172 ASC 'C'
DFB TXT,173 ;'haracter'
DFB EOT
M173 ASC 'haracter'
DFB EOT
M174 ASC 'ad'
DFB TXT,152 ;' character'
DFB EOT
M175 ASC 'Suffix '
DFB EOT
M176 ASC ' logging '
DFB EOT
M177 DFB TXT,158,' ' ;'BBC> '
DFB EOT
M178 DFB 31,2,20,YELLOW,NEWBG,RED,' ',' '
DFB TXT,148 ;'Press any key to '
ASC 'continue'
DFB MSP,6,BLKBG
DFB EOT
M179 DFB $0D
DFB TXT,138 ;'ERROR : '
DFB EOT
M180 ASC 'parameter'
DFB EOT
M181 ASC 'Mandatory '
DFB TXT,180,'s' ;'parameters'
ASC ' missing'
DFB EOT
M182 ASC 'Too many '
DFB TXT,180,'s' ;'paramaters'
ASC ' supplied'
DFB EOT
M183 ASC 'Ambiguous'
DFB TXT,185 ;' command or parameter'
DFB EOT
M184 ASC 'Unknown'
DFB TXT,185 ;' command or parameter'
DFB EOT
M185 DFB ' ',TXT,169 ;' command'
ASC ' or '
DFB TXT,180 ;'parametr'
DFB EOT
M186 DFB TXT,187 ;'Not a valid '
DFB TXT,125 ;'Eight-bit-prefix character'
DFB EOT
M187 DFB TXT,167 ;'Not a '
ASC 'valid '
DFB EOT
M188 DFB TXT,125 ;'Eight-bit-prefix character'
DFB TXT,193 ;' cannot be same as '
DFB TXT,191 ;'Quote character'
DFB EOT
M189 DFB TXT,175 ;'Suffix '
ASC 'string'
DFB TXT,190 ;' is too long'
DFB EOT
M190 ASC ' is too long'
DFB EOT
M191 ASC 'Quote'
DFB TXT,152 ;' character'
DFB EOT
M192 DFB TXT,191 ;'Quote character'
DFB TXT,193 ;' cannot be same as '
DFB TXT,125 ;'Eight-bit-prefix character'
DFB EOT
M193 ASC " can't be same as "
DFB EOT
M194 ASC 'Value is out of range'
DFB EOT
M195 DFB TXT,170 ;'File '
ASC 'name'
DFB TXT,190 ;' is too long'
DFB EOT
M196 DFB TXT,187 ;'Not a valid '
ASC 'number'
DFB EOT
M197 ASC 'Directory on'
DFB TXT,163 ;' remote system'
DFB EOT
M198 DFB TXT,167 ;'Not a '
ASC 'single'
DFB TXT,152 ;' character'
DFB EOT
M199 ASC ' we wish to receive'
DFB EOT
M200 ASC 'Start-of-'
DFB 'p',TXT,218 ;'packet'
DFB TXT,152 ;' character'
DFB EOT
M201 DFB TXT,224 ;' we send'
ASC ' to'
DFB TXT,163 ;' remote system'
DFB EOT
M202 ASC ' (0-31)'
DFB EOT
M203 ASC 'End-of-line'
DFB TXT,152 ;' character'
DFB EOT
M204 ASC 'Password?'
DFB EOT
M205 ASC 'Timeout'
DFB EOT
M206 DFB 28,0,0,79,0,12,26,11
DFB EOT
M207 ASC ' BBC MICRO '
DFB TXT,156 ;'KERMIT'
ASC ' '
DFB EOT
M208 ASC 'DL/PT '
DFB EOT
M209 ASC 'Type? '
DFB EOT
M210 DFB 22,3
DFB EOT
M211 DFB 22,7
DFB YELLOW,NEWBG,RED
ASC 'CF:0=Exi:1=Dsc:2=Prt:3=Hld:4='
DFB MSP,3,':',$0D
DFB YELLOW,NEWBG,RED
ASC ' :5='
DFB MSP,3
ASC ':6='
DFB MSP,3
ASC ':7='
DFB MSP,3
ASC ':8=Lbk:9=Brk:'
DFB 28,0,24,39,2
DFB EOT
M212 DFB TXT,91 ;'erminal '
ASC 'log'
DFB EOT
M213 ASC 'Number of '
DFB EOT
M214 ASC 'uffer size'
DFB EOT
M215 DFB ' ',CYAN
ASC 'Name '
DFB GREEN
DFB EOT
M216 ASC 'TRANSFER'
DFB EOT
M217 DFB TXT,218 ;'acket '
ASC 'size'
DFB EOT
M218 ASC 'acket '
DFB EOT
M219 ASC 'echo'
DFB EOT
M220 ASC 'prefix'
DFB EOT
M221 ASC ' period'
DFB EOT
M222 ASC ' V'
DFB MARK+$30
ASC '.'
DFB VERSION/10+$30
DFB (VERSION-(VERSION/10*10))+$30
IF ~LEVEL
DFB LEVEL+'A'
ELSE
DFB ' '
FI
DFB EOT
M223 DFB $0D,TXT,156 ;'KERMIT'
DFB TXT,222,$0D ;' Vm.vv'
DFB EOT
M224 ASC ' we send'
DFB EOT
M225 DFB TXT,170 ;'File '
ASC 'to transmit'
DFB EOT
M226 ASC 'ddress'
DFB EOT
M227 DFB 'A',TXT,226 ;'Address'
DFB EOT
***************************************
*
* MESSAGE ADDRESS TABLE
* =====================
*
* This defines the start address of each
* of the texts.
*
* The first table holds the low bytes of
* each address, one message per table byte
*
* The second table is built with the MTHE
* macro. It contains a list of message numbers,
* each being the first message to start
* within one page, relative to the page
* M0 is in. The macro takes two parameters,
* so for message n the call should be
* MTHE n-1,n
*
***************************************
MSGTBL DFB >M0,>M1,>M2,>M3,>M4,>M5,>M6,>M7,>M8,>M9
DFB >M10,>M11,>M12,>M13,>M14,>M15,>M16,>M17,>M18,>M19
DFB >M20,>M21,>M22,>M23,>M24,>M25,>M26,>M27,>M28,>M29
DFB >M30,>M31,>M32,>M33,>M34,>M35,>M36,>M37,>M38,>M39
DFB >M40,>M41,>M42,>M43,>M44,>M45,>M46,>M47,>M48,>M49
DFB >M50,>M51,>M52,>M53,>M54,>M55,>M56,>M57,>M58,>M59
DFB >M60,>M61,>M62,>M63,>M64,>M65,>M66,>M67,>M68,>M69
DFB >M70,>M71,>M72,>M73,>M74,>M75,>M76,>M77,>M78,>M79
DFB >M80,>M81,>M82,>M83,>M84,>M85,>M86,>M87,>M88,>M89
DFB >M90,>M91,>M92,>M93,>M94,>M95,>M96,>M97,>M98,>M99
DFB >M100,>M101,>M102,>M103,>M104,>M105,>M106,>M107,>M108,>M109
DFB >M110,>M111,>M112,>M113,>M114,>M115,>M116,>M117,>M118,>M119
DFB >M120,>M121,>M122,>M123,>M124,>M125,>M126,>M127,>M128,>M129
DFB >M130,>M131,>M132,>M133,>M134,>M135,>M136,>M137,>M138,>M139
DFB >M140,>M141,>M142,>M143,>M144,>M145,>M146,>M147,>M148,>M149
DFB >M150,>M151,>M152,>M153,>M154,>M155,>M156,>M157,>M158,>M159
DFB >M160,>M161,>M162,>M163,>M164,>M165,>M166,>M167,>M168,>M169
DFB >M170,>M171,>M172,>M173,>M174,>M175,>M176,>M177,>M178,>M179
DFB >M180,>M181,>M182,>M183,>M184,>M185,>M186,>M187,>M188,>M189
DFB >M190,>M191,>M192,>M193,>M194,>M195,>M196,>M197,>M198,>M199
DFB >M200,>M201,>M202,>M203,>M204,>M205,>M206,>M207,>M208,>M209
DFB >M210,>M211,>M212,>M213,>M214,>M215,>M216,>M217,>M218,>M219
DFB >M220,>M221,>M222,>M223,>M224,>M225,>M226,>M227
MSGTBH DFB 0 ;M0 starts page relative 0
MTHE 0,1
MTHE 1,2
MTHE 2,3
MTHE 3,4
MTHE 4,5
MTHE 5,6
MTHE 6,7
MTHE 7,8
MTHE 8,9
MTHE 9,10
MTHE 10,11
MTHE 11,12
MTHE 12,13
MTHE 13,14
MTHE 14,15
MTHE 15,16
MTHE 16,17
MTHE 17,18
MTHE 18,19
MTHE 19,20
MTHE 20,21
MTHE 21,22
MTHE 22,23
MTHE 23,24
MTHE 24,25
MTHE 25,26
MTHE 26,27
MTHE 27,28
MTHE 28,29
MTHE 29,30
MTHE 30,31
MTHE 31,32
MTHE 32,33
MTHE 33,34
MTHE 34,35
MTHE 35,36
MTHE 36,37
MTHE 37,38
MTHE 38,39
MTHE 39,40
MTHE 40,41
MTHE 41,42
MTHE 42,43
MTHE 43,44
MTHE 44,45
MTHE 45,46
MTHE 46,47
MTHE 47,48
MTHE 48,49
MTHE 49,50
MTHE 50,51
MTHE 51,52
MTHE 52,53
MTHE 53,54
MTHE 54,55
MTHE 55,56
MTHE 56,57
MTHE 57,58
MTHE 58,59
MTHE 59,60
MTHE 60,61
MTHE 61,62
MTHE 62,63
MTHE 63,64
MTHE 64,65
MTHE 65,66
MTHE 66,67
MTHE 67,68
MTHE 68,69
MTHE 69,70
MTHE 70,71
MTHE 71,72
MTHE 72,73
MTHE 73,74
MTHE 74,75
MTHE 75,76
MTHE 76,77
MTHE 77,78
MTHE 78,79
MTHE 79,80
MTHE 80,81
MTHE 81,82
MTHE 82,83
MTHE 83,84
MTHE 84,85
MTHE 85,86
MTHE 86,87
MTHE 87,88
MTHE 88,89
MTHE 89,90
MTHE 90,91
MTHE 91,92
MTHE 92,93
MTHE 93,94
MTHE 94,95
MTHE 95,96
MTHE 96,97
MTHE 97,98
MTHE 98,99
MTHE 99,100
MTHE 100,101
MTHE 101,102
MTHE 102,103
MTHE 103,104
MTHE 104,105
MTHE 105,106
MTHE 106,107
MTHE 107,108
MTHE 108,109
MTHE 109,110
MTHE 110,111
MTHE 111,112
MTHE 112,113
MTHE 113,114
MTHE 114,115
MTHE 115,116
MTHE 116,117
MTHE 117,118
MTHE 118,119
MTHE 119,120
MTHE 120,121
MTHE 121,122
MTHE 122,123
MTHE 123,124
MTHE 124,125
MTHE 125,126
MTHE 126,127
MTHE 127,128
MTHE 128,129
MTHE 129,130
MTHE 130,131
MTHE 131,132
MTHE 132,133
MTHE 133,134
MTHE 134,135
MTHE 135,136
MTHE 136,137
MTHE 137,138
MTHE 138,139
MTHE 139,140
MTHE 140,141
MTHE 141,142
MTHE 142,143
MTHE 143,144
MTHE 144,145
MTHE 145,146
MTHE 146,147
MTHE 147,148
MTHE 148,149
MTHE 149,150
MTHE 150,151
MTHE 151,152
MTHE 152,153
MTHE 153,154
MTHE 154,155
MTHE 155,156
MTHE 156,157
MTHE 157,158
MTHE 158,159
MTHE 159,160
MTHE 160,161
MTHE 161,162
MTHE 162,163
MTHE 163,164
MTHE 164,165
MTHE 165,166
MTHE 166,167
MTHE 167,168
MTHE 168,169
MTHE 169,170
MTHE 170,171
MTHE 171,172
MTHE 172,173
MTHE 173,174
MTHE 174,175
MTHE 175,176
MTHE 176,177
MTHE 177,178
MTHE 178,179
MTHE 179,180
MTHE 180,181
MTHE 181,182
MTHE 182,183
MTHE 183,184
MTHE 184,185
MTHE 185,186
MTHE 186,187
MTHE 187,188
MTHE 188,189
MTHE 189,190
MTHE 190,191
MTHE 191,192
MTHE 192,193
MTHE 193,194
MTHE 194,195
MTHE 195,196
MTHE 196,197
MTHE 197,198
MTHE 198,199
MTHE 199,200
MTHE 200,201
MTHE 201,202
MTHE 202,203
MTHE 203,204
MTHE 204,205
MTHE 205,206
MTHE 206,207
MTHE 207,208
MTHE 208,209
MTHE 209,210
MTHE 210,211
MTHE 211,212
MTHE 212,213
MTHE 213,214
MTHE 214,215
MTHE 215,216
MTHE 216,217
MTHE 217,218
MTHE 218,219
MTHE 219,220
MTHE 220,221
MTHE 221,222
MTHE 222,223
MTHE 223,224
MTHE 224,225
MTHE 225,226
MTHE 226,227
MTHCNT EQU *-MSGTBH-1
LST ON
PRGTOP EQU *
IF LFULL!LSTXXX&LIST
LST ON
ELSE
LST OFF
FI
IF ROM
DS $C000-*
IF ~ADE
DISP2 'ROM space free %D($C000-PRGTOP) bytes'
FI
FI
****** File BBCWKS *************************************************************
START WKS
* BBCWKS: Updated 10/01/87 @ 1730
**************************************
*
* WORKSPACE
* =========
*
* This defines the non-page 0 areas
* to be used
*
**************************************
DSECT
ORG $400
WKBASE EQU *
***************************************
*
* Locations in this block are maintained
* by the main program but can be used
* by a TXR for the same purposes. Their
* location is fixed
*
***************************************
PTYPE DFB 0 ;0=ROM, $FF=RAM
IOBUFF DS IOBSIZ ;comms buffer
***************************************
*
* This block contains the current SET
* parameter values. A TXR may read them
* but should not really change them
* unless it is prepared to do any dependent
* changes involved as well. TXRs *must*
* access values as offsets from (DEFPTR)
* above, as this block may move. The
* offset values will not be changed.
*
* Also here are various odds and ends
* used by the main program - TXRs must
* not tamper with these
*
***************************************
DFBASE EQU *
TXBAUD DFB 0 ;transmit baud rate
RXBAUD DFB 0 ;receive baud rate
ECHO DFB 0 ;local echo
DFB 0 ;obsolete byte (1.03)
DEBUG DFB 0 ;debug mode
DFB 0 ;obsolete byte (1.03)
STIME DFB 0 ;timeout he uses on me
RTIME DFB 0 ;timeout I use on him
TIMER DFB 0 ;whether I do timing
PAUSE DFB 0 ;pause after packet read
DELAY DFB 0 ;delay after SEND command
DFB 0 ;obsolete byte (1.40)
DFB 0 ;obsolete byte (1.40)
CLICK DFB 0 ;keyclick flag
SQUOTE DFB 0 ;quote I will send
CUREBQ DFB 0 ;8 bit prefix I want to use
SEOLN DFB 0 ;EOLN I send to start
REOLN DFB 0 ;EOLN I ask him to send
RPADC DFB 0 ;pad char I ask him to send
RNPAD DFB 0 ;pad char count I ask him to use
SPADC DFB 0 ;pad character I send
SNPAD DFB 0 ;number I send
PARITY DFB 0 ;parity setting
FTYPE DFB 0 ;file type
EORTYP DFB 0 ;type of EOR in use
SOURCE DFB 0 ;source of data (file/memory)
MSBASE DW 0 ;source base for memory
MSTOP DW 0 ;source top for memory
DESTIN DFB 0 ;destination (file/memory)
MDBASE DW 0 ;dest base for memory
MDTOP DW 0 ;dest top for memory
SSOP DFB 0 ;start of packet I will send
RSOP DFB 0 ;start of packet I expect him to send
RMAXL DFB 0 ;max size packet (data + red tape) I want from him
FBPAGES DFB 0 ;size of file buffer in pages
FWARN DFB 0 ;file warning flag
FINCOM DFB 0 ;incomplete file disposition
FLOW DFB 0 ;flow control in use
SUFLEN DFB 0 ;length of file suffix
SUFFIX DS 8 ;file suffix (less the ".")
TKECHO DFB 0 ;TAKE file echo
VDUCOL DFB 0 ;VDU foreground colour
TVFLAG DFB 0 ;flag for doing *TV
TVPAR1 DFB 0 ;first *TV parameter
TVPAR2 DFB 0 ;second *TV parameter
IGNFLG DFB 0 ;flag for VDI ignore in use
IGNCHR DFB 0 ;character to ignore
MUXWT DFB 0 ;MUX wait in byte periods
HLPTRG DFB 0 ;char triggering command autohelp
MAXTRY DFB 0 ;max retries allowed
HSHAKE DFB 0 ;handshake type in use
TTYPE DFB 0 ;terminal type in use
FNTYPE DFB 0 ;file name translation type
DFTOP EQU *
DFSIZE EQU *-DFBASE
OLDIRQ DW 0 ;copy of old IRQ1 vector
EOR DS 2 ;end-of-record bytes in use
FSNUM DFB 0 ;number of filing system at start
FBSIZE DW 0 ;size of buffer
OLDHWM DFB 0 ;setting of OSHWM on entry
STARTUP DFB 0 ;startup flag
***************************************
*
* Space from here to $7FF may be used
* freely by a TXR. Such ROMs should
* allocate space from $7FF down to
* allow for expansion in the tables
* above
*
***************************************
TXBUFF DS MAXPAK ;outgoing packet
RXBUFF DS MAXPAK ;incoming packet
SCBUFF DS MAXPAK ;buffer for building server command
MAXINP EQU 120 ;max length of command line
CMDBUF DS MAXINP ;input buffer
MAXFNL EQU 64 ;max length of filename
FBTOP DW 0 ;buffer high water mark
FBMAX DW 0 ;pointer to byte past buffer
FHAND DFB 0 ;file handle
EOB DFB 0 ;buffer flags
EOF DFB 0
GBPBLK DS 18 ;OSGBPB block for I/O; also OSFILE use
GNXBLK DS 13 ; for directory scan
RFNAME DS MAXFNL ;remote filename
LFNLEN DFB 0 ;size of local name
LFNAME DS MAXFNL ;local name - must follow LFNLEN
LFGIVEN DFB 0 ;flag for explicit local name
WCLEN DFB 0 ;length of wildcarded name
WCNAME DS MAXFNL ;wildcarded name
FSNLEN DFB 0 ;size of name FS allows
IF *>$800
STOP '** Too much workspace **'
FI
DEND
***************************************
*
* This area defines the buffer used for
* terminal mode logging. A TXR may use
* it as it wishes
*
***************************************
DSECT
ORG $A00
LOGBUF DS 256
DEND
CHN BBCMAI