What BASIC is running

From BeebWiki
Revision as of 00:31, 22 December 2013 by Jgh (talk)
Jump to: navigation, search

Sometimes a program needs to know what version of BASIC it is running on, for instance so that BASIC V instructions such as SYS, local errors and multi-line IFs can be used where version-neutral or platform-neutral code cannot otherwise be used. This is different from knowing what machine a program is running on which can be found with OSBYTE 0 and INKEY-256. 6502 BASIC II could be running on RISC OS via 65Tube, ARM BASIC V could be running on a BBC B via the ARM CoProcessor. In each of these cases, OSBYTE 0 or INKEY-256 would not give the answer looked for.

The following code allows a program to tell if it is running on BASIC V.

 DEFPROCtest
 IF FALSE THEN
   PRINT "Not running on BASIC V":ENDPROC
 ENDIF
 PRINT "Running on BASIC V"
 ENDPROC

The above is BASIC V code. As some keywords are tokenised differently, on BASIC I to IV the code must be entered as:

 DEFPROCtest
 IF FALSE THEN
   PRINT "Not running on BASIC V":ENDPROC
 SAVE
 PRINT "Running on BASIC V"
 ENDPROC

This takes advantage of the fact that pre-BASIC V does not understand multi-line IFs and so will just execute an empty THEN as an empty THEN. BASIC V sees an empty THEN as the start of a multi-line IF/ENDIF structure.

BASIC I does not implement offset assembly. This can be used to distinguish BASIC I from other pre-BASIC Vs with the following code:

 DIM P% -1:O%=P%:[OPT 4:NOP:]
 IF P%<>O% THEN PRINT "BASIC I" ELSE PRINT "BASIC II or later"

OPT 4 selects offset assembly, so if O% has not changed after assembling some code, it must be BASIC I running.

It is difficult to distinguish BASIC IV from other BASICs without generating an error or writing to the screen. A weak test is to read the ROM version number, but this will only work with 6502 BASIC. The following code will do this.

 IF HIMEM=&8000 OR HIMEM=&B800 THEN PRINT "BASIC ";?(HIMEM+7)

This is not perfect, as BASIC IV v4.0 will return &40, BASIC IV v4.30 will return &06 and BASIC IV v4.32 will return &07.

These tests can be made into a function as follows, as in the BASIC library:

 REM Code if edited on pre-BASIC V
 DEFFNBASIC_Ver:LOCAL O%,P%
 IF FALSE THEN
 DIM P%-1:O%=P%:[OPT 4:NOP:]IFP%<>O%:=1
 IFHIMEM=&8000 OR HIMEM=&B800:IF!(HIMEM+9)=&49534142:=?(HIMEM+8)
 =2
 SAVE
 =5
 
 REM Code if edited on BASIC V
 DEFFNBASIC_Ver:LOCAL O%,P%
 IF FALSE THEN
 DIM P%-1:O%=P%:[OPT 4:NOP:]IFP%<>O%:=1
 IFHIMEM=&8000 OR HIMEM=&B800:IF!(HIMEM+9)=&49534142:=?(HIMEM+8)
 =2
 ENDIF
 =5

This returns the following values:

  • 1 if BASIC I or equivalent, offset assembly, OSCLI, OPENUP not available
  • >1 if BASIC II or equivalent or later, offset assembly, OSCLI, OPENUP available
  • >3 if BASIC IV or equivalent or later, TIME$, ON x PROC available
  • >4 if BASIC V or equivalent or later, SYS, WHILE, CASE, multiline IF/ENDIF available

This means you can then use code such as the following:

 IF FNBASIC_Ver<5 THEN CHAIN "Exit" ELSE SYS "XOS_CLI","Quit"

or

 IF FALSE THEN
 CHAIN "Exit"
 ENDIF
 SYS "XOS_CLI","Quit"

Jgharston 11:06, 2 September 2008 (BST)