Notes on Screenmodes, selectors and specifiers

(This topic needs to be preceded by a 'Health Warning'. Although the principles are easy to state, the practice can be frustrating if you try to change desktop mode from within a wimp program whilst you are 'up and running'.)

Since the arrival of 3.50, it has been possible to choose the desktop start-up screen mode - and change the screen mode - via the Configure process, i.e. by double-clicking on your !Boot application and choosing the required options.

However, there are many circumstances when you might want to set/change a screen mode from within a program or from an Obey file, for either desktop or non-desktop operations.

Prior to 3.50 screen modes were defined by number, e.g. mode 27, and you need to refer to the User Guide to find out the preset screen resolution and number of colours each number represented. In principle, the numbers could take any value in the range 0-127 (with 128-255 for the corresponding 'shadow' modes) but, in practice, only about 50 numbers were defined.

From RISC OS 3.50 onwards, many more screen mode options became available, and the use of a single number then became too restrictive, so a new method of defining the modes was needed and one which still enabled the 'old' modes to be used.

Acorn, in fact, provided several definition methods. They include mode specifier, mode string and ModeInfo files - and they are all related through something called the mode selector.

This article will confine itself to looking mainly at mode specifier and mode string with just a brief mention of ModeInfo files.

The 'mode selector'

Let's start with the common factor, the mode selector. This is the name given to a memory block in a specified format which actually defines a screen mode. The block contains (in defined locations within it) the required x/y resolutions, number of colours, text resolution, etc.

You need to consult the PRM if you want to investigate the mode selector format properly. However, you can construct a simple mode selector block yourself using the following guide:

 +0      1 : a flag word, telling the Wimp that it is a mode selector.
 +4      x-res : the x-resolution (in pixels) [11]
 +8      y-res : the y-resolution (in pixels) [12]
 +12     pixel-depth (0=1 bpp, 1=2 bpp, 2=4 bpp, 3=8 bpp, 4=16 bpp, 5=32 bpp) [9]
 +16     frame rate (-1 means use highest available)
 +20     -1 : terminator

The +0, +4 etc are byte offsets from the start of your block. (Incidentally, some of these values are the same as those returned from SWI "OS_ReadModeVariable" with R1 set to the value shown in square brackets [ ], so it is helpful to be familiar with that SWI.) You might like to note that the selector block is not of fixed length. It can be shorter or longer depending on the particular definition - the format allows extra pairs of 4-byte words to be used from +20 onwards, with the terminator then added afterwards.

Archive 8.1 (a real archive!) carried a pretty detailed explanation of this subject by Matthew Hunter. It's worth looking at and it's on the Archive CD, of course.

The 'mode specifier'

Once a screen mode definition has been put into a block in mode selector format, we need to be able to refer to it in SWI/SYS calls, for instance. This brings us to the mode specifier. Fundamentally, this is just a name for the start address of the mode selector memory block, i.e. an integer number. So, a mode specifier is usually just the address of the required mode selector block.

However, it is a bit more clever than that. If we use a mode specifier and give it a number in the range 0-255, the OS knows that this isn't a memory address and it therefore interprets such a number as one of the old mode numbers instead.

Hence, the mode specifier conveniently captures both old and new methods of defining a screen mode.

A typical use of the mode specifier might be, in Basic:

SYS "Wimp_SetMode",27

to change the wimp mode to 'old' mode 27. Or:

SYS "Wimp_SetMode",modeselector%

to change the wimp mode to the mode selector at location modeselector%.

It is worth noting that the mode specifier is the most frequently used method in SWI calls.

The 'mode string'

The mode string is a textual form of the mode selector - but it's not quite as versatile. It's just a 'cheap and cheerful' alternative method which can be used in several (but not all) SWI/SYS calls.

If you have RISC OS 3.50 or higher, you can probably see what a mode string looks like by 'sliding right' over the mode item from the iconbar menu of the display manager. You might see something like this:

(Your string may be different, and some of it may be cut off at the left, so use the arrow keys to move the cursor along to scroll it.)

The full string in the above case is:

X800 Y600 C16 EX1 EY1

(As the icon is writable, you can change the screen mode directly by altering this string and clicking OK.)

In Basic, this mode string could be used directly, as in the following example:

MODE "X800 Y600 C16 EX1 EY1"

That is, a mode string can be used instead of a number here, but don't forget the quotes (and make sure they are ASCII 34 quotes - see first item!).

The mode string can consist of more code letters than those shown above. The full list is:

Xnnnn     - the x-resolution, where nnnn can be a 3 or 4-digit number
Ynnnn     - the y-resolution, where nnnn can be a 3 or 4-digit number
Cccc      - the number of available colours. Only the following descriptors should be used:
              2, 4, 16, 256, 32K (or 32T), 16M
Gggg      - the number of greys. Only the following descriptors should be used: 4, 16, 256
EXn       - the x-direction 'EIG' factor. n can be 0-3 - the smaller the value the wider
              the text.
EYn       - the y-direction 'EIG' factor. n can be 0-3 - the smaller the value the taller
              the text.
Ffff      - the frame rate in Hz, where fff can be a 2 or 3-digit number.

G and C values cannot be specified together.

When compiling a mode string, the order and the case aren't important. The codes EX, EY and F are optional and default values will be used if you omit them.

You can safely play with these mode string codes in the display manager writable icon, as shown in the earlier screenshot. A mode change takes place as soon as you click OK. If you have something wrong in the string, nothing will happen, but if all is well, the screen will go blank and then restore itself with the desktop displayed with the same contents as before but in the new mode. (Be careful with the EX and EY values because it's easy to make the text so small as to be almost indecipherable and the pointer action is changed as well. This makes it difficult to use the writable icon to change things back!)

Incidentally, using Basic, I have found the mode string the most reliable of the methods to 'play' with.

Reading the current screen mode

Two ways of finding out the current screen mode are:

SYS "OS_ScreenMode",1 TO ,currentmode%

and

screenmode%=MODE

Both of these will return a number, i.e. either an 'old' mode number or a mode specifier.

ModeInfo files

These files contain definitions of all the screen modes available on a particular monitor in an editable text format.

The files are then accessed by commands made available by the ScreenModes module - particularly by the display manager which, among other things, lists the available modes for your selection. If you want to see what they look like go to !Boot.Resources.Configure.Monitors.

ModeInfo files are undoubtedly the 'proper' way to handle screen modes and are very versatile. However, their handling is somewhat involved.


Source: Archive Magazine - 14.12 - "Learners' Column"
Publication: Archive Magazine
Contributor: Ray Favre