1 REM VERSION 1.1 FIXED ALOT OF BUGS 10 rem Here are some limitations of IBM's Basic Compiler 2.0 and 20 rem rather detailed instructions of how to program around them. 30 rem When compiling programs larger in source than the 64 kilobyte 40 rem limit inherent in the compiler, you may either run out of 50 rem compiler space giving the ^TC (too compilcated error) of the 60 rem linker may give the obstruce error "Data out of segment bounds" 70 rem (meaning the object code created has data or program code 80 rem larger than 64K, it is known that object code can be generated 90 rem beyond 128K and still link successfully). 100 rem On may ask, "Is this really relevant to anything I* would 110 rem ever do?" and stop reading. This is certainly not a problem 120 rem you would run into everyday, however, for us hackers out here 130 rem in bbs-land, we have been fighting with this problem for what 140 rem seems like a long time! RBBS has this certain limitation, I 150 rem am sure. Even my own bbs is definitely running full steam 160 rem into it day in and day out. Here are some tips. 170 rem Why compile with the /E switch in the first place? If you 180 rem write code with no error, why trap any? Take this program: 190 rem 10 ON ERROR GOTO 20 200 rem 15 PRINT "AN ERROR HERE? NEVER!":END 210 rem 20 PRINT "OOPS!" 220 rem 30 RESUME 15 230 rem 40 STOP 240 rem Seriously, the /E switch generates two bytes of extra code for 250 rem each line in your program. This gets a bit more complex as I 260 rem will try to point out. IBM's Basic Compiler 2.0 has the ability 270 rem to link separately compiled 'subprograms' together. Each of 280 rem may itself be up to 64K of code (up to 64K for all subprograms 290 rem is used for data space, so beware!) Thus, you could compile 300 rem ten programs and link each object module into one giant 310 rem executable file. Read your manual for further details. Also 320 rem see the COMMAND SHARED statement. But, what does this have to 330 rem do with the /E switch? Simply put, these neat little subprograms 340 rem do not allow error trapping... (no ON ERROR statements!) 350 rem To overcome large module constraints in the second release 360 rem of IBM's Basic Compiler while programming communications (yes, 370 rem this is what I was getting at the whole time) we found a way 380 rem to do without the OPEN "COM... statement altogether since it 390 rem requires error trapping for it's various related methods of 400 rem receiving data from the device into your program (INPUT$ when 410 rem someone hangs up, for example) and since you cannot CHAIN another 420 rem compiled Basic program and re-open the communications port without 430 rem either dropping the carrier or receiving an error message to the 440 rem effect that it is already open (or try writing to it when it 450 rem isn't open. ARGH!) 460 rem On method is to access the serial ports directly for input, 470 rem output, and detecting carrier or the status of other parts of 480 rem the modem itself. Basically (hah) we start by turning on the 490 rem DTR lead (see your modem manual for whatever correct switches must 500 rem be set) with the statement OUT 1020,1 next send the ATZ code 510 rem (let's assume you have a hayes compatible) through a routine 520 rem which is listed below. After that, some other modem commands 530 rem may be necessary, in particular, ATE0Q1 or ATS2=255S0=1 (see 540 rem your manual for the exact meaning of these) Then wait for the 550 rem modem to ring and send the ATA command. The modem status 560 rem register's seventh bit, the ring indicator bit, can be examined. 570 rem This short peice of code works: 580 rem WHILE(INP(1022)AND 64)=0:WEND:A$="ATA":GOSUB 1000 590 rem The last step is to wait for a carrier, the following code works: 600 rem WHILE(INP(1022)<128:WEND It is a good idea to time how long 610 rem each loop is being thrashed through and to disconnect before 620 rem thirty seconds has elapsed (then hang up the modem with 630 rem OUT 1020,0 -- this can also be done at any time while your 640 rem program is running and the carrier is present) 650 rem Now that you have a carrier and the program is interacting 660 rem with a user, take a look at the example program below, with it's 670 rem sparse remarks and notice the modem input and output routines, 680 rem in fact the whole program, is working without ever opening 690 rem the communications port. 700 rem This document was typed in by an anonymous hacker. The 710 rem program was written by a large team of programmers on their 720 rem lunch break. 721 rem *** Begin program *** 722 rem 723 DEF FNTI!=VAL(MID$(TIME$,1,2))*3600+VAL(MID$(TIME$,4,2))*60+VAL(MID$(TIME$,7,2)) 725 rem Turn on the DTR lead 730 OUT 1020,1 731 rem Initialize the modem and wait two seconds for the OK response 733 A$="ATZ":GOSUB 8740:SOUND 32767,36 734 rem Instruct the modem to answer the phone after one ring 736 A$="ATQ1ES2=255S0=1":GOSUB 8740 737 rem Wait for the phone to ring 738 WHILE(INP(1022)AND 64)=0:WEND 739 rem Modem answers phone. Wait for carrier or timeout 741 T2!=FNTI!:WHILE(INP(1022)<128):GOSUB 8730:WEND:QQ=1:OUT 1019,3 742 rem Initialize the baud variables 743 rem ** Find out if it's 300,1200 and No parity or Even parity 744 ' Look at the buffer until a character is entered 745 WHILE(INP(1021)AND 1)=0:WEND 750 A=0:WHILE A=0:A=INP(1016):WEND:SWAP Q,QQ 751 ' If it is ascii 13 then it found even parity 752 IF A=13 THEN 200 753 ' If it is ascii 141 then it is a return with an extra bit, 754 ' then set the register to reflect this 755 IF A=141 THEN OUT 1019,26:GOTO 200 758 ' Store the line status register value 759 R1=INP(1019) 760 ' Set the divisor latch so the I/O buffer becomes the baud generator 761 OUT 1019,R1 OR 128:IF Q THEN OUT 1016,128:OUT 1017,1 ELSE OUT 1016,96:OUT 1017,0 762 ' Recode the baud. The baud is alternated until CR is found. 763 IF Q THEN OUT 1016,128:OUT 1017,1 ELSE OUT 1016,96:OUT 1017,0 764 ' Restore the I/O buffer by resetting the divisor latch 770 OUT 1019,R1:OUT 1019,3:GOSUB 8730:GOSUB 8730:GOTO 750 771 ' Set parity to none, check for carrier loss, and timeout 772 OUT 1019,3:GOSUB 8730:GOSUB 8730:GOTO 745 780 rem ** At this stage it has found the correct baud and parity.. 790 A$="Welcome to beta site X":GOSUB 1010 800 A$="Enter your name:":GOSUB 2001:STOP 810 rem add your program here 1000 rem ***** modem output routine ***** 1010 FOR A=1 TO LEN(A$) 1011 IF(INP(1021)AND 1) THEN D$=CHR$(INP(1016)) 1030 B$=MID$(A$,A,1):PRINT B$; 1040 IF INP((1021)AND 32)=0 THEN 1040 1050 GOSUB 8730:OUT 1016,ASC(B$):NEXT:RETURN 2000 rem ***** modem input routine ***** 2001 WHILE(INP(1021)AND 1)=0:WEND 2002 GOSUB 8730:C$=CHR$(INP(1016)) 2003 IF C$=CHR$(8) AND LEN(A$) THEN A$=LEFT$(A$,LEN(A$)-1):PRINT CHR$(29);CHR$(32);CHR$(29);:C$=CHR$(8)+CHR$(32)+CHR$(8):GOSUB 8760 2004 PRINT C$;:GOSUB 8760:IF Y$=CHR$(13)THEN RETURN 2005 A$=A$+C$:GOTO 2001 3000 REM ***** check carrier ***** 8730 IF INP(1022)<128 THEN END ELSE RETURN 8735 rem ***** send a modem command ***** 8740 A$=A$+CHR$(13):FOR A=1 TO LEN(A$):IF(INP(1021)AND 1)THEN DUMY=INP(1016) 8745 GOSUB 8770:OUT 1016,ASC(MID$(A$,A,1)):NEXT:RETURN 8750 rem ***** send a character to the modem ***** 8760 GOSUB 8770:GOSUB 8730:OUT 1016,ASC(C$):RETURN 8770 IF(INP(1021)AND 32)=0 THEN 8770 ELSE RETURN