Environ - BASIC program environment =================================== Environ displays the program environment that the BASIC program is running in. A typical display is as follows: BBC BASIC program environment ----------------------------- Program name: >Environ< Command line: >Hello world< Host: 8 Unix Filing System: 24 UNIXFS Filenames are: Unix-like d:/directory/filename.ext Keyboard type: Regular f1=&81 f10=&8A Cursors=&CC+ CPU: PDP11 CALL &FFxx: Yes PAGE<&FFFF Program text: Acorn/Wilson ?(TOP-3)<>0 PAGE=&3A80 HIMEM=&E000 ?(TOP-3)=36 !(TOP-3)=&52FF0D24 Command line ------------ The program name and command line are found with the ProgEnv OS_GetEnv function which does some complicated processing to determine the program environment so that the rest of the program doesn't have to. The program and command line should be that used to run the program, for instance: CHAIN "Eviron Hello world" RUN Environ Hello world RUN BASIC Environ Hello world BASIC -quit Environ Hello world BASIC Environ Hello world Environ Hello world When writing a BASIC interpreter, when it is not started with CHAIN your BASIC startup code should copy the command line to the string buffer so that it appears in the same format as if a CHAIN command had been used, normally by passing the command line to the CHAIN command itself. If you get the wrong information, it is most likely because you have made your BASIC environment "look" too much like another environment without actually reproducing that environment. For instance, an environment that "looks like" a 6502, such as a 6809 or 65816, should place the command string at &0600 the same as the 6502. Host ---- The host is determined by calling OSBYTE 0 with U%=USR&FFF4. On some platforms the result is an accidental side effect of OSBYTE 0 not being implemented, and the ProgEnv OS_GetEnv function is written to ensure the correct environment to ensure the correct side effects results in the required return value. Even if you do not implement CALL &FFxx API translation, you must at the minimum ensure A%=0:X%=1:U%=USR&FFF4 returns an appropriate value, then the rest of the program can take appropriate action. Filing system ------------- If CALL &FFxx is available, the filing system is found with OSARGS 0,0. Otherwise it defaults to DOSFS on DOS/Windows and UNIXFS on Unix. The filename format is determined from the host value read from OSBYTE 0. %000x0xxx BBC-style :D.directory.filename/ext %00001xxx Unix-style D:/directory/filename.ext %00011xxx CPM-style D:filename.ext %nnnxxxxx DOS-style D:\directory\filename.ext If the filename format is displayed wrong, you are supplying the wrong host OS value from OSBYTE 0. As host values are a limited resource, you should use a pre-existing value that closely matches the environment you are running on. If your environment uses Unix-like filenames, it should return os%=8 If your environment uses CPM-like filenames, it should return os%=24 If your environment uses DOS-like filenames, it should return os%=32 More specific detail about the host environment is found with INKEY-256. Note, this is the *host* environment, *NOT* the BASIC environment. 6502 BASIC running on Windows must return 32, not 1-5; ARM BASIC running on Unix must return 8, not 6. Keyboard type ------------- OS API access ------------- The BBC-style OS API is accessed from BASIC via CALL/USR to an address at &0000FF00-&0000FFFF. Either the host platform should have actual entry points to the OS API at those addresses, or BASIC should interpret those addresses passed to CALL/USR and redirect them to the appropriate OS API call. The commonest method to determine if CALL &FFxx is available is to test for PAGE<&FFFF with, for example: IF PAGE<&FFFF THEN CALL OSGBPB ELSE do something manually If your BASIC *does* *not* translate CALL/USR &FFxx to OS API calls, it *must* *not* default to PAGE<&FFFF. This does not mean that PAGE>&FFFF requires that CALL &FFxx must not be available, you are free to choose to implement CALL translation, but it makes it much easier for the programmer if PAGE<&FFFF when CALL &FFxx is available as a MOS API call. Note that there are some BASICs that do default to PAGE<&FFFF and do not translate CALL &FFxx calls, multi-platform code that wants to support those platforms need to use additional code. However, any new implementation of BASIC must stick to 'PAGE<&FFFF equals CALL &FFxx is available'. CPU --- The CPU is determined by assembling a NOP opcode. Even if you do not implement an inline assembler, you should ensure that entering and exiting the assembler results in the opcode for a NOP being deposited in memory. Strictly speaking, this test determines the target of the in-line assembler. There are versions of BASIC where you can use the inline assembler to assemble code for other CPUs. Programs that assemble machine code normally just attempt to assemble the code and generate a Syntax error if the inline assembler doesn't match the code. A program rarely needs to know what CPU it is running on. There are better ways to determine a BASIC's functionality than testing what CPU it is running on, test for the functionality itself not for the CPU. Program text information ------------------------ There are two main methods of storing a BASIC program in memory: the original Acorn format: Richard Russell format: The format can be determined by examining the last few bytes of the program: Acorn format: Richard Russell format: <00> ?(TOP-3) will be zero for Russell format and non-zero for Acorn format. This information may be needed by code that examines the program in memory. You should ensure that ?(TOP-3) reflects the memory layout of the BASIC program in memory. For compatibility, if you use Russell format then REPORT should not issue a newline, if you use Acorn format then REPORT should issue a newline, so the following code works: IF ?(TOP-3)=0 THEN PRINT REPORT Brandy Basic uses another method which is not detected by this test.