VSYS JBBS is a bulletin board system (BBS) program designed to run unattended, accepting incoming modem calls and allowing remote callers to read and leave messages, chat with the SYSOP, view system information, and switch between up to four message bases. The system stores up to 20 messages per base in a 20×1000-character string array, with messages bounded by a CHR$ 3 end-of-message sentinel, and persists data to Microdrive cartridges using named file saves and loads. Three blocks of machine code are POKEd into high RAM at addresses 65000–65212 to handle RS-232 serial I/O: a status check routine at 65000, an input (receive) routine at 65100, and an output (transmit) routine at 65200, all accessed via RANDOMIZE USR calls and OUT/IN instructions on port 119 (modem) and port 115 (serial data). The auto-answer loop polls the modem status port, sounds a multi-tone alert on ring detection, then presents a logon bulletin and menu to the caller, with the NOT key (key code 195) reserved as a local SYSOP escape to a privileged editor mode. Line-feed injection at every 40th character is supported as an option for callers whose terminals require it.
Program Structure
The program is organized into well-defined functional blocks, each introduced by a REM comment. Execution begins at line 5 with GO TO VAL "1700", jumping to the initialization section. The major sections are:
- Lines 10–40: Universal serial print subroutine (
GO SUB 10) - Lines 100–199: Main menu display and command dispatch
- Lines 200–475: Message read routines
- Lines 480–720: Message leave (compose) routines
- Lines 800–900: Info/system configuration display
- Lines 1000–1090: Character filter subroutine
- Lines 1100–1150: System clock read subroutine
- Lines 1160–1395: Auto-answer and logon bulletin
- Lines 1400–1580: Logon name capture and SYSOP chat mode
- Lines 1590–1690: Remote input subroutine (
GO SUB 1590) - Lines 1700–1890: Initialization (CLEAR, machine code install, clock set)
- Lines 1900–1970: Machine code POKE routines
- Lines 1980–2095: Connect-time and time-of-day calculation/display
- Lines 2100–2190: SYSOP-local message base switching
- Lines 3000–3190: SYSOP editor (local keyboard, entered via NOT key)
- Lines 3900–3915: Message pointer wrap helpers
- Lines 5000–5100: Remote message base change routine
- Lines 6000–6090: SYSOP local base-change subroutine
- Lines 9000–9070: Goodbye/hangup and re-answer loop
Machine Code Routines
Three machine code routines are installed at startup by GO SUB 1900, which RESTOREs DATA statements and POKEs bytes directly into high RAM above the CLEAR boundary (set at 64999):
| Address | Purpose | Called via |
|---|---|---|
| 65000–65008 | Modem status check — reads port 119, masks bits 0–1, returns in C register | USR 65000 / LET statchk=65000 |
| 65100–65145 | Serial receive — waits for data-ready on port 119, reads port 119 for data byte, handles timeout via BC counter | USR input (input=65100) |
| 65200–65212 | Serial transmit ready check — polls port 119 bit 0 in a loop until clear, then returns | RANDOMIZE USR output (output=65200) |
The transmit routine at 65200 is used as a “wait until TX ready” gate: the program calls it immediately before every OUT 115, ... to send a character byte. Port 119 is the modem/RS-232 control port and port 115 is the data port. The machine code bytes for the receive routine (lines 1940) are 45 bytes long and include nested polling loops with a timeout counter loaded into BC.
Serial Output Subroutine (Lines 10–40)
The core output routine at line 10 appends a carriage return to p$, PRINTs locally, then iterates character by character. For each character, it calls the TX-ready machine code via RANDOMIZE USR output and then sends the character code via OUT 115, CODE p$(x). The optional line-feed injection at line 12 checks if x is a multiple of 40 and lfeed=1, and if so also sends a line-feed (ASCII 10) for terminals that require CR+LF. POKE 23692,255 at line 10 suppresses the “scroll?” prompt by resetting the line counter.
Remote Input Subroutine (Lines 1590–1690)
The input routine at line 1590 is the primary method for reading a line of text from the remote caller. It polls IN 119 for the data-ready flag (bit 7 set = >128), calls USR input to receive the byte, then passes it through the character filter at line 1020. A local keyboard shortcut at line 1635 also allows the SYSOP to inject a response via INKEY$. A timeout counter uv is incremented on null bytes; reaching 200 null bytes causes a jump to the goodbye routine at line 9000. The received characters are accumulated in u$(), a 32-character DIM string.
Character Filter Subroutine (Lines 1020–1090)
The subroutine at line 1020 accepts known control characters by RETURNing immediately for codes 1, 7, 3, 10, 13, and 8 (SOH, BEL, ETX, LF, CR, BS). Any other character below 32 or above 127 is zeroed out (LET uu=0), which the callers treat as a null/no-data signal.
Message Storage Design
Messages are stored in m$(20,1000), a 20-element array of 1000-character strings. Each message slot begins with a “TO: ” header in positions 1–4, a recipient name through position 32, “FROM: ” in positions 33–38, and the sender’s name through position 64, with the message body starting at position 65. A CHR$ 3 (ETX) byte at position 1000 (or earlier) marks the end of a message. The message pointer variables y1 (current write slot), y2 (oldest message number), y3 (newest message number), and y4 (wrap count) are persisted to Microdrive in a separate y(4,1) numeric array.
Message Base Switching
Both remote (lines 5000–5100) and local SYSOP (lines 6000–6090) base-switching routines save the current m$() array and y() pointer array to named Microdrive files, then load the selected base. Microdrive device specifiers such as "@1,mess1", "@4,msg1", "@7,mess2", and "@:,msg2" indicate specific drive/slot assignments. Up to four message bases are referenced, though bases 3 and 4 are flagged as unavailable in the runtime messages.
Clock and Time Tracking
The system uses the system frame counter at addresses 23672–23674 (the three-byte FRAMES variable) as a software clock. Lines 1840–1880 convert a SYSOP-entered hour and minute into a frame count and POKE it into the FRAMES locations. The subroutine at line 1100 reads those same addresses back and converts to hours and minutes. Connect time is calculated in lines 1980–2040 by comparing the current minute to the stored login-time minute tw, with wrap-around handling at 60 minutes.
Auto-Answer and Call Flow
The auto-answer loop (lines 1160–1195) sends control bytes to port 119 to configure the modem, then polls IN 119 for a ring signal (value 5 = no ring; other values trigger answer). On ring detection, it sounds five short BEEPs, issues off-hook and connect commands, waits 300 frames (about 5 seconds), then falls through to the warmstart/logon sequence. After goodbye, line 9070 sends hangup commands to port 119 and loops back to the auto-answer routine.
SYSOP Chat Mode (Lines 1410–1580)
Chat mode first checks for 128 consecutive INKEY$ reads with no local keypress; if none detected, it reports the SYSOP unavailable. If a local key is pressed during that window, it enters a full-duplex loop: USR 65000 checks TX/RX status, USR 65100 receives incoming characters, and OUT 115, CODE i$ sends local keystrokes. The NOT key (INKEY$ code 195) exits chat and returns to the main menu. The SYSOP editor is also entered by pressing NOT during the auto-answer polling loop at line 1215.
Key BASIC Idioms and Techniques
GO TO VAL "nnnn"andGO SUB VAL "nnnn"are used extensively as a memory optimization, storing the line number as a string constant rather than a numeric token.POKE 23692,255resets the scroll counter before output operations to prevent “scroll?” interrupts during automated output.RESTOREfollowed by a specific line number andREADintop$is the standard pattern for emitting multi-line text blocks to the remote terminal.- The boolean expression
1 AND (a=1 OR a=3)at line 1510 is used to assign 0 or 1 toTxRDYandRxRDYflags. - The expression
"0" AND hr<10at line 2040 is a Spectrum-dialect idiom that produces the string “0” when the condition is true and “” when false, enabling zero-padded time display without an IF statement.
Bugs and Anomalies
- Line 540 embeds a
FORloop with multipleNEXT xjumps insideIFstatements (lines 550, 560, 570, 575), which iterates the FOR loop from within conditional branches — a valid but unusual structural pattern that can be hard to follow. - Line 550 uses
IF uv=60 THEN LET x=32:NEXT x— the intent is to force the FOR loop to its limit to exit, but this relies on the NEXT incrementing x to 33, not 32; the logic may leave the loop one iteration early in some cases. - Line 855 jumps to line 130 but never assigns
p$to a GO SUB 10 call first, so the message is assembled intop$but never transmitted to the caller. - Lines 2100–2190 appear to be unreachable dead code: there is no GO TO or GO SUB targeting line 2100, and line 2130 begins a REM that overlaps the info-files section label with the line 2140 output routine, suggesting these are leftover stubs from an earlier version.
- The DATA at line 820 contains the author’s name and BBS contact details — the system configuration info screen is effectively hardcoded and cannot be changed without editing the DATA statement.
- Line 1450 contains a FOR/NEXT loop where the NEXT is embedded inline after a conditional body, relying on the interpreter executing NEXT even after the IF body; if INKEY$ is never empty (key always held), the loop body’s NEXT is skipped and an infinite loop results.
Source Code
1 REM VSYS TS BBS- Latest Update: 8/20/86 by JOE NEWMAN
5 GO TO VAL "1700"
10 POKE 23692,255:LET p$=p$+ CHR$ 13:PRINT p$:FOR x=1 TO LEN p$
12 IF x/40= INT (x/40) AND lfeed=1 THEN RANDOMIZE USR output:OUT 115,10
15 RANDOMIZE USR output
30 OUT 115, CODE p$(x)
40 NEXT x:RETURN
100 REM MENU
110 RANDOMIZE USR output:OUT 115,13:LET p$=" VSYS Tiny BBS MENU >>>==========================<<<"+ CHR$ 13:GO SUB VAL "10"
120 RESTORE 129:FOR z=1 TO 8:READ p$:GO SUB 10:NEXT z
129 DATA "?) for this menu","R)ead messages","L)eave messages","C)hat with SYSOP","I)nfo files on system config.","M)essage base change","T)ime on system","G)oodbye"
130 RANDOMIZE USR output:OUT 115,13:LET p$="COMMAND(?=MENU)>":GO SUB VAL "10":GO SUB VAL "1590"
140 LET c$=u$(1)
145 IF c$="r" OR c$="R" THEN GO TO VAL "200"
147 IF c$="l" OR c$="L" THEN GO TO VAL "480"
148 IF c$="?" THEN GO TO VAL "100"
149 IF c$="C" OR c$="c" THEN GO TO VAL "1410"
150 IF c$="m" OR c$="M" THEN GO TO VAL "5000"
153 IF c$="T" OR c$="t" THEN GO SUB VAL "1980":GO SUB VAL "2080":LET p$="Connect time ":LET p$=p$+x$(1):RANDOMIZE USR output:OUT 115,13:PRINT :GO SUB 10:GO TO VAL "130"
155 IF c$="i" OR c$="I" THEN GO TO VAL "800"
160 IF c$="g" OR c$="G" THEN GO TO VAL "9000"
199 GO TO VAL "130"
200 REM READ
210 RANDOMIZE USR output:OUT 115,13
220 IF y3=0 THEN LET p$="Sorry, no messages found":GO SUB VAL "10":GO TO VAL "130"
230 LET p$="Messages from "+ STR$ y2+" to "+ STR$ y3+"...":GO SUB VAL "10"
240 LET p$="Read...(F)orward,(I)ndividual?":GO SUB VAL "10":GO SUB VAL "1590"
245 IF u$(1)="f" OR u$(1)="F" THEN LET loop=1
260 LET p$="Start at which message?":GO SUB VAL "10":GO SUB VAL "1590":LET y5= VAL u$( TO 2):IF u$(2)= CHR$ 13 THEN LET y5= VAL u$(1)
262 IF y5=0 THEN GO TO VAL "230"
340 IF INT y5<y2 OR INT y5>y3 THEN GO TO VAL "200"
350 LET y= INT y5:IF y5>20 THEN LET y= INT (y5-(20*y4))
360 IF y<0 THEN LET y=y+20
370 IF m$(y,1)=" " THEN RANDOMIZE USR output:OUT 115,13:LET p$="No message at that number...try another":GO SUB 10:GO TO VAL "200"
380 LET p$="MESSAGE NUMBER: "+ STR$ y5+ CHR$ 13:RANDOMIZE USR output:OUT 115,13:GO SUB 10
385 PRINT m$(y):FOR x=1 TO 1000
390 IF CODE m$(y,x)=3 THEN RANDOMIZE USR output:OUT 115,13:GO TO VAL "415"
400 RANDOMIZE USR output:OUT 115, CODE m$(y,x)
410 NEXT x
415 IF loop=1 AND y5+1 <=y3 THEN LET y5=y5+1:GO TO VAL "472"
470 LET loop=0:GO TO VAL "130"
472 LET p$="(N)ext, (Q)uit?":GO SUB VAL "10":GO SUB VAL "1590":IF u$(1)="N" OR u$(1)="n" THEN GO TO VAL "262"
475 GO TO VAL "470"
480 REM leave
490 LET y1=y1+1:IF y1>20 THEN LET y1=3
500 LET y3=y3+1
510 IF y3>20 THEN LET y2=y2+1
520 LET y4= INT (y3/20)
530 DIM l$(1000):LET m$(y1)=l$
540 RANDOMIZE USR output:OUT 115,13:LET p$="Who gets message: ":GO SUB VAL "10":LET uv=0:LET m$(y1,1 TO 4)="TO: ":FOR x=5 TO 32:IF IN VAL "119"> VAL "128" THEN LET uu= USR input:GO SUB VAL "1020"
549 IF IN VAL "119"< VAL "128" THEN GO TO VAL "9000"
550 IF uv=60 THEN LET x=32:NEXT x
560 IF uu=0 THEN LET x=x-1:LET uv=uv+1:NEXT x
570 IF uu=8 THEN LET x=x-1:LET uv=0:NEXT x
575 IF CHR$ uu= CHR$ 13 THEN LET x=32:NEXT x
580 LET m$(y1,x)= CHR$ uu:PRINT m$(y1,x);:LET uv=0
590 IF CODE m$(y1,x)=13 THEN LET x=32
600 NEXT x
610 IF uv=60 THEN GO TO VAL "9000"
615 LET m$(y1,33 TO 38)="FROM: "
620 FOR x=39 TO 64:IF k$(x-38)= CHR$ 13 THEN LET x=64:NEXT x
622 LET m$(y1,x)=k$(x-38):NEXT x
630 RANDOMIZE USR output:OUT 115,13:PRINT :LET p$="Input message (900 chars max).. <CTRL C> to save...":PRINT :RANDOMIZE USR output:OUT 115,13:GO SUB VAL "10"
650 LET uv=0:FOR v= VAL "65" TO VAL "999":POKE 23692,255:IF IN VAL "119"> VAL "128" THEN LET uu= USR input:GO SUB VAL "1020"
651 IF IN VAL "119"< VAL "128" THEN GO TO VAL "9000"
660 IF uv= VAL "60" THEN LET v= VAL "999":GO TO VAL "700"
670 IF uu= VAL "8" THEN LET v=v-1:LET uv= VAL "0"
680 IF uu=0 THEN LET v=v-1:LET uv=uv+1:NEXT v
690 LET m$(y1,v)= CHR$ uu:PRINT m$(y1,v);:LET uv= VAL "0":IF uu= VAL "3" THEN LET v= VAL "1000":NEXT v:LET m$(y1,1000)= CHR$ 3:GO TO VAL "100"
700 NEXT v:LET m$(y1,1000)= CHR$ 3
710 IF uv= VAL "60" THEN GO TO VAL "9000"
720 GO TO VAL "130"
800 REM Info Files
810 RESTORE VAL "820":PRINT :PRINT :RANDOMIZE USR output:OUT 115,13:FOR z=1 TO 14:READ p$:GO SUB VAL "10":NEXT z:GO TO VAL "130"
820 DATA "VSYS System Configuration","=========================",""," This is a BBS run off a Timex","Sinclair 2068 computer, and two","A&J Microdrives. The original ","version of the tinyboard program","was written by Randy & Lucy","Gordon. Mods were added by John","Ryan of the RATS DEN BBS","and the program was made into","its present form by yours truly","SYSOP===> Joe Newman <===",""
830 REM Message Base Change
840 RESTORE 900:LET p$="Current Message base="+ STR$ mbase+ CHR$ 13:GO SUB VAL "10":FOR z=1 TO 4:READ p$:GO SUB VAL "10":NEXT z
850 RANDOMIZE USR output:OUT 119,13:LET p$="Which base?":GO SUB VAL "10":GO SUB VAL "1590"
855 IF u$(1)= STR$ mbase THEN LET p$="This is mbase #"+ STR$ mbase:GO TO VAL "130"
856 IF u$(1)="4" THEN LET p$="Sorry, not available yet":GO SUB VAL "10":GO TO VAL "130"
857 LET h= VAL u$(1):IF h<0 OR h>4 THEN GO TO VAL "830"
858 IF mbase=1 THEN SAVE "@1,mess1":SAVE "@4,msg1"DATA y():
859 IF mbase=2 THEN SAVE "@7,mess2":SAVE "@:,msg2"DATA y()
860 IF mbase=3 THEN SAVE "@1,mes3":SAVE "@4,msg3"DATA y():POKE 24201,0
865 IF mbase=4 THEN SAVE "@7,mess4":SAVE "@:,msg4"DATA y():POKE 24201,0
870 IF u$(1)="3" OR u$(1)="4" THEN POKE 24201,1
872 LET o$="@mess"+u$(1):LOAD o$ DATA m$():LET o$="@msg"+u$(1):LOAD o$ DATA y()
880 GO TO VAL "130"
900 DATA "1) TS 1000,2068,Spectrum,Zx81","2) QL,buy,sell,trade,misc.","3) BS Base- Debate forum","4) Not avaialable yet! Up soon"
1000 LET users=0
1010 GO TO VAL "1700"
1020 IF uu=1 THEN RETURN
1030 IF uu=7 THEN RETURN
1040 IF uu=3 THEN RETURN
1050 IF uu=10 THEN RETURN
1060 IF uu=13 THEN RETURN
1070 IF uu=8 THEN RETURN
1080 IF uu<32 OR uu>127 THEN LET uu=0
1090 RETURN
1100 LET ty= INT ((65536* PEEK 23674+256* PEEK 23673+ PEEK 23672)/60)
1110 LET ht= INT (ty/3600)
1120 LET bz=ty-ht*3600
1130 LET mt= INT (bz/60)
1140 IF ht=24 THEN LET ht=0:LET dy=dy+1
1150 RETURN
1160 REM autoans
1170 OUT 119,34
1180 OUT 119,0
1190 REM ansloop
1200 GO SUB VAL "1100"
1205 LET loop=0
1210 LET a= IN 119
1215 IF CODE INKEY$=195 THEN GO TO VAL "3000"
1230 IF a=5 THEN GO TO VAL "1190"
1240 FOR x=1 TO 5:BEEP .1,40:NEXT x
1250 OUT 119,2
1260 OUT 119,34
1270 PAUSE 300
1280 REM warmstart
1290 OUT 119,64:OUT 119,123:OUT 119,55:LET tw= INT mt:REM set online timer
1300 REM logonbull
1305 LET lfeed=0
1310 PAUSE 30:FOR x=1 TO 30:RANDOMIZE USR output:OUT 115,0:NEXT x
1320 IF IN VAL "119"< VAL "128" THEN GO TO VAL "9000"
1330 RANDOMIZE USR output:OUT 115,28:RANDOMIZE USR output:OUT 115,31
1340 RANDOMIZE USR VAL "65200":OUT VAL "115", VAL "28"
1350 FOR x= VAL "1" TO VAL "17":RANDOMIZE USR VAL "65200":OUT 115,13:PRINT :NEXT x
1360 RESTORE VAL "1365":FOR z=1 TO 8:READ p$:GO SUB VAL "10":NEXT z
1365 DATA "Welcome to the...","","VSYS Timex/Sinclair BBS","Hours: Weekdays 7PM to 10AM","Fri. 7PM to Sun. 10AM, then","back up Sun. night at 7PM","","Board sponsored by Variety Sales"
1370 LET p$= CHR$ (13):LET p$=p$+ CHR$ (13):GO SUB VAL "10"
1380 LET users=users+1:LET p$="You are caller number "+ STR$ users:GO SUB 10:OUT 115,13:
1390 FOR x=1 TO 5:RANDOMIZE USR 65200:OUT 115,13:PRINT :NEXT x
1395 LET p$="Last caller="+k$:GO SUB VAL "10":RANDOMIZE USR output:OUT 115,13
1400 LET logon= VAL "1":LET p$="Full Name=":GO SUB VAL "10":GO SUB VAL "1590":LET p$="Need line Feeds (y/n)?":GO SUB VAL "10":GO SUB VAL "1590":IF u$(1)="y" OR u$(1)="Y" THEN LET lfeed=1
1401 LET p$="SORRY- Message bases 3 & 4 will NOT be available for a while":GO SUB VAL "10":GO TO VAL "100"
1410 REM chat
1440 PRINT :RANDOMIZE USR VAL "65200":OUT 115,13:LET p$="You want to talk to the VSYSOP?!Let's see if I can dig him up...":GO SUB 10:PRINT :RANDOMIZE USR 65200:OUT 115,13
1450 FOR x=1 TO 128:IF INKEY$="" THEN PRINT ".";:BEEP .1,1:RANDOMIZE USR 65200:OUT 115,46:NEXT x:LET p$="VSYSOP is not available.....":GO SUB 10:PRINT :RANDOMIZE USR 65200:OUT 115,13:GO TO 1300
1460 RANDOMIZE USR 65200:OUT 115,13:LET p$="Well, you've GOT him!:":FOR x=1 TO LEN p$:POKE 23692,255:PRINT p$(x);:RANDOMIZE USR 65200:OUT 115, CODE p$(x):NEXT x:PRINT :RANDOMIZE USR 65200:OUT 115,13
1470 CLS :PRINT "You are in chat mode with ";k$:PRINT :PRINT "SYMBL SHIFT/NOT to escape..."
1480 IF CODE INKEY$=195 THEN GO TO VAL "130":REM 195=NOT
1490 POKE 23692,255
1500 LET RxRDY=0:LET TxRDY=0
1510 LET a= USR 65000:LET TxRDY=1 AND (a=1 OR a=3):LET RxRDY=1 AND (a=2 OR a=3)
1520 IF RxRDY THEN LET k= USR 65100:PRINT CHR$ k;:IF k=13 THEN PRINT ">";
1530 IF TxRDY AND INKEY$ <>"" THEN GO SUB 1550
1540 GO TO 1480
1550 IF TxRDY THEN LET i$= INKEY$:PRINT i$;:OUT 115, CODE i$:FOR x=1 TO 5:NEXT x:IF CODE i$=13 THEN PRINT ">";
1560 IF INKEY$ <>"" THEN GO TO 1560
1570 IF CODE INKEY$=195 THEN GO TO VAL "130"
1580 RETURN
1590 REM inname
1600 DIM u$(32):LET u=1
1610 RANDOMIZE USR output:OUT 115,5:LET uv=0
1620 :IF IN 119>128 THEN LET uu= USR input:GO SUB 1020
1630 IF IN 119<128 THEN GO TO VAL "9000"
1635 IF INKEY$ <>"" THEN LET u$= INKEY$:PRINT u$:RANDOMIZE USR output:OUT 115, CODE u$(1):RETURN
1640 IF uv=200 THEN GO TO VAL "9000"
1650 IF uu=0 THEN LET uv=uv+1:GO TO 1620
1660 LET v$= CHR$ uu:PRINT v$;
1670 LET u$(u)=v$ AND u<32:LET u=u+1
1680 IF CODE v$=13 AND logon=1 THEN LET k$=u$:LET logon=0:RETURN
1685 IF CODE v$= VAL "13" THEN RETURN
1690 LET uv=0:GO TO 1620
1700 REM init
1710 REM 20 message base
1720 PAPER 0:BORDER 0:INK 7:CLS
1730 CLEAR 64999:GO SUB 1900
1740 LET lfeed=0:LET users=0:LET chatmode=-1
1750 DIM y(4,1):LET y1=0:LET y2=0:LET y3=0:LET y4=0:DIM l$(1000):DIM m$(20,1000):LET m$(1)="No messages found..."+ CHR$ 3:PRINT "Do you wish to load a message base?":INPUT x$:IF x$="y" OR x$="Y" THEN LOAD "@mess1"DATA m$():LOAD "@msg1"DATA y():LET y1=y(1,1):LET y2=y(2,1):LET y3=y(3,1):LET y4=y(4,1)
1760 PRINT :PRINT "<NOT> from most modes will exit to SYSOP control mode.":LET mbase=1
1770 LET y=0
1780 LET output=65200:LET input=65100:LET statchk=65000
1790 INPUT "Day";dy
1800 INPUT "Hour";ht
1810 INPUT "Minute";mt
1820 INPUT "Month ";e$:LET e$=e$+" "
1830 LET m6=0
1840 LET aa=(ht*3600+mt*60)*60
1850 LET bz= INT (aa/65536):POKE 23674,bz
1860 LET cz=aa-bz*65536
1870 LET aa= INT (cz/256):POKE 23673,aa
1880 LET bz=cz-aa*256:POKE 23672,bz
1885 CLS
1890 GO TO VAL "1160"
1900 REM code
1910 RESTORE 1920:FOR x=65000 TO 65008:READ x1:POKE x,x1:NEXT x
1920 DATA 175,219,119,230,3,79,6,0,201
1930 RESTORE 1940:FOR x=65100 TO 65145:READ x1:POKE x,x1:NEXT x
1940 DATA 1,255,255,119,230,128,200,175,219,119,230,2,32,10,11,120,177,32,240,6,0,14,1,201,219,115,6,0,79,219,119,230,128,200,175,219,119,230,1,40,244,121,211,115,201
1950 RESTORE 1960:FOR x=65200 TO 65212:READ x1:POKE x,x1:NEXT x
1960 DATA 219,119,230,128,200,175,219,119,230,1,40,244,201
1970 RETURN
1980 DIM x$(2,5):GO SUB VAL "1100":LET time= INT mt
1990 LET tz= INT (time-tw)
2000 IF tz<0 THEN LET tz= INT (time+60-tw)
2010 LET hr=0
2020 IF tz>60 THEN LET hr=1:LET tz=tz-60
2030 LET min=tz
2040 PRINT :PRINT AT 21,0;"0" AND hr<10;hr;":";"0" AND min<10;min:FOR x=1 TO 5:LET x$(1,x)= SCREEN$ (21,x-1):NEXT x
2050 GO SUB 1100
2060 PRINT :PRINT AT 21,0;"0" AND ht<10;ht;":";"0" AND mt<10;mt:FOR x=1 TO 5:LET x$(2,x)= SCREEN$ (21,x-1):NEXT x
2070 RETURN
2080 RANDOMIZE USR output:OUT 115,32:LET p$=e$+ STR$ dy+",1986"+ CHR$ 13:GO SUB 10
2090 LET p$="Time of day "+x$(2)+ CHR$ 13:GO SUB 10:
2095 RETURN
2100 INPUT "mbase1,2,3,4>";change
2110 IF change=1 THEN SAVE "@2,mess1"DATA m$():LET y(1,1)=y1:LET y(2,1)=y2:LET y(3,1)=y3:LET y(4,1)=y4:SAVE "@3,msg1"DATA y():GO TO 1700
2120 IF change=2 THEN SAVE "@4,mess2"DATA m$():LET y(1,1)=y1:LET y(2,1)=y2:LET y(3,1)=y3:LET y(4,1)=y4:SAVE "@5,msg2"DATA y():GO TO 1700
2130 REM info files
2140 RANDOMIZE USR output:OUT 115,13
2150 IF y1>20 THEN LET y1=y1-20
2160 RETURN
2170 IF y3>20 THEN LET y2=y2+1:RETURN
2180 IF mbase=1 THEN SAVE "@1,mess1"DATA m$():LET y(1,1)=y1:LET y(2,1)=y2:LET y(3,1)=y3:LET y(4,1)=y4:SAVE "@4,msg1"DATA y():LOAD "@mess2"DATA m$():LOAD "@msg2"DATA y():LET y1=y(1,1):LET y2=y(2,1):LET y3=y(3,1):LET y4=y(4,1):LET mbase=2:CLS :RETURN
2190 IF mbase=2 THEN SAVE "@7,mess2"DATA m$():LET y(1,1)=y1:LET y(2,1)=y2:LET y(3,1)=y3:LET y(4,1)=y4:SAVE "@:,msg2"DATA y():LOAD "@mess1"DATA m$():LOAD "@msg1"DATA y():LET y1=y(1,1):LET y2=y(2,1):LET y3=y(3,1):LET y4=y(4,1):LET mbase=1:CLS :RETURN
3000 REM SYSOP EDITOR
3010 PRINT AT 0,0;"SYSOP EDITOR"; AT 2,0;"<R>ead"; AT 4,0;"<L>eave"; AT 6,0;"<D>elete"; AT 8,0;"<Q>uit"; AT 10,0;"<S>ave mbase"; AT 12,0;"<B>reak program"; AT 14,0;"<C>hange mbase"; AT 16,0;"<N>o chat"
3050 LET i$= INKEY$:IF i$="" THEN GO TO VAL "3050"
3070 IF i$="s" OR i$="S" THEN GO TO VAL "4000"
3080 IF i$="R" OR i$="r" THEN INPUT "Message #?";x:PRINT "Message #";x:PRINT m$(x):PAUSE 0:CLS :GO TO VAL "3000"
3090 IF i$="d" OR i$="D" THEN INPUT "Message #=";x:PRINT "Message #";x;" deleted.":LET m$(x)=l$:PAUSE 0:CLS :GO TO VAL "3000"
3100 IF i$="l" OR i$="L" THEN LET y1=y1+1:GO SUB VAL "3900":LET y3=y3+1:GO SUB VAL "3910":PRINT "Message # ";y1:PRINT :FOR x=64 TO 1000:PAUSE 0:LET m$(y1,x)= INKEY$:PRINT m$(y1,x);:IF CODE INKEY$=195 THEN LET m$(y1,x)= CHR$ 3
3110 IF i$="l" OR i$="L" THEN IF m$(y1,x)= CHR$ 3 THEN GO TO VAL "3170"
3120 IF i$="l" OR i$="L" THEN NEXT x:PAUSE 0:LET m$(y1,1000)= CHR$ 3:GO TO VAL "3170"
3130 IF i$="q" OR i$="Q" THEN GO TO VAL "9000"
3140 IF i$="b" OR i$="B" THEN ©:STOP
3150 IF i$="c" OR i$="C" THEN GO SUB VAL "6000"
3160 GO TO VAL "3000"
3170 INPUT "Message to-";z$:LET m$(y1,1 TO 32)=z$(1 TO LEN z$)
3180 LET m$(y1,32)= CHR$ 13:LET m$(y1,33 TO 63)="From VSYSOP JOE":LET m$(y1,64)= CHR$ 13
3190 CLS :GO TO VAL "3000"
3900 IF y1>20 THEN LET y1=y1-20:RETURN
3905 RETURN
3910 IF y3>20 THEN LET y2=y2+1:RETURN
3915 RETURN
5000 REM MBASE CHANGE
5010 RANDOMIZE USR output:OUT 115,13
5020 RESTORE 5100:FOR z=1 TO 4:READ p$:GO SUB VAL "10":NEXT z:RANDOMIZE USR output:OUT 115,13
5025 LET p$="This is message base #"+ STR$ mbase:GO SUB VAL "10"
5030 LET p$="Choose mbase (1,2,3,4)>":GO SUB VAL "10"
5040 GO SUB VAL "1590"
5050 IF u$(1)= STR$ mbase THEN LET p$="This is Mbase #"+ STR$ mbase:GO SUB VAL "10":GO TO VAL "130"
5055 LET p$="Tapes Grinding...please stand by":GO SUB VAL "10":
5060 LET h= VAL u$(1)
5061 IF h>2 THEN LET p$="Sorry, not available now!":GO SUB VAL "10":GO TO VAL "5000"
5062 LET y(1,1)=y1:LET y(2,1)=y2:LET y(3,1)=y3:LET y(4,1)=y4
5065 IF mbase=1 THEN SAVE "@1,mess1"DATA m$():SAVE "@4,msg1"DATA y()
5067 IF mbase=2 THEN SAVE "@7,mess2"DATA m$():SAVE "@:,msg2"DATA y()
5070 IF mbase=3 THEN SAVE "@=,mess3"DATA m$():SAVE "@@,msg3"DATA y():
5072 IF mbase=4 THEN SAVE "@C,mess4"DATA m$():SAVE "@F,msg4"DATA y():
5075 LET z$="@mess"+ STR$ h:
5080 :LOAD z$ DATA m$():LET z$="@msg"+ STR$ h:LOAD z$ DATA y():LET y1=y(1,1):LET y2=y(2,1):LET y3=y(3,1):LET y4=y(4,1):LET mbase=h
5090 LET p$="WHEW...Mbase Changed!":GO SUB VAL "10":GO TO VAL "130"
5100 DATA "1) TS 2068/1000 ZX81 Spectrum","2) QL,misc.,buy,sell,trade","3) BS Base- Not available now","4) Not available now"
6000 REM sys change
6005 INPUT "Base to load=";h
6010 LET y(1,1)=y1:LET y(2,1)=y2:LET y(3,1)=y3:LET y(4,1)=y4
6020 IF mbase=1 THEN SAVE "@1,mess1"DATA m$():SAVE "@4,msg1"DATA y()
6030 IF mbase=2 THEN SAVE "@7,mess2"DATA m$():SAVE "@:,msg2"DATA y()
6040 IF mbase=3 THEN SAVE "@1,mess3"DATA m$():SAVE "@4,msg3"DATA y():POKE 24201,0
6050 IF mbase=4 THEN SAVE "@7,mess4"DATA m$():SAVE "@:,msg4"DATA y():POKE 24201,0
6060 LET z$="@mess"+ STR$ h:
6070 IF h=1 OR h=2 THEN LOAD z$ DATA m$():LET z$="@msg"+ STR$ h:LOAD z$ DATA y():LET y1=y(1,1):LET y2=y(2,1):LET y3=y(3,1):LET y4=y(4,1):LET mbase=h:RETURN
6080 POKE 24201,1:LOAD z$ DATA m$():LET z$="@msg"+ STR$ h:LOAD z$ DATA y():LET y1=y(1,1):LET y2=y(2,1):LET y3=y(3,1):LET y4=y(4,1):LET mbase=h
6090 RETURN
9000 REM QUIT
9010 IF y1 <>0 THEN LET m$(y1,1000)= CHR$ 3
9020 RANDOMIZE USR output:OUT 115,13
9030 CLS :PAUSE 10
9040 RESTORE 9050:FOR z=1 TO 7:READ p$:GO SUB VAL "10":NEXT z
9050 DATA "Thank you for calling the","VSYS Timex/Sinclair BBS","","To reach a human during BBS","hours, try calling 201-289-5699","","PLEASE HANG UP NOW!"
9060 PAUSE VAL "120"
9070 OUT 119,64:OUT 119,0:OUT 119,0:PAUSE VAL "60":CLS :GO TO VAL "1160"
9999 REM QUITNote: Type-in program listings on this website use ZMAKEBAS notation for graphics characters.
