What BASIC is running

From BeebWiki
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"

BBC API entries

You very rarely need to know what BASIC you program is running on, but one useful test is determining if you can call the BBC MOS API at &FFxx. On most implementations of BBC BASIC, CALL and USR can be used to access the BBC API at &FFxx. Testing for PAGE<&FFFF will tell you if the API is available, so you can use code such as:

 REM Read object information:
 IF PAGE<&FFFF THEN $name%=A$:?X%=name%:X%?1=name%DIV256:A%=5:ftype%=(USR&FFDD)AND&FF
 
 REM Write bytes to file:  
 ?X%=channel:X%!1=address,X%!5=count:A%=gbpb_wr
 IF PAGE<&FFFF THEN CALL &FFD1 ELSE REPEAT:BPUT#?X%,?(X%!1):X%!1=X%!1+1:X%!5=X%!5:UNTIL X%!5=0

Processor memory size

On an 8-bit CPU HIMEM is neccessarily below 64K. On larger CPUs there is more than 64K available to the program and consequently HIMEM will be above 64K. This can be used to test what CPU type the program is running on. This is useful when claiming memory as on 64K CPUs loops and calls stack less data than on larger CPUs, and if you claim too much memory your program will run out of memory. So, by testing for a large CPU you can claim less memory than you would on a small CPU

 max%=HIMEM-LOMEM-2048+2048*(HIMEM>&FFFF)
 DIM mem max%

Jgharston 11:06, 2 September 2008 (BST) Jgharston (talk) 20:42, 24 June 2018 (CEST)