Megalextoria
Retro computing and gaming, sci-fi books, tv and movies and other geeky stuff.

Home » Archive » net.micro.trs-80 » My first BASIC program (source)
Show: Today's Messages :: Show Polls :: Message Navigator
E-mail to friend 
Switch to threaded view of this topic Create a new topic Submit Reply
My first BASIC program (source) [message #91816] Tue, 16 July 1985 23:51
ronbe is currently offline  ronbe
Messages: 15
Registered: June 2013
Karma: 0
Junior Member
Article-I.D.: tekred.384
Posted: Tue Jul 16 23:51:52 1985
Date-Received: Fri, 19-Jul-85 03:27:13 EDT
Organization: The Hollow Tree
Lines: 466

Actually, it's my first BASIC program in over 6 months.
But, just so as not to get away from Z80 (my language),
this BASIC program uses Z80 routines...

It's a bulletin board program.  There are four Z80
routines that the program uses.  The first (FNI) sets
up the RS232 and waits for carrier detect, the second
(FNS) sends a BASIC string, the third (FNR) receives a
BASIC string, and the fourth (FNQ) resets the RS232 and
clears the line.  FNR actually puts the characters
right into your BASIC program's string.

The following shar has all you need to get it running.
It's set up at 300 baud, but easy to change via POKE or
a small change in the source.  The included BASIC
program is just an example, I'm sure it will grow for
me as I do more things.  I'd like to have random access
files with user's names, person-to-person mail, and all
sorts of other things that the "big" BBS's have.

Anyway, here it is.  Enjoy.

			Ron Bemis
			tektronix!tekred!ronbe

# This is a shell archive.  Remove anything before this line,
# then unpack it by saving it in a file and typing "sh file".
#
# Wrapped by tekred!ronbe on Tue Jul 16 20:42:05 PDT 1985
# Contents:  Makefile vectors.z80 setup.z80 send.z80 receive.z80 quit.z80
#	bbs.cmd bbs.equ bbs.bas
 
echo x - Makefile
sed 's/^@//' > "Makefile" <<'@//E*O*F Makefile//'
TITLE=	bbs
OBJS=	vectors.obj setup.obj send.obj receive.obj quit.obj
SHAR=	Makefile vectors.z80 setup.z80 send.z80 receive.z80 quit.z80 bbs.cmd bbs.equ bbs.bas
BASE=	FE00
SIZE=	200
ASM=	/usr/local/z80/lasasm
SASM=	/usr/local/z80/asm
LNK=	/usr/local/link/link
HEX=	/usr/local/ehex
CHK=	/usr/local/chks
LST=	/usr/local/lstr

$(TITLE).rom:	$(OBJS) $(TITLE).cmd
	$(LNK) -v -d -r -o $(TITLE).lnk -c $(TITLE).cmd > $(TITLE).log
	$(HEX) -s $(TITLE).lnk > $(TITLE).tek
	$(HEX) -i $(TITLE).lnk > $(TITLE).hex
	$(CHK) -b $(BASE) -s $(SIZE) < $(TITLE).tek > $(TITLE).rom
	$(LST) -s $(TITLE).lnk >> $(TITLE).log

vectors.obj:	vectors.z80 $(TITLE).equ
		$(SASM) vectors.obj vectors.prn vectors.z80
setup.obj:	setup.z80 $(TITLE).equ
		$(SASM) setup.obj setup.prn setup.z80
send.obj:	send.z80 $(TITLE).equ
		$(SASM) send.obj send.prn send.z80
receive.obj:	receive.z80 $(TITLE).equ
		$(SASM) receive.obj receive.prn receive.z80
quit.obj:	quit.z80 $(TITLE).equ
		$(SASM) quit.obj quit.prn quit.z80

new:	clean
	make

clean:
	rm -f *.obj *.lnk *.prn *.hex *.tek *.rom *.log

list:
	lpr *.log *.prn

shar:	$(SHAR)
	shar $(SHAR) > shar
@//E*O*F Makefile//
chmod u=rw,g=r,o=r Makefile

echo "Send BBS updates to $USER" | mail tektronix!tekred!ronbe 
 
echo x - vectors.z80
sed 's/^@//' > "vectors.z80" <<'@//E*O*F vectors.z80//'
	title	'Bulletin Board Program'
	stitle	'Jump Vectors'
	list	page(64)
	include	'bbs.equ'
	section	vectors
	global	setup,send,rline,quit
	jp	setup
	jp	send
	jp	rline
	jp	quit
@//E*O*F vectors.z80//
chmod u=rw,g=r,o=r vectors.z80
 
echo x - setup.z80
sed 's/^@//' > "setup.z80" <<'@//E*O*F setup.z80//'
	title	'Bulletin Board Program'
	stitle	'Set up RS232'
	list	page(64)
	include	'bbs.equ'
	section	code
	global	setup,quit
setup	ld	a,15
	call	vdchar		;cursor off
	xor	a
	out	(rsrset),a	;reset uart
	ld	a,55h		;300 baud
	out	(baudsl),a	;set it
	ld	a,0b4h		;parameters
	out	(rscntl),a	;set it
waitcd	call	kbbrk		;break pressed?
	jp	nz,quit		;return if so
	in	a,(rsrset)	;read status
	and	20h		;check bit 5
	jp	nz,waitcd	;wait for cd
	ld	a,14
	call	vdchar		;cursor on
	ld	hl,0		;got dcd!
	jp	basret		;return to BASIC
@//E*O*F setup.z80//
chmod u=rw,g=r,o=r setup.z80
 
echo x - send.z80
sed 's/^@//' > "send.z80" <<'@//E*O*F send.z80//'
	title	'Bulletin Board Program'
	stitle	'Send A String'
	list	page(64)
	include	'bbs.equ'
	section	code
	global	send,txchar,quit
send	call	basget
	ld	b,(hl)		;length of string
	inc	hl
	ld	a,(hl)
	inc	hl
	ld	h,(hl)		;!!!
	ld	l,a		;hl points to data
txeach	call	kbbrk		;break pressed?
	jp	nz,quit		;go if so
	ld	a,b		;get length
	or	a
	jp	z,txend		;go if last
	ld	c,(hl)		;put data in c
	call	txchar		;send it
	call	vdchar		;display it
	inc	hl
	dec	b
	jp	txeach
txend	ld	c,13		;create return
	call	txchar		;send it
	call	vdchar		;display it
	ld	c,10		;create linefeed
	call	txchar		;send it
	ld	hl,0		;status good
	jp	basret		;return to BASIC
txchar	in	a,(rscntl)	;check status
	and	40h		;transmit buffer empty?
	jp	z,txchar	;wait if not
	ld	a,c		;get the data
	out	(rsdata),a	;send it
	ret
@//E*O*F send.z80//
chmod u=rw,g=r,o=r send.z80
 
echo x - receive.z80
sed 's/^@//' > "receive.z80" <<'@//E*O*F receive.z80//'
	title	'Bulletin Board Program'
	stitle	'Receive A Line'
	list	page(64)
	include	'bbs.equ'
	section	code
	global	rline,txchar,quit
rline	call	basget		;get pointer
	ld	a,(hl)		;get old length
	ld	ix,length	;point to storage
	ld	(ix+1),a	;(ix+1) = # left to fill
	ld	(ix+0),0	;new length = 0
	inc	hl
	ld	a,(hl)
	inc	hl
	ld	h,(hl)		;!!
	ld	l,a		;hl points to data
timer	ld	bc,0		;delay counter
loop	call	kbbrk		;break pressed?
	jp	nz,quit		;go if so
	call	rca		;character available?
	jp	nz,got1		;go if so
	push	bc
	ld	b,40h		;makes about 30 secs
	djnz	$
	pop	bc
	djnz	loop		;keep checking
	dec	c
	jr	nz,loop		;keep checking
	ld	hl,-1		;timeout
	jp	basret		;return to BASIC
got1	cp	22h		;double quote?
	jp	z,timer		;nice try, jerk!
	cp	' '		;less than space?
	jp	nc,normal	;go if not
	cp	13		;return?
	jp	z,return
	cp	10		;linefeed?
	jp	z,return
	cp	8		;backspace?
	jp	z,backsp
	cp	15h		;control-u?
	jp	z,cancel
	cp	3		;etx?
	jp	z,erase
	cp	18h		;cancel (control-x)?
	jp	z,erase
	jp	timer		;ignore others
normal	ld	c,a		;move it to C
	ld	a,(ix+1)	;# left to fill
	or	a		;enough room?
	jp	z,timer		;ignore if not
	ld	(hl),c		;put it in
	inc	hl		;bump the pointer
	inc	(ix+0)		;bump the length
	dec	(ix+1)		;one less to fill
	call	txchar		;echo it
	call	vdchar		;display it
	jp	timer		;wait for next
backsp	ld	c,a		;move it to C
	ld	a,(ix+0)	;get the length
	or	a		;is it 0?
	jp	z,timer		;ignore if so
	dec	(ix+0)		;back off length
	dec	hl		;back off pointer
	inc	(ix+1)		;one more to fill
	call	txchar		;echo it
	call	vdchar		;display it
	jp	timer		;wait for next
cancel	ld	c,5eh		;create control-
	call	txchar		;echo it
	call	vdchar		;display it
	ld	c,'U'		;create U
	call	txchar		;echo it
	call	vdchar		;display it
	ld	c,13		;create carriage return
	call	txchar		;echo it
	call	vdchar		;display it
	ld	c,10		;create line feed
	call	txchar		;echo it
mtloop	ld	a,(ix+0)	;get the length
	or	a		;is it 0?
	jp	z,timer		;go if so
	dec	(ix+0)		;back off length
	dec	hl		;back off pointer
	inc	(ix+1)		;one more to fill
	jp	mtloop		;until length = 0
erase	ld	a,(ix+0)	;get the length
	or	a		;is it 0?
	jp	z,timer		;go if so
	dec	(ix+0)		;back off length
	dec	hl		;back off pointer
	inc	(ix+1)		;one more to fill
	ld	c,8		;create backspace
	call	txchar		;echo it
	call	vdchar		;display it
	jp	erase		;until length = 0
return	ld	c,13		;create return
	call	txchar		;echo it
	call	vdchar		;display it
	ld	c,10		;create linefeed
	call	txchar		;send it
	ld	h,0
	ld	l,(ix+0)	;length in HL
	jp	basret		;return to BASIC
rca	in	a,(rscntl)	;get uart status
	and	80h		;character available?
	ret	z		;return if not
	in	a,(rsdata)	;get the data
	and	7fh		;strip top bit
	cp	7fh		;all 1's?
	ret	z		;return if so
	or	a		;null?
	ret			;return with Z flag
length	block	1		;string length
tofill	block	1		;initial length
@//E*O*F receive.z80//
chmod u=rw,g=r,o=r receive.z80
 
echo x - quit.z80
sed 's/^@//' > "quit.z80" <<'@//E*O*F quit.z80//'
	title	'Bulletin Board Program'
	stitle	'Reset the RS232'
	list	page(64)
	include	'bbs.equ'
	section	code
	global	quit
quit	xor	0
	out	(rsrset),a	;reset modem
	dec	a
	out	(rscntl),a	;turn off everything
	ld	a,14
	call	vdchar		;cursor on
	ld	hl,-1
	jp	basret
@//E*O*F quit.z80//
chmod u=rw,g=r,o=r quit.z80
 
echo x - bbs.cmd
sed 's/^@//' > "bbs.cmd" <<'@//E*O*F bbs.cmd//'
-O vectors.obj setup.obj send.obj receive.obj quit.obj
-m MEM=0FE00-0FFFF		;location for code
;assign class names to sections
-L SEC=VECTORS BASE MEM		;VECTORS at beginning
-L SEC=CODE RANGE MEM		;locate CODE in MEM
-x 402D				;entry address
@//E*O*F bbs.cmd//
chmod u=rw,g=r,o=r bbs.cmd
 
echo x - bbs.equ
sed 's/^@//' > "bbs.equ" <<'@//E*O*F bbs.equ//'
VDCHAR	EQU	0033H
KBBRK	EQU	028DH
BASGET	EQU	0A7FH
BASRET	EQU	0A9AH
RSRSET	EQU	0E8H
BAUDSL	EQU	0E9H
RSCNTL	EQU	0EAH
RSDATA	EQU	0EBH
@//E*O*F bbs.equ//
chmod u=rw,g=r,o=r bbs.equ
 
echo x - bbs.bas
sed 's/^@//' > "bbs.bas" <<'@//E*O*F bbs.bas//'
10 POKE 16562,&HFD:POKE 16561,&HFE:CLEAR 2000:CMD "L","BBS/CMD"
20 DEFUSR0=&HFE00:DEFFNI=USR0(0)  'SETUP RS232, WAIT FOR CD
30 DEFUSR1=&HFE03:DEFFNS(S$)=USR1(VARPTR(S$))  'SEND ROUTINE
40 DEFUSR2=&HFE06:DEFFNR(R$)=USR2(VARPTR(R$))  'RECEIVE ROUTINE
50 DEFUSR3=&HFE09:DEFFNQ=USR3(0)  'QUIT ROUTINE
60 ON ERROR GOTO 230  
70 CLS:X=FNI:ST$=TIME$:FOR X=1 TO 1000:NEXT
80 SR$="**********  "  'FOR PRINTER MESSAGES
90 N$="Anonymous"  'NO NAME YET
100 X=FNS("")
110 X=FNS("-----------------------------------")
120 X=FNS("  TRS-80 Model III Bulletin Board")
130 X=FNS("   TRSBBS (c) 1985 by Ron Bemis")
140 X=FNS("-----------------------------------")
150 X=FNS("")
160 GOTO 470  
170 REM *************************************
180 REM * RECEIVE A LINE - STUFF IT INTO C$ *
190 REM *************************************
200 C$="--------------------------------------------------"
210 X=FNR(C$):IF X=-1 THEN 320  'TIMED OUT
220 C$=LEFT$(C$,X):RETURN
230 REM *****************
240 REM * PROGRAM ERROR *
250 REM *****************
260 LPRINT SR$"ERROR CODE "ERR/2+1
270 LPRINT SR$"ON LINE "ERL:LPRINT
280 X=FNS("")
290 X=FNS("Program Error!  Sorry, but I can't continue...")
300 RESUME 360  
310 REM ***************************************************
320 REM * TIMEOUT -- SEND MESSAGE, HANG UP AND START OVER *
330 REM ***************************************************
340 X=FNS("")
350 X=FNS("Timeout...")
360 REM *******************
370 REM * END THE SESSION *
380 REM *******************
390 ET$=TIME$
400 X=FNS("Connected from "+ST$+" to "+ET$)
410 X=FNS("Thanks for calling, "+N$+"!")
420 FOR X=1 TO 100:NEXT
430 X=FNQ
440 LPRINT SR$N$" was connected from "ST$" to "ET$:LPRINT
450 FOR X=1 TO 15000:NEXT  'ABOUT 30 SECONDS
460 RUN 20   
470 REM *************************
480 REM * START THE INTERACTION *
490 REM *************************
500 X=FNS("What is your name?")
510 GOSUB 170  :IF C$<>"" THEN N$=C$:GOTO 560  
520 X=FNS("No anonymous calls allowed.")
530 X=FNS("What is your name?")
540 GOSUB 170  :IF C$<>"" THEN N$=C$:GOTO 560  
550 X=FNS("Shall we get serious now?"):GOTO 500  
560 REM *************
570 REM * Main Menu *
580 REM *************
590 X=FNS("")
600 X=FNS("Main Menu:")
610 X=FNS("")
620 X=FNS("   1:  System Message")
630 X=FNS("   2:  Leave a message for the SysOp")
640 X=FNS("   3:  Chat with the SysOp")
650 MX=3
660 X=FNS("ENTER:  Quit")
670 X=FNS("")
680 X=FNS("Your selection:")
690 GOSUB 170  :IF C$="" THEN GOTO 360  'END THE SESSION
700 S=VAL(C$):IF S>0 AND S<=MX THEN GOTO 780  'GOOD CHOICE
710 X=FNS("Invalid selection, try again:")
720 GOSUB 170  :IF C$="" THEN GOTO 360  'END THE SESSION
730 S=VAL(C$):IF S>0 AND S<=MX THEN GOTO 780  'GOOD CHOICE
740 GOTO 560  
750 REM *****************************
760 REM * POINTERS TO MENU ROUTINES *
770 REM *****************************
780 ON S GOTO 790  ,890  ,970  
790 REM ******************
800 REM * SYSTEM MESSAGE *
810 REM ******************
820 OPEN "I",1,"SYSMSG/BLD"
830 IF EOF(1) THEN 870  
840 LINEINPUT #1,C$
850 X=FNS(C$)
860 GOTO 840  'NEXT LINE
870 CLOSE 1:X=FNS("Press ENTER...")
880 GOSUB 170  :GOTO 560  
890 REM ***************************
900 REM * LEAVE MESSAGE FOR SYSOP *
910 REM ***************************
920 LPRINT SR$"MESSAGE FROM "N$
930 X=FNS("Type up to 20 lines; enter a blank line to end.")
940 FOR I=1 TO 20:GOSUB 170  :IF C$="" THEN 950  :LPRINT C$:NEXT I
950 LPRINT SR$"END OF MESSAGE":LPRINT
960 X=FNS("Message logged."):GOTO 560  
970 REM ***********************
980 REM * CHAT WITH THE SYSOP *
990 REM ***********************
1000 LPRINT SR$N$" CHAT SESSION"
1010 X=FNS("Wait just a moment while I make some noise...")
1020 PRINT "Hey, boss!  "N$" would like a word with you..."
1030 FOR X=1 TO 15:LPRINT CHR$(7);:FOR Y=1 TO 100:IF INKEY$<>"" THEN 1080 ELSE NEXT Y:NEXT X
1040 LPRINT SR$"GOT NO REPLY":LPRINT
1050 X=FNS("Looks like nobody's around.")
1060 X=FNS("You might want to try again later.")
1070 GOTO 560  
1080 X=FNS("Ok!  Somebody's here...")
1090 X=FNS("Here's how we do this:  You start, and type your")
1100 X=FNS("message first.  Send a blank line to tell me")
1110 X=FNS("that you're finished.  You can type up to ten")
1120 X=FNS("lines.  The Sysop follows the same rules.  If")
1130 X=FNS("either of you want to stop, just send 'DONE'")
1140 X=FNS("all by itself on a line.  It must be capitalized.")
1150 X=FNS("I (the TRS-80) keep track of whose turn it is.")
1160 X=FNS("Your turn...")
1170 FOR I=1 TO 10
1180 GOSUB 170  :IF C$="" THEN 1210  'SYSOP'S TURN
1190 LPRINT C$:IF C$="DONE" THEN 1270  'CHAT DONE
1200 NEXT I
1210 PRINT "SysOp Reply..."
1220 FOR I=1 TO 10
1230 LINEINPUT C$:IF C$="" THEN 1260  'USER'S TURN
1240 LPRINT SR$C$:X=FNS(C$):IF C$="DONE" THEN 1270  'CHAT DONE
1250 NEXT I
1260 GOTO 1160
1270 LPRINT SR$"CHAT SESSION OVER":LPRINT
1280 GOTO 560
@//E*O*F bbs.bas//
chmod u=rw,g=r,o=r bbs.bas
 
exit 0
-- 
Be careful tonight, if you drive, don't park.
Remember, accidents are the major cause of people.
	...tektronix!tekred!ronbe (Ron Bemis)
  Switch to threaded view of this topic Create a new topic Submit Reply
Previous Topic: MODEL 1 help! Software to toggle shift key?
Next Topic: Request a dying species...
Goto Forum:
  

-=] Back to Top [=-
[ Syndicate this forum (XML) ] [ RSS ] [ PDF ]

Current Time: Mon Oct 03 14:26:50 EDT 2022

Total time taken to generate the page: 0.14058 seconds