DTJ-BBS Programmer's Information - for Rev. 950307 ------------------------------------------------------------------------------ The information given in this textfile is for the use of programmers who wish to write their own E[X]EC modules and file transfer protocols for the DTJ-BBS. Use this information at your own risk! DTJ Software assumes no responsibility for any damage caused by the use of this information. The information in this textfile is subject to change without notice! ------------------------------------------------------------------------------ This textfile contains a map of memory locations and BASIC variables used by the DTJ-BBS. Although most of the memory locations are not usable by modules you may program, some are, and the rest are included so that you will know which memory locations are used by the BBS. Locations marked for future use should not be used by your program as they may create conflicts in future revisions of the BBS. The list of memory locations and variables may come in handy for use within BASIC expressions in the file server. It is up to you to determine if a variable has any use for this application. This memory map also lists the entry points for the various machine language routines used by the DTJ-BBS. The majority of these routines are NOT intended to be used by your programs. However, there are a couple that you can use, and the use of these routines is described later in this textfile. Please do not use any BBS machine language routines other than the ones described after the memory map! Most routines are subject to change, and may even vary within the same revision under different hardware configurations. Besides the memory locations listed here, the BASIC and Kernal routines also use their own memory locations. The use of them are described in memory map books for the Commodore 64. Locations in the memory map marked with a * may be useful in your modules or within file server BASIC expressions. The following RAM memory locations are not used by the BBS and are free for you to use: Zero page: 02, 92h, 96h, 9B-9Ch, 9E-9Fh, BE-BFh, C1-C4h. Other: 0310-0313h, 032E-032Fh, 0334-033Bh, 03FC-03FFh, 07F8h, 07FD-07FFh, C000-C11Bh. Some of these addresses are listed as used in various Commodore 64 memory maps, but you should be able to use them without causing any problems. The values stored in these locations may be destroyed after your module returns control to the BBS program. You may also use any memory location listed below as used for temporary storage, but remember that values stored in these locations are subject to change after your module has returned control back to the BBS. A BASIC variable list is also given. Most of these variables will not be usable by your program, but they are all listed anyway just to make the listing complete. ------------------------------------------------------------------------------ DTJ-BBS Memory Map (Revision 950307): ------------------------------------------------------------------------------ Simplified (shows RAM under ROM): ------------------------------------------------------------------------------ 0000 - System/BBS RAM variables 0400 - Video Memory 0800 - Complied BASIC code & variables 9A6C - M.L. Module (S.5) (terminal / baudrate tuning functions) A000 - Editor/Protocol/Exec-module buffer B158 - Data Module (S.3) (configuration data) BB4E - M.L. Module (S.4) (editor & fileserver functions) C000 - Buffer areas C15C - M.L. Module (S.2) (init. and main M.L.) D000 - I/O Ports (RAM used by terminal program) E000 - Bases file message pointers F72C - Data Module (S.6) (Awaiting-Call screen / shareware screen) FD15 - Message base tables ------------------------------------------------------------------------------ Detailed Memory Map (shows DTJ-BBS unique addresses only): ------------------------------------------------------------------------------ 0001 - Bank switch port The DTJ-BBS stores the edit buffer, loadable machine language modules, some additional machine language, and the s.3 configuration file under the BASIC ROM. Message pointers and tables, the awaiting- call screen, shareware notice screen, and Kernal ROM NMI routines are stored under the Kernal ROM. The terminal mode routine is stored under the I/O address space. 008B-008C - ACIA base I/O pointer (Swiftlink only). This data points to the location of the Swiftlink ports. 008D - ( for future use ). *008E = Menu-Abort Enable flag Storing a non-zero value here causes all file #2 output (the BBS output channel) to be discarded when there is data in the RS-232 input buffer. This location is zeroed when the BBS requests input from the user. This location is used to impliment the BBS "quick-keys". 008F - ( for future use ). *00A0-00A2 = Jiffy clock - used for protocol timing and timeout checks. 00A5/00A6 - Used by IRQ routine. *00B0/00B1 = Temporary work pointer. *00B2/00B3 = Temporary work pointer. *00FB/00FC = Temporary work pointer. Used by OPEN routine. *00FD/00FE = Temporary work pointer. *02A7 = BBS Input/Output Control. Controls I/O through the BBS I/O channel (file #2). Valid values are: Bit 0 - 0 = ASCII translation off 1 = ASCII translation on Bit 1 - 0 = RS-232 I/O only 1 = RS-232 and console I/O (Both bits zero allows raw RS-232 I/O, otherwise linefeed and xon/xoff flow control are active.) 02A8 - Modem device number. Normally 2, however may be changed to 4 to route output to printer. Since this should only be done on console mode, do not change this location in your modules. 02A9 - Carrier-detect mask. Allows for carrier-detect to be turned on or off. This is used to prevent dropped carrier conditions during console mode while in machine language routines. (BASIC has it's own carrier-detect mask variable.) Valid values are: #$00 - BBS ignores carrier #$10 - BBS detects carrier 02AA - Linefeed flag. A non-zero value will send a linefeed after each #$0D code sent to the modem if the BBS input/output control is non-zero. *02AB = XON/XOFF flag. A non-zero value will pause output via the BBS output channel if the BBS input/output control is non-zero. 02AC - Video width. Current video width (must be between 20 and 140). 02AD - Last key pressed while in file server. Used by BASIC portion of BBS to determine if user [A]borted, [S]kipped, or [N]ext'ed the file output. 02AE - Abort flag. Used by file server. Non-zero value aborts file output. 02AF - Device / Buffer file number. Used by buffer load/save routines and file server. 02B0 - Baud-rate index. #$00 = Swiftlink baud #1 or 300 bps on Kernal RS-232 #$01 = Swiftlink baud #2 or 1200 bps on Kernal RS-232 #$02 = Swiftlink baud #3 or 2400 bps on Kernal RS-232 #$03 = Swiftlink baud #4 only #$04 = Swiftlink baud #5 only #$05 = Swiftlink baud #6 only When the BBS changes the baud, it pokes the baud rate index here, then calls the baud-rate change routine. If the baud-rate value is OR'ed with #$08, then the BBS will always change the baud-rate, otherwise it will only change it if carrier is not present. After returning from the baud-rate change routine, this location contains the current baud-rate index value which can be used to verify if the baud rate was changed. 02B1 - Window flag. If this location is greater than zero, then the BBS will display a blue window at the top of the screen. The number stored here should be the number of characters in the window. (Currently, this number is 80 or 120.) *02B2/02B3 = Maximum number of CBM disk blocks allowed in file upload. 02B4/02B5 - Message number ( Message database routines ). 02B6/02B7 - Oldest message index ( Message database routines ). 02B8/02B9 - New message number ( Message database routines ). 02BA - Room number + #$40 ( Message database routines ). 02BB - Maximum number of rooms ( Message database routines). Must always equal 50! Do not change! 02BC - CONTROL-C mask. #$00 = Disable CONTROL-C detect #$FF = Enable CONTROL-C detect 02BD - RS-232 status register XOR value. 02BE - System Control Block (first 8 switches) Bits are arranged as follows: Bit 0 = CHT Bit 1 = CEN Bit 2 = MON Bit 3 = NEW Bit 4 = PAS Bit 5 = CRE Bit 6 = FUL Bit 7 = SYS 02BF - Printer type. Non-zero value here turns CBM-ASCII translation on for printer. 02C0 - Edit buffer size. Size in 256-byte blocks plus A0h. 02C1-02C6 - Twit detector threshold values. 02C7-02D1 - Twit detector trigger values. 02D2 - Censor mode flag. Indicates to censor routine if censor routine is being called from the file server or the twit detector. If the censor routine is being called from the file server, then any words blanked out will not trigger the twit detector. 02D3 - Censor word counter ( Twit detector ). 02D4 - Minute storage ( IRQ Window routine ). This location is used to make sure the window is updated at least once a minute. 02D5 - Input interrupt flag. This location indicates to the BASIC portion of the BBS if the input routine or file server routine was interrupted abnormally. This occurs when certain function keys or CONTROL-C are pressed, if carrier is dropped, or a timeout error occurs. Valid values are: #$00 = Normal (no interrupt occurred) #$08 = F4 key pressed #$09 = CTRL-C key pressed #$0A = F2 key pressed #$0B = F6 key pressed #$0C = F8 key pressed #$0D = Carrier drop #$0E = Timeout error Appropriate action is taken when control returns to the BASIC portion of the program. 02D6 - Control-key flag. Used when entering control codes via the CTRL-P sequence to tell the BBS not to interpret the code as a command, but to accept it as normal data. 02D7 - Screen echo flag. This location is used to disable screen echo if specified for the current baudrate. (Swiftlink only) 02D8 - Cursor position save. *02D9 - Temporary work space ( File server - working video width ). *02DA - Temporary work space ( File server - current screen column ). *02DB - Temporary work space ( File server - aux buffered text pointer ). *02DC - Temporary work space ( File server - new paragraph flag ). *02DD - Temporary work space ( File server - stack pointer save ). *02DE - Temporary work space ( File server - ANSI-sequence? flag ). *02DF - Temporary work space ( File server - main buffer head pointer ). *02E0 - Temporary work space ( File server - main buffer tail pointer ). *02E1 - Temporary work space ( File server - main buffer wrap pointer ). *02E2 - Temporary work space ( File server - valid wrap loc. found? ). *02E3 - Temporary work space ( File server - center para disable flag ). *02E4 - Temporary work space ( File server - indent position ). *02E5 - Temporary work space ( File server - center flag ). *02E6 - Temporary work space ( File server - current "next" key ). *02E7 - Temporary work space ( File server - current "abort" key ). 02E8 - BBS output - current screen line number. 02E9 - BBS output - user's screen height - 1. 02EA - BBS output - working screen height - 1. *02EB = Temporary work space ( CTRL-P hexadecimal-binary conversion ). *02EC = Temporary work space ( CTRL-P hexadecimal-binary conversion ). *02ED = Temporary work space ( Message database routines ). *02EE/02EF = Temporary work space ( Message database routines ). *02F0/02F1 = Temporary work space ( Message database routines ). *02F2 = Temporary work space ( SYS statement argument value ). *02F3 = Temporary work space ( File server routine ). *02F6 = Temporary work space ( File server routine - last kernal status ). 02F7 - RS-232 interrupt status save. This is used by the pause routine. 02F8-02FA - ( for future use ). *02FC/02FD = Temporary work space ( hours/minutes save / directory blocks free ). 02FF - System Control Block (last 8 switches) Bits are arranged as follows: Bit 0 = ANS Bit 1 = ESC Bit 2 = TWT Bit 3 = ANO Bit 4 = SEE Bit 5 = BAS Bit 6 = SCN Bit 7 = (for future use) 033C - Current drive letter This location stores the ASCII value of the current drive letter. 033D-0354 - Current partition table 24 memory locations, one for each possible physical drive (devices 8-31). Each location contains the ASCII value of the last drive letter that accessed that physical drive. This is used to determine if the kernal overlay should send the command channel string when opening a file. To force the BBS to send the command channel string, set the appropiate location (or all locations) to zero. 0355-035D - 300 bps RS-232 data (Kernal RS-232 only) Data is organized as follows: Bytes 1-4 = Data stored in mock RS-232 control registers Bytes 5-6 = Receiver half-bit time Bytes 7-8 = Transmitter full-bit time 035E-0365 - 1200 bps RS-232 data (Kernal RS-232 only) (See above.) 0366-036D - 2400 bps RS-232 data (Kernal RS-232 only) (See above.) 036E-0373 - Hayes Response Code Table (Swiftlink RS-232 only) Six bytes, one for each possible baudrate. This table contains the response codes that the BBS looks for to determine the baudrate of the incoming call. Setable using program SW-SET. 0374-0379 - ACIA Control Register Table (Swiftlink RS-232 only) Six bytes, one for each possible baudrate. This table contains the value to be stored in the ACIA command register for a particular baudrate. If the high bit is set, then local screen echo is disabled for the baudrate. Setable using program SW-SET. 037A-037F - Baudrate Value Table (Swiftlink RS-232 only) Six bytes, one for each possible baudrate. This table contains the displayed baudrate value for each baudrate. Setable using program SW-SET. 0380 - ANSI graphics enable flag ANSI graphics is enabled for the user if this location is non-zero. 0381-0383 - ( for future use ). 0384-03FB - Window data. These locations contains the data to be displayed in the blue window in the form of screen codes. This data should not be modified since the BBS not only writes to this buffer, but it also reads the data back since some of the BBS's machine language routines may modify the window data. *03FC-03FF = Free RAM. *07F9 = Date Preset flag A value of #$7B here indicates the next three bytes contain a valid date. This and the next three bytes are used when rebooting the BBS with a battery-backed clock calendar. Then during the BBS, the following 2 bytes contain the hour and minute. *07FA = Decimal year (0-99) / current hour *07FB = Decimal month (1-12) / current minute *07FC = Decimal day (1-31) 0800-9E33 - Compiled BASIC portion of BBS & variable area. 9A6C - CHANGE BAUD Enter (S.5 Machine Language Module) This is used to change the serial port baudrate. It can make an unconditional change, or make the change only if there is no carrier. 9A6F - TERMINAL Entry This routine swaps in the terminal mode, runs it, and swaps the terminal mode out before exitting. 9A72 - TOGGLE DTR Entry This is a hardware method of hanging up some modems. 9A75 - TRANSFER TERMINAL MODE IN/OUT Entry The terminal mode routine is located in the RAM under the I/O port area. This routine swaps that RAM (D000) with the RAM at 6000 so the terminal program can be used. 9A78 - OPEN FILE Entry This routine handles the kernal overlay. It is called whenever a file is opened. Use the kernal OPEN vector to open a file. 9A7B - CENSOR Entry This routine clears the censor word count and either blanks out words found or counts the words found. 9A7E - CENSOR Entry (alternate) This does the same thing except it doesn't reset the word count. 9A81 - CENSOR COUNT RESET Entry This resets the censor word count. 9A84 - GET A CHARACTER Entry (for file server) This routine is called by the file server to get a character from a file or the edit buffer. It handles some of the special CMDR codes in the file including resolving the CMDR-B BASIC expressions. 9A87 - CMDR-F PROCESSOR Entry (for file server) This routine is called by the file server whenever a CMDR-F code is detected. It stores the keys and filenames in a 256-byte buffer. It is also used to perform the key test and the actual branching to the new text file. 9A8A-9FE6 - S.5 Machine Language Module *9FE7 = RS-232 status register ( XOR'ed ) The IRQ routine checks the RS-232 status every 1/60th of a second, XOR's the value found there with XOR value (@ 02BDh), and stores the result here. All checks for carrier should be checked here. Carrier is present when bit 4 (value = 10h) is 0. Carrier should be checked as follows: lda $9fe7 ; get rs-232 status and #$10 ; mask all bits except carrier and $02a9 ; mask with carrier-detect mask bne -no carrier- -carrier- *A000-B157 = Editor, File copier, Module buffer Location $A000 normally contains a #$0D (CR), followed by the edit buffer text, with a NULL byte used as an EOT character. The BBS's file copier and loadable machine language modules will overwrite any edit buffer text. If the edit buffer text is over- written, then the BBS will clear the edit buffer before the next COMMAND prompt so that the user will not see any garbage characters in the buffer. B158-BB4D - S.3 configuration file buffer Contains the censor vocabulary, a NULL, Kernal overlay (each entry followed by a NULL), and the editable phrases (each entry followed by a NULL). BB4E - EDITOR/FILE SERVER Entry. All machine language functions of the editor (writing, listing, editting, loading and saving), as well as the file server routine (used to display all text from disk such as messages, email, SIGfiles, etc), are called through this location. BB51 - CENSOR Entry. This is BASIC's entry into the censor routine. This entry is used by the twit detector. It jumps directly to the CENSOR entry in the S.5 module. BB54-BFFF - S.4 Machine Language Module *C000-C11B = Temporary storage buffers. This area is used by the BBS as buffers for the editor search and replace routines, list routines, and the BBS line editor. This area may be used by modules in any manner. There is enough room here for one 256-byte or two 128-byte file transfer buffers. You can also use it to store short machine language routines such as a routine to switch in the BASIC ROM temporarily, call a subroutine, and switch BASIC back out. C11C-C15B - Censor vocabulary index (allows for up to 64 entries). This index is used to help speed things up for the nasty-word- checker. It contains the length of each word in the vocabulary. C15C - DTJ M.L. INIT This initializes the machine language portions of the BBS, changing kernal vectors, etc. It is only used when the BBS is first loaded. Do not use this location because it may be used for other things in the future. C15F - EDITOR/FILE SERVER Setup Entry. Switches BASIC out and jumps to BB4E (EDITOR/FILE SERVER in the s.4 module). C162 - INTERRUPT CHECKER Entry. Also called by the LINE EDITOR routine. It checks to see if the key last pressed or the character last received is a BBS interrupt character (i.e. CTRL-C, a function key, CMDR-status-change etc). It also checks for carrier drops. It the key is, it either processes the key and returns with carry clear, or it sets carry and then returns. Carry set indicates that the calling routine should return to BASIC so that the BASIC portion of the BBS can process the interrupt key. C165 - DIRECTORY READER Entry Displays disk directory. The directory file must be open and BASIC must be switched in. Mem-loc (02F2) = #$00 - Normal disk directory format = #$01 - SIGfile disk directory format C168 - STACK RESET Entry Used to reset the stack (clear off all GOSUB return addresses) at COMMAND prompts. Do not use! C16B - DISPLAY OFF-LINE SCREEN Entry. Displays the background for awaiting-call screen. C16E - DISPLAY SHAREWARE SCREEN Entry. Displays the shareware screen (SHIFT/CTRL screen). C171 - DISPLAY S.3 FILE EDITABLE PHRASE Entry. This routine displays data indicated in the S.3 editable phrases. It displays the text, displays a file, or runs a module. C174 - NON-CASE-SENSITIVE STRING COMPARE Entry. Compares two string variables. This routine compares only characters up to the length of the second string. C177 - FILE-COPIER DISK READ Entry. Reads blocks into the edit buffer. C17A - DISK LINE-INPUT Entry. Used to input a string into one or more variables. Similar to LINE INPUT in other BASICs. *C17D = GET CHARACTER Entry. All BBS inputs use this routine to accept data from the user. This routine calls the INTERRUPT CHECKER and will return with carry set if an interrupt request occurs due to carrier drop, CTRL-C, and certain function keys are pressed. Modules using GET CHARACTER should exit as soon as possible so that the BBS can process the interrupt. C180 - GARBAGE COLLECTOR Entry. This routine erases certain string variables to provide for a faster garbage collection. Garbage collection occurs before the COMMAND prompt. C183 - FILE-COPIER DISK WRITE Entry. Writes disk block info from the edit buffer to the disk. C186 - DISPLAY-TRANSLATE Entry. Used internally to map some of the ASCII codes to their closest CBM-ASCII visual equivalent. C189 - SKIP BAM Entry. Used to skip the BAM entry when reading a track & sector directory. C18C - KILL ROOM Entry. Replaces all occurances of a specific room code in the message index with a different code. Used to clear all messages from a room. C18F - FIND INDEX FROM MESSAGE NUMBER Entry Finds the position in the message index of the message number given based on what the current room is. C192 - SET UP ROOM Entry Finds information about room. C195 - ROOM HOUSEKEEPING Entry Checks for unused rooms and deletes them. C198 - MESSAGE-INDEX LOAD Loads the message index from the BASES file into memory. C19B - MESSAGE-INDEX SAVE Saves the message index from memory to the BASES file. C19E - ROOM SORT Creates a sorting index for the sig/room list. C1A1 - INTERNAL ROOM DATA TABLE SETUP This routine sets up tables which contain statistics about each room's messages. C1A4 - FIND PHRASE This routine finds an editable phrase entry in the S.3 file data. C1A7 - DISPLAY WINDOW This routine displays the window data. It is called by the IRQ routine when the IRQ routine and by BASIC. C1AA-CFFF - S.2 Machine Language Module *DC08-DC0B = TOD Clock #1 - Used for time-of-day. *DD08-DD0B = TOD Clock #2 - Used for user's session timer E000-EDAB - Message index. Each position indicates the room number + #$40 of each message. F72C-FD01 - S.6 Module This contains the awaiting-call and shareware screens; each are NUL terminated. FD15-FD46 - New Message Pointers (low bytes) FD47-FD78 - New Message Pointers (hi bytes) These locations contain pointers to the newest messages that the user has read for each room. These pointers are used to compute the number of old and new messages the user has. FD79-FDAA - Number of Messages (low bytes) FDAB-FDDC - Number of Messages (hi bytes) These locations contain the number of messages in each room. When the user enters a different room, a machine language routine looks up the number and stores it at $02EE/02EF. FDDD-FE0E - Number of Old Messages (low bytes) FE0F-FE40 - Number of Old Messages (hi bytes) These locations contain the number of old messages in each room. When the user enters a different room, a machine language routine looks up the number, adds 1 to it (so it becomes the message number of the first new message), and stores it at $02B8/02B9. (All other RAM under the Kernal ROM is and must remain a copy of the Kernal ROM. This allows for the use of the NMI interrupt routines when the ROM is switched out.) ------------------------------------------------------------------------------ The following ROM vectors have been changed: 0308/0309 - IGONE - To allow execution of BASIC extensions. 0314/0315 - IRQ - To enable the BBS window and carrier-detect routines. 0318/0319 - NMI - To lessen the chance of locking up the computer if the RESTORE key is pressed, and also to display the diagnostic screen with RUN/STOP & RESTORE. Also handles Swiftlink NMI routines if Swiftlink is active. *031A/031B = OPEN - To enable the kernal overlay. *031E/031F = CHKIN - To allow the use of device 4 to read the edit buffer. Used only by the file server when listing the edit buffer. *0320/0321 = CHKOUT - To handle the proper channel number for the BBS output channel depending on the carrier mask. *0326/0327 = CHROUT - BBS output driver. Handles all modem/display output. *032A/032B = GETIN - BBS input driver. Handles all modem/keyboard input. (BBS does not use CHRIN for keyboard or RS-232 input!) Please do not change any vectors! ------------------------------------------------------------------------------ BASIC Variable Listing: ------------------------------------------------------------------------------ You may find variables marked with an * useful in your own modules or in BASIC expressions in the file server. (Since the BASIC ROM is switched out when executing a module, you must devise your own routine for accessing variables if you need to.) a - Constant = 56577 a$ - Temp - Hayes command to send a% - Account - SIG-bulletin read flags aa - Temp aa$ - Account - Access ac - Account - Number of calls ad - Account - Number of downloads ad$ - Account - Date of last call ae - Editor mode flag (used to determine where editor is called from) af - Account - Email forwarding account number ah$ - Account - New message pointers (encoded) ai - Account - Number of messages posted (system total) al - Account - Number of bad logoffs. am - Account - Number of messages posted (user's total) an$ - Account - Name an% - Account - Saved messages as old or new flag ap - PM-to-AM tracker (used for midnight housekeeping). ap$ - Account - Password *ar% - Fileserver auto-return flag as$ - Account - Status at - Account - Daily time limit at% - Account - Time used today (previous sessions only) au - Account - Number of uploads av - Account - Video Width ax - Temp ax$ - Account - Protocol b - Baudrate value / Temp b$ - Temp *b$(*) = Room Name Array (Valid index is 1 to 50. Unused rooms are null.) *b%(*) = Room Status Array (Valid index is 1 to 50. The value returned is as follows: bits 0-3 = SIG room is assigned to (0 means room not in use), bit 4 = bit 5 = Logoff message room flag, bit 6 = Read-only flag, bit 7 = Locked room flag, bit 8 = Anonymous room flag. Note that an unused room may be locked so that it cannot be created.) *bn = Current room index number (Valid number is 1 to 50. 0 means user is not in a room.) c$ - Last command sequence entered. c% - carrier XOR value ca - Carrier status (used in CHAT mode) cc - Carrier Detect Bit Mask cm - Command-entered flag (other than chat or download) *cm% - number of remaining buffered commands *cn = Number of calls received. cr$ - Constant - CHR$(13) d - Temp - Drive d$ - Temp - Date string (includes day of week) *d$(*) = SIG Bulletin Date-last-modified Array (String in YYMMDD format.) *d% = User - SIG-bulletin read flags (Each bit represents a SIG bulletin that the user has read.) *d%(*) = Message/drive Allocation Array (Valid index is 0 to 25 for drives a to z. Each entry indicates the number of messages on that drive.) db - Default baudrate *dd = Day Of Month (Between 1 and 7, starting at Friday.) dn - (for future use) *dw = Day Of Week (1 to 31.) e - Temp - DOS Error Number e$ - Temp *e%(*) = Email Type/Receiver Data Array (Valid index from 1 to variable me. Value is account number plus 1024 if certified, plus 3072 if urgent. 0 indicates an available email slot.) e2$ - Temp - DOS Error Channel Buffer ed - *ed(*) = Email Date-sent Array (Valid index from 1 to variable me. Value is date in YYYYMMDD format. 0 indicates an available email slot.) en$ - Constant = "Enter " eu - Email Account to Read f$ - Temp - Filename f0 - (for future use) f1$ - Temp - Filename f1 - (for future use) f2$ - Temp - Filename f2 - (for future use) f3 - (for future use) f4 - (for future use) *fa = First Available Account Number fd - Last Message Editted (Either drive or base index number) fr$ - Temp - name & account number of user posting message g$ - Temp - Current SIG Letter h$ - Hayes Escape Sequence ASCII Character (The character must be sent 3 times for the Hayes escape sequence.) hi - Index to Next Message to Save (Used to determine the start/end points of the message index buffer. This is a pointer to the next message to be saved. It also points to the oldest message in the system once the messages have started cycling.) *hl = Max number of messages BBS configured to handle i - Temp i$ - Temp - Line Editor Input String i1 - Temp i2 - Temp i3 - Temp id - File Server & Editor Interrupt Type ii$ - Temp - Line Editor Input String (Uppercase) j - Temp j$ - Temp - Window Builder k$ - Constant = "------" l - Temp - Line Editor Maximum Length l$ - Temp lb$ - Constant = ":a.LOGBOOK" *lc$ = Last Caller's Name *lg = Logoff Messages Available flag (Any non-zero value means logoff messages are available.) lm$ - Constant = ":e-sys" ls - Temp lt - LtKernal ROM flag (Any non-zero value indicates the presence of a LtKernal hard drive. This was for future use of LtKernal hard drives but will probably never be implimented.) m$ - Constant - CHR$(13) m0$ - Hayes BBS Initialization Sequence (Each command sent is separated with a space.) m1$ - Hayes Terminal Initialization Sequence (Each command sent is separated with a space.) m2$ - Hayes Hangup Sequence (Hayes command to send after sending the escape sequence.) m3$ - Hayes Modem Off-hook Sequence *me = Maximum pieces of email BBS can handle *mm = Month (1 to 12. 0 indicates BBS is disabled.) *mn = Number Of Messages In Room *mp = Number Of Messages Posted (This is the system total. Variable hi is derived from this variable.) ms$ - Constant = "essage" n$ n% - User - Saved messages as old or new flag (Any non-zero value will make saved messages as new.) n%(*) - User - New message pointers (Valid index is 1 to 50 representing room numbers. Each array element is a pointer to the last message read in the room. This array in conjunction with variables mp and ui tell the BBS which messages are new.) na$ - Constant = "NNNNNNNNNNNNNN" (used to check for minimum access) nb - Message Number *nm = Number Of New Messages In Room (If 0, then room is empty.) nm$ - New User Questionaire Name Prompt (i.e. "Name:", "Handle:", etc.) ny$ - Constant - "Anonymous" o$ - Constant - CHR$(0) p$ - Constant - "ress RETURN" ps - Message Index q - Temp q$ - Temp *q$(*) = Buffered commands / Answers to Questionaire / Room/SIG info (This array contains buffered commands when the CM% variable is set. Otherwise, at the COMMAND prompt, the following formatted data exists: Q$(0) = Current room name, Q$(1) = Number of new messages in room, Q$(2) = Current SIG name, Q$(3) = Number of messages in room. Data is padded with spaces.) q0 - Temp - Current Question Pointer qa$(*) - Buffered command arguments / New User Questionaire qb%(*) - Maximum Number of Characters Allowed in Questionaire qq - Number of Questions in Questionaire r - Constant = 50 (Maximum Number of Rooms - do NOT change) r$ - Temp r1 - Temp - Starting Message in Sequence r2 - Temp - Ending Message in Sequence rd - Disable remote-enable flag (i.e. date = "999999"). re - Temp *rt$ - Name of RETURN key (If the current video width is 40 or less, this variable contains the text "RETURN", otherwise it contains "ENTER".) s$ - Room/SIG Sort Index *s$(*) = SIG Name Array (Valid index is 0 to 14. This array contains the names of each SIG. A null signame is a hidden ("deleted") SIG. *s1 = Default Video Width (Valid video width is 20 to 80. Please do not exceed this range.) s1$ - Recovery Password (Used for remote enabling.) *s2 = Maximum Number of Users (Valid number is from 1 to 999. Do not exceed 999.) s2$ - New User Access *s3 = Default Time Limit (Default daily time limit.) s3$ - Unlogged-on User Access s4 - Account drive (ASCII value of drive letter.) s5 - Email drive (ASCII value of drive letter.) s6$ - SIG Download drives (15 drive letters.) s8 - Current upload drive (ASCII value of drive letter.) s8$ - SIG Upload drives (15 drive letters.) s9 - Modem type (1 = 1650 or compatable, 2 = 1670/Hayes or compatable, 3 = 1660 or compatable.) sc$ - Constant = "CHTCENMONNEWPASCREFULSYSANSESCTWTANOSEE---------" sf - Logoff Message drive (ASCII value of drive letter.) sl - Logoff Message room (Contains the room number of the room that logoff messages are to be saved to. Logoff messages are saved to "e.sys" file if this variable is 0. The BBS scans the room status array and stores the appropriate value here.) sk - Save KEEP flag sn - (for future use) *sp$ = 80 spaces (used for padding) su - (for future use) t - Temp / Number of tries left / Logoff type t0 - Temp t1 - Temp *t2 = User - Time Online Today (Total) (Current amount of time, in minutes, that the user has been online today. Used in conjunction with variable ud$ (to determine if user has been online today or if user's timelimit can be reset).) t3 - Temp t4 - Temp t9 - Temp *tw = User - Twit Level (Valid range between 0 and 255.) *u = User - Account Number (Valid range between 0 and 999. If zero, then user is not logged on.) u$ - "Sysop" or "SIGop" (Displayed when [.] command is selected.) *ua = Access level in current room (Current access value derived from variables ua$ and b(bn). 1 = No access, 2 = Read-only access, 3 = Write access, 4 = Create access, 5 = SIGop access.) *ua$ = User - Access *uc = User - Number of calls *ud = User - Number of downloads *ud$ = User - Date last called (Date in YYMMDD format. Used in conjunction with array n .) *uf = User - Email forwarding account number (Valid range between 0 and 999.) *ui = User - Number of messages posted at last call (system total) (Contains value of variable mp at time of user's last logoff. Used to determine if all messages are new.) *ul = User - Number of bad logoffs. *um = User - Number of messages posted (user's total) *un$ = User - Name *up$ = User - Password *us$ = User - Status *ut = User - Daily Time Limit *ut% = User - Time Used Today (previous sessions only) (Contains the value of variable t2 at time of user's last logoff.) *uu = User - Number of uploads *ux$ = User - Protocol (Must contain the name of a protocol, even if protocol does not exist.) w% - Temp - number of bytes displayed in window x - Temp - Disk Space Available *x$ = Date and Time / Temp / Room access for current room (Date and time in format "YYMMDD at HH:MM?M" except during the [G]oto command's room list, in which case it is the user's access to the current room (a single letter)). xm$ - Last Message Editted (Filename of message) *yy = Year (Valid range is 0 to 99. Any value less than 81 is in the 21st century.) z$ - Temp zr$ - Constant = "000000" (used to check if BBS disabled) If the BBS crashes with an error, or does a warm start, you may display the value of any variable with the PRINT command. ------------------------------------------------------------------------------ Accessing BASIC Variables & Memory Locations From The File Server As mentioned in the main BBS documentation, the CMDR-B code allows the display of almost any BASIC expression. This can include simple variable names or complex equations and string functions. To display any variable, memory location, or expression, enclose the variable name, PEEK statement, or expression within CMDR-B codes within the message or text file. For example, to display the current user's name, which is stored in the variable UN$, insert the following in the file whereever you want the name to appear: [CMDR-B] u n $ [CMDR-B] Examine the file "statistics" that comes with the BBS for more complicated examples using expressions. The BBS processes the CMDR-B code before the other CMDR codes. This allows you to use a CMDR-B expression as an "argument" to a CMDR-F file menu/jump code. For example, if you want to have separate 40 column and 80 column versions of the same file, you can use the contents of memory location 02AC (decimal 684) to tell the BBS which file to display. Heres an example of how to do this with a SIG bulletin for the first SIG. Assume that the SIG bulletin is on drive A and it is formatted to be displayed on a 40 column screen. Another file called a.BULL80, located on the same drive, is an 80 column version of the SIG bulletin. All you would need to do is put the following line at the beginning of the main SIG bulletin file (filename: a.BULLETIN): [CMDR-F][CMDR-B]CHR$(42-(peek(684)<80))[CMDR-B]a/a.BULL80 Here's how it works: The first thing the BBS does is process the expression in between the CMDR-B codes. The expression is: CHR$(42-(peek(684)<80)) This BASIC expression converts to '*' if the video width is 80 or more. Otherwise it converts to '+'. So, if the video width is 80 or more, then the original line will resolve to: [CMDR-F]*a/a.BULL80 which will display the file a.BULL80 on drive A. (The '*' tells the BBS to branch immediately to the file.) Otherwise the original line will resolve to: [CMDR-F]+a/a.BULL80 This doesn't do anything except set up a file jump entry that will allow the user to display the a.BULL80 file if he presses '+'. Normally you wouldn't want to display this option in the text of the file so the user won't know it is there. By changing the (peek(684)<80) to (peek(896)<>1), you can use this same technique to switch to a different file if the user has selected ANSI mode. This allows you to have special ANSI graphics screens for users who can display them. With the 941002 version of the BBS, you can now modify variables and memory locations from within any textfile. I was hesitant to add this feature because it can be dangerous. You can corrupt the BBS memory and even "bases" file. I added it anyway because I thought the advantages outweighed the disadvantages. To disable the feature, set the BAS switch to off. To modify a variable, use a standard BASIC "LET" statement within the CMDR-B codes. (The expression must start with "LET" for this to work.) To modify a memory location, use the BASIC "POKE" statement. For example, to change a user's daily time limit to 120 minutes: [CMDR-B] l e t u t = 1 2 0 [CMDR-B] You can use this new feature however you want. Just be careful with it! A new undocumented feature allows you to store a list of BBS commands in an array from within a text file and the BBS will process them the next time it goes to the COMMAND prompt. You can use this feature to create more user- friendly download menus, where a user can select a file by pressing a key and the BBS will automatically go into download mode. While the BBS is processing the stored commands, it will not display the COMMAND prompt. To store commands, use the [CMDR-B] LET [CMDR-B] technique to store the lowercase command keystrokes into the Q$() array with any arguments in the QA$() array. The commands should be stored in reverse order... the last command goes into Q$(0). Then store the number of commands into the CM% variable. Only one LET or POKE statement is allowed enclosed in the CMDR-B codes. For example, if you want to store the following commands: [R]ead [X]fer FILE.TXT [T]erminate Then use the following LET statements in your file (enclosed in CMDR-B codes): LET Q$(1)="rt" LET QA$(1)="FILE.TXT" LET Q$(0)="t" LET QA$(0)="" LET CM%=2 Most commands, including sysop commands, are available using this method, even if the user is not a sysop. (Since non-sysop users cannot enter the CMDR-B code in a file, the BBS is still secure.) However, the [G]oto room-list command and [L]ogon new-user command also use the Q$() array so don't use those commands. The main limitation of this is that it only works for commands available at the main COMMAND prompt. If a command sends the BBS to another prompt (i.e. the editor, account editor, DOS shell, etc), then the user has to take it from there. Another new undocumented feature allows you to display a file after the current file is finished being displayed. If you want to display a textfile immediately after the current textfile is finished, then load the drive/filename into the I$ variable and set AR% to 1. Note that when the BBS branches to a different file using the CMDR-F code (also described in the documentation), the BBS treats the different file as a continuation of the original. This allows you to use one file as a menu to select one or more textfiles for viewing and when those textfiles are finished viewing, the BBS can return back to the menu file automatically. Here's is a sample menu file that can display two other files: [CMDR-B]left$("(paused)[CMDR-P]",10*ar%)[CMDR-B] [CMDR-F]1b/file1.txt [CMDR-F]2a/file2.txt [CMDR-B]leti$="a/menu"[CMDR-B][CMDR-B]letar%=1[CMDR-B] [Clear-screen]File Menu: (1) Display file1.txt (2) Display file2.txt Press key or RETURN to exit.[CMDR-P][Clear-screen] [CMDR-B]letar%=0[CMDR-B] The first line is used to pause the BBS after one of the file is display and before the menu file is redisplayed. This is to give the user a chance to finish reading before the menu file clears the screen. If you leave the clear-screen code out (5th line down), then you don't have to have this line. The next two lines set up the keys used to display the files. These lines are described in the BBS documentation for the CMDR-F code. The next line stores the drive/filename of the menu file into the I$ variable and set the AR% variable to 1. This tells the BBS to redisplay this menu file after it is finished displaying one of the other files. Notice that you can include more than one CMDR-B expression on the same line. Next is the menu itself as displayed to the user. The CMDR-P code near the end of the file is where the menu pauses, waiting for the user to select a file to display. After the user presses a key, the screen will be cleared. (After the user presses a key, the BBS will continue displaying the rest of the line after the CMDR-P code, then it will process the keystroke.) If the user presses (1) or (2), the BBS will immediately branch to the appropriate file. It will not process the last line of the menu file. If the user presses any other key, the BBS will not branch to another file but it will process the last line of the menu file. This last line clears the AR% variable so that the menu file will not be redisplayed. You can get really complicated with this technique by using an array such as Q$() to hold a series of filenames to return to. Once you figure out how to do it, you can create nested menus or even a hypertext database. ------------------------------------------------------------------------------ Module Programming Guide: Module files are small machine language programs that your can run from the DTJ-BBS. They may be given any filename if you intend to run them from an s.3 file phrase. But if you want to run them by using the E[X]ec command, then they must be located on a SIG-file drive and the filename must consist of the SIGletter, a percent sign, and the name of the module in uppercase letters i.e. "a%VOTE". The BBS will load a module of any sequential file type (PRG, SEQ, or USR). Modules can be run online by using the command E[X]ec: at the COMMAND prompt. By leaving out the modulename, a description file will be displayed. The filename of this file consists of only the SIG letter and a percent sign. This file should be located on the SIGfile drive and it should contain a list of available modules. When writing modules for the DTJ-BBS, you should observe the following guidelines: 1. To help maintain compatability with future revisions of the DTJ-BBS, try not to read or modify any memory locations mentioned in the memory map except for the ones label "Temporary work space", "Temporary work pointer", or those memory locations mentioned below. If the memory locations other than the temporary locations are changed, they must be restored to their original values upon exiting the module. You may also find reading variables marked with a * useful. 2. The BBS keeps the following file channels open at all times: #2 = BBS Input/Output Channel #4 = Printer Output/Edit-Buffer Input Notice that the printer channel is open even when it is not being used. Do not close these files! All other file numbers are available for your use. However, if you open a file, close it before exiting your module. 3. Modules are loaded into the edit buffer memory. Modules must load and execute at $A001. Module size may be larger than the configured size of the edit buffer (in the s.1 file), but it may not exceed the maximum size of the edit buffer (4095 bytes). Since modules are located under BASIC ROM, you cannot access any BASIC ROM routines without branching out from under the BASIC ROM and then switching the BASIC ROM in temporarily. All modules must exit with an RTS instruction. 4. Use the documented Kernal ROM vectors as much as possible. This applies especially to the RS-232 I/O routines. 5. Any disk access should open files using device numbers cooresponding to the ASCII values of the drive letters (A=65, B=66, etc). Once the file has been open, the BBS's kernal overlay will convert the logical drive number into a physical device number so that location $BA will contain the actual device number as it usually does. 6. The software Jiffy clock values may be changed and do not have to be restored when returning control to the BBS. 7. Do not turn interrupts off, or modify interrupt routines. The BBS uses the IRQ routine to display the window at the top of the screen and to check for carrier. The NMI routine is used for RS-232 communications. 8. To prevent lockup problems, always check for carrier in all loops that do not exit in a short period of time. Carrier may be checked by calling the following subroutine: carrier ; get rs-232 status. lda $9fe7 ; mask all bits except the carrier bit. and #$10 ; mask result with carrier-detect mask (force carrier if in ; console mode). since doing a file transfer while in console ; mode is useless (rs-232 i/o is disabled), leave this instruction ; out if you are writing a protocol module. and $02a9 ; exit subroutine. rts This subroutine will return zero set (register A=0) if carrier is present, or zero cleared (register A=16) if carrier is not present. If carrier is not present, the module should close all files and exit. The BBS will then handle the carrier-drop. Do not check carrier at location $DD01 as some modems/interfaces may use reverse carrier and also this location is not used with the Swiftlink-232 cartridge. 9. The DTJ-BBS does not use a full 256-byte RS-232 output buffer. This is to help prevent garbling problems with the software RS-232 routines. The Swiftlink mode also does not use an output buffer. This keeps the NMI routine as short as possible and allows for more compatablity with the software RS-232 routines. The full 256-byte input buffer is used however, with both software and Swiftlink RS-232 modes. Please do not manipulate the I/O buffers directly. Use the Kernal I/O routines. 10. The Swiftlink's receiver section is disabled during all serial port access to prevent serial port timing problems. The receiver is enabled via the Kernal CLRCHN routine. Always remember to call CLRCHN after a disk access if you want to be able to receive characters from the modem. 11. The Swiftlink NMI routine stores bits 0 through 3 of the status register to location $0297 so you can use this location as you would normally. Location $02A1 is not used in Swiftlink mode. 12. Use GETIN, not CHKIN, for all file #2 (modem/keyboard) input. 13. You may find the BASIC variables listed above with a * after the variable name useful. Since the BASIC ROM is switched out, you will have to devise your own method of access the variable you want to use. Variable positions may vary so you should always search for a variable by name. Do not assume that a given variable will always be in the same location in the variable area in future revisions. In most cases, you should not change the value of a variable. 14. Do not call BASIC's random number generator. The memory location used to store the seed value is being used for other purposes. ------------------------------------------------------------------------------ Protocol Module Programming Guide: Protocol files are a more specialized form of module. The filename of a protocol module consists of "p-" followed by the protocol name in uppercase letters. These files are located on drive A. In addition to the above guidelines, the following applies to protocol files: 15. The DTJ-BBS opens the file to be received or sent before calling the protocol module routine. The file number is 8. The command channel is also open using file number 1. (In the future, this will change if/when multi-file transfers are implimented. File 8 will be a PRG-format directory file and file 1 will be closed. The loading address may change to $A000 or $A002 to force incompatability with the old modules. This is to prevent problems with running multi-file transfers on an older BBS that can't handle them.) 16. The protocol module must contain both send and receive routines. The receive routine must start at $A001 and the send routine must start at $A004. 17. Unless the protocol is an ASCII transfer, both the send and receive routines must turn ASCII translation off. Echo should also be turned off. Make sure you turn translation and echo back on when the transfer is finished. Translation and echo control is at $02A7. 18. Both send and receive routines use the A register to indicate the success of the transfer upon exiting the module: #$00 = file transfer complete - no error #$01 = error - timeout #$02 = error - cancelled by user #$03 = error - cancelled by sysop #$04 = error - other (unused) #$05 = error - disk full #$10 = error - carrier drop Any non-zero status on a file receive will cause the BBS to scratch the file. Note that the routine described earlier to check for carrier will set A to #$10 for you if carrier is dropped. Remember to leave the "and $02a9" instruction out of your carrier detect routine when writing a protocol module. 19. Make sure you check for carrier and impliment timeouts in all loops to prevent too much idle time being wasted. 20. Use the software jiffy clock for timing. 21. Try not to buffer too many blocks in memory at a time. Alot of file transfer protocols written for the Commodore buffer up to 16 blocks or more in memory before writing to disk or sending to the modem. This slows down the file transfer. Instead, when sending data, read one or two blocks of data from the disk as you need it. When receiving data, write it to disk as soon as it has been verified correct. 22. Your protocol module should display the status of the transfer on the screen as it goes. Try not to use the whole screen. At a minimum, you should display the number of blocks sent or received. 23. Provide some way for the sysop and user to abort the transfer. A CONTROL-X would conform to the original DTJ xmodem's way of aborting the transfer. If you think a CONTROL-X is too easy to abort the transfer by accident, then try two CONTROL-X's in a row within a limitted amount of time. Remember to set register A to the appropriate value when exiting. 24. The maximum number of 254-byte disk blocks that can be saved to disk when receiving a file is stored at locations $02B2 and $02B3 (in low/high byte order). Exceeding this limit by about 12 blocks may result in a corrupted disk. (12 blocks was chosen to provide a safety zone.) The protocol should abort when this limit has been reached. Before the transfer begins, you can multiply or divide this memory location to get the number of file transfer blocks (i.e. multiply by 2 to get the approximate number of 128- byte xmodem blocks). 25. When the transfer is complete, you should close files 8 and 1. If the transfer was not a success, you don't have to delete the file. The BBS will do that for you if the protocol module exits with the A register holding a non-zero value. ------------------------------------------------------------------------------ Module Programming Examples: ; ---------------------------------------------------------------------------- ; Turning ASCII translation and screen echo off and on. (Used when ; writing a file transfer protocol.) lda $02A7 ; get current BBS I/O status pha ; save it on stack for later restoral lda #$00 ; value to turn translation and echo off sta $02A7 ; store back into BBS I/O status sta $008E ; turn "quick-keys" off. : ; your code goes here pla ; restore old BBS I/O status sta $02A7 ; ; The BBS will restore the value of $008E when it exits the module; you don't ; have to save it. ; ---------------------------------------------------------------------------- ; Getting typed-in input from a user. (Used when writing an interactive ; module such as a voting booth, questionaire, etc.) buffer = $C000 _GETCHAR = $C17D CLRCHN = $FFCC CHKIN = $FFC6 CHKOUT = $FFC9 CHROUT = $FFD2 UINPUT jsr CLRCHN ; clear I/O channels if needed ldx #$02 ; setup BBS I/O jsr CHKIN ldx #$02 jsr CHKOUT ldy #$00 ; reset buffer pointer LOOP jsr _GETCHAR ; get a character from the user bcs EXIT ; exit module if carry is set cmp #$0D ; RETURN key? beq CR ; exit input routine if yes cmp #$14 ; DEL key? beq DEL cmp #$20 ; invalid control character? bcc LOOP ; ignore and get another character if yes cpy #40 ; 40 characters entered already? (You may change ; this value if desired.) bcs LOOP ; ignore and get another character if yes jsr CHROUT ; echo character to user sta buffer,y ; store character in input buffer iny ; increment buffer pointer bne LOOP ; get another character DEL cpy 0 ; is buffer empty? beq LOOP ; ingore and get another character if yes jsr CHROUT ; echo DEL character to user dey ; decrement buffer pointer bpl LOOP ; get another character CR jsr CHROUT ; echo carriage return to user lda #$00 ; store a null after buffer characters (optional) sta buffer,y EXIT rts ; exit input subroutine ; This subroutine assumes BBS I/O control ($02A7) is set for translation and ; echo on. "buffer" points to an area of memory sufficiently large enough ; to contain all the characters the user can type in. Upon exiting this ; subroutine, register A contains #$0D, Y contains the number of characters ; typed in, and the characters themselves are stored at "buffer". If this ; subroutine exits with carry set, then you should exit the module as soon ; as possible. Note that calls to _GETCHAR will reset the jiffy clock. If ; carrier is dropped while in this routine, carry will be set, so there is ; no need to add carrier detect to this routine. This routine will also ; handle all standard console interrupts such as sysop-page, C= status ; change, etc if you exit your module when this routine returns with carrier ; set. ; ---------------------------------------------------------------------------- ; Getting the value of a string variable. (Used when you want to use or ; display the value of a BASIC string variable such as the date, user's name, ; etc.) adrs = $0019 ; Used to store address of string data var = $0021 ; Used to store address of variable descriptor length = $0023 ; Used to store length of string data FINDVAR pla ; get address of jsr instruction used to call this sta adrs ; this subroutine (variable name is stored pla ; immediately after the jsr instruction) sta adrs+1 inc adrs bne FV00 inc adrs+1 FV00 lda #$02 ; set up jmp instruction at end of this subroutine clc ; to jump back into the calling routine just after adc adrs ; the variable name sta JUMP lda #$00 adc adrs+1 sta JUMP+1 lda $2d ; find start of variable storage area sta var lda $2e sta var+1 FV01 ldy #$00 ; (var) pointing to desired variable? lda (var),y cmp (adrs),y bne FV02 iny lda (var),y eor #$80 cmp (adrs),y beq FV03 ; jump if variable found FV02 lda #$07 ; otherwise go to next variable clc adc var sta var bcc FV01 inc var+1 bne FV01 FV03 ldy #$02 ; variable found (var points to variable name lda (var),y ; in variable table sta (length) ; store length iny lda (var),y sta adrs ; store address iny lda (var),y sta adrs+1 jmp ; return to calling routine JUMP $0000 ; This subroutine must be called with the name of the variable stored in ; the two bytes following the jsr statement. The variable name must start ; with a lowercase letter, and end with a lowercase letter, a digit, or a ; space. The variable must already exist, otherwise the routine will lockup. ; Upon exiting, "var" points to the variable name in the variable table, ; "length" contains the number of characters in the string variable, and ; "adrs" points to the first character of the string. Registers A and Y are ; modified. ; If you wish to read a numeric variable, you must devise your own method ; of using the floating point information in the variable. Once you devise ; a way to access the BASIC ROM, you can use the Integer/Floating Point ; conversion routines available through vectors $3/$4 and $5/$6. ; You can also try switching in BASIC at times when you need to. Just ; remember not to switch BASIC in while you are still under the BASIC ROM. ; One method to do this would be to copy a short machine language subroutine ; to $C000 that switches in the BASIC ROM, does whatever it need to do with ; with the BASIC ROM, switches the BASIC ROM out, and then RETurns back to ; the main module code. This is the way the calculator module works.