Copyright M-) Acorn Computers Ltd. 1993                    0197,290/FS Issue E **Live**

          Medusa Screen Mode Selection API Functional Specification
          =========================================================

                   -----------------------------------------
                   | Drawing No : 0197,290/FS              |
                   |      Issue : D **Live**               |
                   |       Date : 7th April 1993           |
                   |     Author : Tim Dobson               |
                   |     Sheets :                          |
                   |  Last Issue: D                        |
                   -----------------------------------------
 Contents
 --------

 1 History             

 2 Outstanding issues

 3 Overview

 4 Technical Background

 4 1/2 User Interface

 5 Programmer Interface
        5.1  New SWIs
                5.1.1 OS_ScreenMode
        5.2  Extensions to existing SWIs and commands
                5.2.1 OS_ReadModeVariable
                5.2.2 OS_CheckModeValid
                5.2.3 OS_Byte (&87)
                5.2.4 ColourTrans SWIs
                5.2.5 Wimp_SetMode
                5.2.6 *WimpMode
        5.3  Extensions to Service_ModeExtension
        5.4  Extensions to Service_ModeTranslation
        5.5  New service call Service_EnumerateScreenModes
        5.6  New module: ScreenModes
                5.6.1 Overview
                5.6.2 *LoadModeFile
                5.6.3 MonitorType 7 (File)
        5.7  Changes due to hardware differences on Medusa platforms
                5.7.1 Monitor lead ID
        5.8  Grey-scale modes
        5.9  Gamma correction
        5.10 External video cards

 6 Data formats
        6.1  File format for filetype ModeInfo

 7 Development Test Strategy

 8 Future enhancements

 Appendix A (in separate file)
        Screen mode timings

 1. History
 ==========

         TMD 11-Feb-93      Started
 Issue A TMD 24-Feb-93      Released for initial review

 ---------------------------------------------------------------------------

 Issue B TMD 26-Feb-93

 Updated with comments from JRoach, AGlover, CWhyte, MChallis

 ---------------------------------------------------------------------------

 Issue C TMD 07-Apr-93

 Issue about SWI number for OS_ScreenMode removed - spec now says it will
  be allocated later.
 Description of mode selector flags modified and expanded.
 Description of extensions to Service_ModeExtension expanded.
 Clarified that VIDC lists type 0 and 1 are not supported (ie existing mode
  extend modules will not work).
 Removed remaining references to Jordan.
 Description of mode selector flags and mode provider flags expanded.
 Format of block returned from screen mode enumeration service and SWI has
  been changed to include size field.
 Section added about default values of mode variables.
 Section added about grey scales.
 Section added about gamma correction.
 Section added about external video cards.
 Appendix A containing screen mode timings added.
 Mode selector format changed to include desired frame rate, as is
  enumeration block format.
 Default monitor type for monitor ID 0 changed to 3 (VGA) (was 4 (SVGA)).
 DAC control bit added to video control parameters list (and entries
  renumbered).
 Extensions to Service_ModeTranslation added.
 Section on new monitor types removed.
 Section on ScreenModes module added.
 Section on filetype "ModeInfo" format added.
 Screen mode is now always returned in the format it was selected.
 New OS_ScreenMode reason code added to select current monitortype.
 Section added on changes to ColourTrans SWIs.
 Section added on changes to Wimp_SetMode.
 Section added on changes to *WimpMode.
 Service_ModeExtension and Service_EnumerateScreenModes changed to include
  passing in of total video memory size, and registers for OS_ScreenMode(2)
  updated to keep in step.

 ---------------------------------------------------------------------------

 Issue C TMD 07-Apr-93

 Add mode name to ModeInfo file and corresponding field in
  Service_EnumerateScreenModes records.
 Extend test strategy to match changes in issue C
 Add section on !Configure changes - sorts out last two outstanding issues

 ---------------------------------------------------------------------------

 Issue D JSR 23-Apr-93

 Final tidying up for AMR:
 Notes on how to select shadow screens
 

 ---------------------------------------------------------------------------

 Issue E JSR 26-May-93

 Input from implementation:
 OS_ScreenMode SWI number is &65
 Frame rate in mode specified may be given as -1 to allow a first match
  scheme
 Modification to Service_EnumerateScreenModes to allow partial enumeration
  of screen modes
 Correction to OS_ScreenMode reason 3

 ---------------------------------------------------------------------------

 2. Outstanding issues
 =====================

 3. Overview
 ===========

In RISC OS 2 and 3, screen modes are selected by sending the VDU sequence
(22, n) where n is the screen mode number. Since this interface is a byte
wide interface, n is limited to 8 bits. Since bit 7 is interpreted as a
"shadow mode" indicator, there are only in fact 128 different screen modes
available by this interface. Of these 64 are allocated to Acorn, the others
being available for third parties or the user.

This creates a problem for the Medusa version of RISC OS, as VIDC20 supports
higher resolution screen modes, and a wider selection of pixel depths (ie
16- and 32-bit per pixel modes). If all the resolutions we wish to support
on Medusa were represented by one new mode number for each available pixel
depth, the number of screen modes would exceed 64 (RISC OS 3.1 already uses
modes 0 to 46).

Therefore a new way of selecting modes is provided.

In addition, the RISC OS mode extension system needs to be modified. In RISC
OS 2 and 3, modules which provide extra screen modes currently respond to
services, returning lists which contain values to be programmed into VIDC1.

Since VIDC20 is capable of generating screen modes which VIDC1 cannot, a new
list format is necessary to take advantage of these capabilities.

Due to resourcing constraints, the code to support old-style formats will
not be written for Medusa.

Because the range of line frequencies available on monitors varies so
widely, it has been decided that rather than create a plethora of new
monitortype numbers to cope with this, a new ScreenModes module will be
created, which reads the timings for the full set of screen modes from a
file on the hard disc.

A new file format has been defined for this.


 4. Technical background
 =======================

A "mode selector" is a word-aligned structure of the following format:-

        Offset  Value

          0     mode selector flags
                        bit  0    = 1 (always)
                        bits 7..1 = format specifier (zero for this format)
                        bits 31..8 = other flags (must be zero currently)
          4     x-resolution (in pixels)
          8     y-resolution (in pixels)
         12     pixel depth (0=1bpp,1=2bpp,2=4bpp,3=8bpp,4=16bpp,5=32bpp)
         16     frame rate (in Hz) (-1 means 'use first match')
         20     pairs of words (mode variable index, value)
                 (there may be any number of these, including zero)
          n     -1 (terminator)

(The mode variable indexes mentioned here are the same numbers which specify
mode variables in SWI OS_ReadModeVariable).

A "mode specifier" is either a mode number (in the range 0..255) or a
pointer to a mode selector (>255). The range of the value determines which.


 4 1/2. User Interface
 =====================

The user interface described here is that of the Screen dialogue of
!Configure. Please find attached the file Templates which gives the
replacement Screen dialogue. From top to bottom there are 5 fields:

Monitor type: this selects the type of the monitor attached to the computer.
Menuing here will bring up a menu with all the monitor types available
listed on it. The menu will be:
        +-------------------------+
        | Monitor type            |
        +-------------------------+
        | CGA (15kHz)             |
        | Multiscan (15kHz-35kHz) |
        | VGA (31kHz)             |
        | SVGA (31kHz-35kHz)      |
        | SVGA (31kHz-48kHz)      |
        | XGA (31kHz-64kHz)       |
        | XGA (31kHz-78kHz)       |
        | Auto                    |
        +-------------------------+
This being the list of ModeInfo files supplied in the directory
!Configure.Monitors with Auto added to the end. The menu button to the right
of this field will also bring up this menu. The configured monitor will be
ticked, unless the configured monitor isn't one of the !Configure.Monitors
files.

Colours: and Resolution: select the mode in the same way as the mode
selector does (see 0197,254/FS). If monitor Auto is selected then both these
fields will come up 'Auto' - you won't be able to change them and the menus
won't be available.

Blank delay: This works in the same way as the RISC OS 3.1 Blank delay field
in !Configure, except its action is only applied if either of Save or OK is
applied.

Vertical adjust: This is the same as the RISC OS 3.1 Vertical adjust field
except that it isn't writeable and its effect is only applied if either of
Save or OK is pressed.

Below these fields are the following action buttons:

Default: This causes machine default values to be filled in. The default
values will match the factory shipped values.

Save: This saves the settings such that when the machine restarts it comes
up with the chosen values.

Cancel: Left click - quit the box, no further action. Right click - fill in
the values in force when the box was last openned/Saved/OKed.

OK: Apply the values in the box, but don't save them.

[ Implementation details:

A predesktop Obey file should be constructed to action the saved values -
this forms the saving of the values. *LoadModeFile should be used for the
monitor type and *WimpMode for the mode.

To avoid duplication of default setup !Configure should take a copy of the
current configuration if it finds it hasn't already got a copy.

The Monitors directory inside !Configure should contain the ModeInfo files
without any special directory structuring. The file names should be chosen
to give the desired menu ordering.

]

 5. Programmer Interface
 =======================

 5.1 New SWIs
 ============

 5.1.1 OS_ScreenMode (&65)
 -------------------------

The SWI number for this call will be allocated at a later date, and the
functional specification updated to reflect the allocation.

This performs various actions relating to screen modes.

On entry, r0 gives a reason code which determines which operation is
performed.

Reason code 0: Select screen mode

 On entry:      r0 = 0 (reason code)
                r1 = mode specifier

 On exit:       All registers preserved

 This selects the given screen mode.

 If a mode number 'n' is given, then the existing mechanisms are used to
 select this mode, exactly as if VDU 22,n were issued.

 If a pointer to a mode selector is given, then any mode variables which
 are not specified are given sensible defaults, based on the specified
 resolution and pixel depth. Note that the relevant information is copied
 away by RISC OS, so mode selector structures need not remain valid after
 the call has returned.

 If a pointer to a mode selector was given, but the specified mode cannot be
 selected for any reason, then an error is always returned. Note that this
 is different behaviour from mode selection by number, which can select a
 substitute mode in certain cases.

 The way that RISC OS works out the mode variables for a given screen mode
 is different when a mode selector is used:

 When given a mode number, if it is recognised by RISC OS then the mode
 variables for that mode are loaded from its internal tables; if it is not
 recognised then Service_ModeExtension is issued and the module which
 responds to this passes back a workspace list which contains a base mode
 (which must be known to RISC OS) and a list of changes to mode variables.

 When passed a pointer to a mode selector, however, the mode variables are
 initialised to defaults based on the information in the mode selector
 block, viz. the x and y resolutions and the pixel depth. Any mode variables
 specified in the mode selector block override these defaults.

 The default values for these mode variables are as follows:

        Variable          Default value

        ModeFlags               0
        ScrRCol                 (xres >> 3) -1
        ScrBRow                 (yres >> 3) -1
        NColour                 1, 3, 15, 63, &FFFF, &FFFFFFFF
                                 for pixdepth = 0 to 5 respectively
        XEigFactor              1
        YEigFactor              1
        LineLength              (xres << pixdepth) >> 3
        ScreenSize              ((xres*yres) << pixdepth) >> 3
        YShftFactor             0
        Log2BPP                 pixdepth
        Log2BPC                 pixdepth
        XWindLimit              xres-1
        YWindLimit              yres-1

 Service_ModeExtension still gets issued in the mode selector case, but only
 if RISC OS does not know the video timings for the resolutions/pixel
 depth/frame rate asked for, and in this case the module responding provides
 only timing and other hardware control information, and not any mode
 variable values.

 See section 5.3 below for further information on changes to
 Service_ModeExtension.

 Note that in the case where pixdepth=3, the default value of NColour is 63.
 This means that by default, the palette in 256-colour modes behaves as it
 does on VIDC1-based machines, ie palette entries get modified in groups of
 16. This is so that programs which expect the old behaviour will
 work without modification in these modes.

 To gain access to fully-palette-programmable 256 colour modes, the
 following variables should be overridden with these values:-

        Variable        Value

        ModeFlags       128
        NColour         255

 Under these conditions, all 256 palette entries become programmable,
 although the initial palette setting is identical.

 You might notice that there is no explicit way of selecting a shadow
 screen mode. In order to get this effect the program should ensure there is
 sufficient memory in the screen dynamic area before switching screen banks.
 If there is sufficient memory then switching banks will work without a
 hitch.

Reason code 1: Return mode specifier for current screen mode.

 On entry:      r0 = 1 (reason code)

 On exit:       r1 = mode specifier

 If the screen mode was selected by mode number, then this call
 returns that number, otherwise it returns a pointer to a mode selector.

Reason code 2: Enumerate screen modes.

This call provides a front end to Service_EnumerateScreenModes. It fills in
r3 (the current monitortype), r4 (the memory bandwidth available) and r5
(the total amount of video RAM), and then issues the service. See the
section on Service_EnumerateScreenModes for more details.

 On entry:      r0 = 2 (reason code)
                r2 = enumeration index
                r6 = pointer to block to return data into, or 0 to just
                      count entries
                r7 = size of block if r6<>0, or zero if r6=0

 On exit:       r1 = 0 if service claimed, otherwise r1 non-zero.
                r2 = updated enumeration index
                r6 = updated block pointer
                r7 = size of remaining free area in block
                All other registers are preserved.

Note: if r6=0 on entry to this SWI, then no data is returned, but r2 will
have been updated to the number of entries that would have been returned,
and r7 will have been decremented by the number of bytes that would have
been put into the block, therefore -r7 is the size of block that will be
needed to hold all the entries.

Each entry stored is of the following format:-

        Offset  Value

        0       size of entry in bytes (24 for this format)
        4       mode provider flags:
                  bit  0     = 1 (always)
                  bits 7..1  = mode info format specifier (zero for this
                                format)
                  bits 31..8 = additional mode info flags (must be zero)
        8       x-resolution (in pixels)
        12      y-resolution (in pixels)
        16      pixel depth (as per mode selector)
        20      frame rate (Hz) (to the nearest integer)

In the future it is possible that different format entries may be returned
by modules, therefore callers of this SWI should check that bits 7..0 of the
mode provider flags contain 1 before extracting the other information in
this block. If these bits contain a different value which is not recognised
by the caller, then the entry should be skipped by adding on the size field
at offset 0. For format checking purposes, bits 31..8 should be ignored.

Reason code 3: Select current monitortype

This call is provided for internal use by the ScreenModes module. It sets
the current monitortype value, which is used by RISC OS when various
services are issued. This call does NOT change the value configured in CMOS
RAM.

On entry:       r0 = 3 (reason code)
                r1 = monitortype value to set, or
                     -1 to restore to configured value

On exit:        All registers preserved

Note that SWI OS_ReadSysInfo(1) now returns the current monitortype value,
rather than the configured value.

 5.2 Extensions to existing SWIs and commands
 --------------------------------------------

 5.2.1 OS_ReadModeVariable
 -------------------------

 On RISC OS 3 this call is passed one of the following in r0:

  a) mode number, or
  b) -1, indicating current screen mode.

 For Medusa this has now been extended to one of the following:

  a) mode number, or
  b) pointer to mode selector, or
  c) new format sprite mode word, or
  d) -1, indicating current screen mode.

 Cases b) and c) are distinguishable because bit 0 of the new format sprite
 word is always set, whereas it must be clear in case b) because mode
 selectors always start on a word boundary.


 5.2.2 OS_CheckModeValid
 -----------------------

 This call now accepts any mode specifier in r0, not just a mode number. In
 addition, the returned substitute mode may be a pointer to a mode
 specifier.

 5.2.3 OS_Byte(&87) (Read character under cursor, and screen mode)
 -----------------------------------------------------------------

 This call will now return a pointer to a mode selector, if the current
 screen mode was selected that way.

 5.2.4 ColourTrans SWIs
 ----------------------

 The following SWIs:-

        ColourTrans_ReturnGCOLForMode
        ColourTrans_ReturnColourNumberForMode
        ColourTrans_ReturnOppGCOLForMode
        ColourTrans_ReturnOppColourNumberForMode

 previously took a mode number (or -1 for the current mode) as an input
 parameter. In all cases they now accept a general mode specifier, or -1.

 The following SWIs:-

        ColourTrans_SelectTable
        ColourTrans_SelectGCOLTable
        ColourTrans_ReadPalette
        ColourTrans_GenerateTable

 previously took a mode number, or -1 for the current mode, or a sprite area
 pointer. The sprite area pointer case was distinguished by the value being
 greater than or equal to 256 (since mode numbers are only byte quantities).

 In all cases they now accept a general mode specifier, or -1, or a sprite
 area pointer. This raises the issue of how a pointer to a mode selector is
 distinguished from a pointer to a sprite area. However, the first word of a
 sprite area contains the size of the sprite area, which must be a whole
 number of words, therefore bits 0 and 1 will be clear, whereas the first
 word of a mode selector is the flags word which always has bit 0 set, thus
 they are distinguishable.
 
 5.2.5 Wimp_SetMode
 ------------------

 This call previously took a mode number in r0 on input. It now accepts a
 general mode specifier. In the case of a pointer to a mode specifier, the
 WindowManager module makes a copy of the whole structure to use on future
 mode changes, not just a copy of the pointer.

 5.2.6 *WimpMode
 ---------------

 This command now allows the mode to be specified either as a number, or in
 the form of a mode description string, which is a textual form of a mode
 selector. This is also reflected in the mode chooser application, which
 also allows this form.

 The format of this string is described in the Medusa Video
 Software Functional Specification (0197,254/FS) from issue 1.08 onwards.


 5.3 Extensions to Service_ModeExtension
 ---------------------------------------

 When this service is issued on RISC OS 3, the registers are as follows:-

  On entry:     r1 = Service_ModeExtension (&50)
                r2 = mode number
                r3 = monitor type (-1 for don't care)

  On exit:      All registers preserved if not recognised, else

                r1 = 0
                r2 is preserved
                r3 -> VIDC list (type 0 or 1)
                r4 -> workspace list

 On RISC OS for Medusa, the registers are as follows:-

  On entry:     r1 = Service_ModeExtension (&50)
                r2 = mode specifier
                r3 = monitor type (-1 for don't care)
                r4 = memory bandwidth available (in bytes/second)
                r5 = total amount of video RAM in system (in bytes)

  On exit:      All registers preserved if not recognised, else

                r1 = 0
                r2 is preserved
                r3 -> VIDC list (type 3)
                r4 -> workspace list if a mode number was passed in, or
                r4 = 0 if a pointer to a mode selector was passed in

 Note that returning a workspace list is only relevant if a mode number is
 passed in - if a pointer to a mode selector is passed in, RISC OS can work
 out what the mode variables should be for that mode, therefore there is no
 need to return a workspace list, and r4 should be set to zero on exit.

 If a pointer to a mode selector is passed in, the module should check that
 bits 7..0 of the mode selector flags hold the value 1. If they hold a
 different value, this implies that the structure of the rest of the mode
 selector may be different, so the module should pass the service on, unless
 it recognises the new format. 

 For format checking purposes bits 31..8 of the mode selector flags should
 be ignored, as these will only pass in extra information which may be of
 use to some modules.

 The mode selector could contain -1 as the frame rate, in which case the
 first matching mode should be used.

 RISC OS 3 supports two formats (types 0 and 1) of VIDC list (the first
 word of the list is the format type). Both these types include values which
 correspond directly to VIDC1's register formats.

 These formats are NOT supported on Medusa. This means that mode extend
 modules for RISC OS 2 and 3 WILL NOT WORK.

 A new format list (type 3) is available on Medusa RISC OS, which aims to be
 independent of the video controller used. The format is as follows:-

        Offset  Value

          0     3 (format of list)
          4     pixel depth (0=1bpp,1=2bpp,2=4bpp,3=8bpp,4=16bpp,5=32bpp)

          8     horizontal sync width (in pixels)
         12                back porch
         16                left border
         20                display size
         24                right border
         28                front porch

         32     vertical sync width (in rasters)
         36              back porch
         40              top border
         44              display size
         48              bottom border
         52              front porch

         56     pixel rate (in kHz)
         60     sync polarities
                  bit 0 set => Hsync inverted
                  bit 1 set => Vsync inverted
                  bits 2-31 must be zero

                  NB if composite sync is configured in CMOS, the syncs
                  will not be inverted

         64     video control parameters list
          n     -1 (terminator)

The video control parameters list which is on the end of this list contains
pairs of words (control parameter index, value), terminated by a -1 word,
which control various additional VIDC registers and bits in registers, as
follows (refer to VIDC20 data sheet for detailed explanations of terms):-

        Control Parameter
        Index   Description             Values

        1       LCD mode                0 => disable, 1 => enable
        2       LCD dual-panel mode     0 => disable, 1 => enable
        3       LCD Offset Register 0   0 to 255
        4       LCD Offset Register 1   0 to 255
        5       Hi-res mode             0 => disable, 1 => enable
        6       DAC control             0 => disable, 1 => enable (default)
        7       RGB pedestal enables    bit0=R, bit1=G, bit2=B
        8       External Register [7:0] 0 to 255
        9       hclk select/specify     See note a) below
       10       rclk frequency          See note b) below

Notes
-----

a) This value, if non-zero, forces RISC OS to select hclk as its clock
input, and the value itself indicates to RISC OS what frequency is expected
to be coming in on this pin (in kHz). RISC OS will then set up the internal
divider to try to achieve the pixel rate specified in the main body of the
list (normally you would make this the same, so that RISC OS would select
divide by 1). The frequency is also used by RISC OS to compute the FIFO load
position.

If the value is zero, then RISC OS uses rclk or vclk as per normal.

b) This value, if non-zero, tells RISC OS that the frequency coming in on
the rclk pin is not 24MHz, but is in fact the value specified (in kHz). This
knowledge is then used by RISC OS to determine the moduli values for the
specified pixel rate and the FIFO load position. In addition, the value is
stored in VDU variable VIDCClockSpeed, which is read by the sound system to
determine what value to program the Sound Frequency Register with (since the
sound system is driven by rclk).


It is expected that the control parameters list will normally contain no
entries at all for normal video operation - only for special applications is
this needed.

[ Implementation details:

Note: RISC OS needs to compute the moduli for the Frequency Synthesizer
Register, based on the requested pixel rate. This requires that either the
operating range of the VCO is known at assembly time, or some kind of
"biofeedback" code is written which times the output from VIDC using the
vsync input.

]

Two additional parameters are supplied on entry to Service_ModeExtension,
namely the video bandwidth available on the machine, in units of
bytes/second, passed in R4 on entry, and the total amount of video RAM in
the system, in bytes, passed in R5 on entry.

These are useful because the Medusa range of machines encompass a wide range
of video capabilities, from DRAM-only machines through to machines with 1 or
2 Mbytes of VRAM. Supplying this parameter allows a mode provider to check
that a given screen mode at the specified frame rate can be achieved with
the machine's video bandwidth and its amount of video RAM.

A mode provider should only respond to this service if the mode being
selected would use no more video bandwidth than the amount in R4, and no
more video memory than the amount in R5.

[ Implementation detail:

Since it is impossible for the machine to measure the video bandwidth
available, RISC OS will supply one of 3 fixed values, based on whether the
machine is fitted with 0, 1 or 2 Mbytes of VRAM respectively.

]


 5.4 Extensions to Service_ModeTranslation
 -----------------------------------------

On RISC OS 3 this service passes in a mode number which is unavailable on
the current monitortype, and passes back a substitute mode number.

On Medusa, this is extended to allow the substitute mode passed back in r2
to be an arbitrary mode specifier.

However, the input mode will only ever be a mode number, as a mode change
controlled by a pointer to a mode selector never uses a substitute mode.


 5.5 New service call Service_EnumerateScreenModes (reason code &8D)
 -------------------------------------------------------------------

The function of this service call is to allow "mode chooser" applications to
find out what resolutions at what pixel depths are available.

Applications should not issue this service call directly - they should
instead call OS_ScreenMode with reason code 2 (see above for details).

 On entry:      r1 = &8D (reason code)
                r2 = enumeration index
                r3 = monitor type
                r4 = memory bandwidth available (in bytes/second)
                r5 = total amount of video RAM in system (in bytes)
                r6 = pointer to block to return data into, or 0 to just
                      count entries
                r7 = size of block if r6<>0, zero if r6=0

 On exit:       r2 = updated enumeration index
                r6 = updated block pointer
                r7 = updated size of block

  This service call provides a means whereby modes can be enumerated. It can
  be issued in two ways: the first to find out how many modes there are,
  and how much space is needed to store all of them; the second to actually
  enumerate them into a buffer. The enumeration form can be done as a
  partial enumeration so that a fixed size buffer can be used.

  The following descriptions are from the point of view of the caller:

  Finding out how many modes there are and how much space they need:

  On entry:     r1 = &8D (reason code)
                r2 = 0 (enumeration index)
                r3 = monitor type
                r4 = memory bandwidth available
                r5 = total VRAM
                r6 = 0
                r7 = 0

  On exit:      r2 = -(number of modes)
                r7 = -(amount of space needed for them)
                other registers preserved

  Doing a (partial) enumeration:

  On entry:     r1 = &8D (reason code)
                r2 = number of modes to skip
                r3 = monitor type
                r4 = memory bandwidth available
                r5 = total VRAM
                r6 = pointer to block
                r7 = size of block

  On exit:
        Block big enough case:
                r1 = &8D
                r2 = -(number of modes in block)
                r6 = pointer to byte after last filled in byte
                r7 = amount of unused space in block
        Block too small case:
                r1 = 0 (Service_Serviced)
                r2 = -(number of modes in block)
                r6 = pointer to byte after last filled in byte
                r7 = amount of unused space in block

  As a client of this service call your algorithm should be:
  Repeat
    r2 = total number of entries processed so far (ie is 0 first time round)
    r6 = pointer to block
    r7 = size of block
    Call OS_ScreenMode reason 2 (Enumerate screen modes)
    Process block contents (from block to r6 returned from OS_ScreenMode)
  Until r1 returned from OS_ScreenMode was non-0


  As a module which wishes to respond to this service call your algorithm
  should be:

  For each mode that wants to be returned
    If r2 > 0 Then
      do nothing, ie skip it
    Else
      If r6<>0 Then
        (enumeration case - filling in block)
        If r7 >= entrysize Then
          store entry at r6
          r6 += entrysize
        Else
          (not enough space for next mode)
          r1 = 0 (Service_Serviced)
          Return (service call claimed)
        EndIf
      EndIf
      r7 -= entrysize
    EndIf
    r2 -= 1
  Next
  Return (service call passed on)

  The registers are updated as follows:-

                r1 = preserved (block didn't overflow) or 0 (block
                      overflowed)
                r2 = updated enumeration index (decremented by 1 for each
                      entry considered)
                r3-r5 are preserved
                r6 = block pointer, updated to point after all entries
                      stored in the block (or stays at 0)
                r7 = size of remaining free area in block (or gets
                      decremented by amount of space needed by the entries
                      that would have been put into the block had r6 been
                      non-0)

The module should return information on all modes that it provides that work
on the specified monitor type and which require no more than the specified
memory bandwidth, and no more video memory than the specified amount.

For each such screen mode, the module stores the following information in
the block:-

        Offset  Value

        0       size of entry in bytes (24 for this format)
        4       mode provider flags:
                  bit  0     = 1 (always)
                  bits 7..1  = mode info format specifier (zero for this
                                format)
                  bits 31..8 = additional mode info flags (must be zero)
        8       x-resolution (in pixels)
        12      y-resolution (in pixels)
        16      pixel depth (as per mode selector)
        20      frame rate (Hz) (to the nearest integer)
        24      mode name. This will be 0-terminated and then padded with 0s
                        until it is word aligned. For unnamed modes this
                        will simply be a single word whose value is 0.

 5.6 New module: ScreenModes
 ---------------------------

 5.6.1 Overview
 --------------

 VIDC20 supports a much wider range of monitors than did VIDC1.

 Because the range of line frequencies available on monitors varies so
 widely, it has been decided that rather than create a plethora of new
 monitortype numbers to cope with this, a new ScreenModes module will be
 created, which reads the timings for the full set of screen modes from a
 file on the hard disc.

 Files containing screen mode information will have the filetype "ModeInfo".
 The number for this will be allocated at a later date, and the functional
 specification updated to reflect the allocation.

 The format for these files is described in section 6.1 below.

 5.6.2 *LoadModeFile
 -------------------

 Syntax: *LoadModeFile <filename>

 This command loads a file of type "ModeInfo" into memory, and if the file
 contains valid information, sets the current monitortype to 7 (file) (using
 OS_ScreenMode(3)). This then makes available all the screen modes defined
 in the file, while removing all modes defined in any previously loaded
 file.

 5.6.3 MonitorType 7 (File)
 --------------------------

 This new monitortype is reserved for exclusive use by the ScreenModes
 module. When a file is loaded by the module, the current monitortype is set
 to this, which effectively replaces all the screen modes defined in the ROM
 by the modes defined in the file, because the kernel does not respond to
 this monitortype.


 5.7 Changes due to hardware differences on Medusa platforms
 -----------------------------------------------------------

 5.7.1 Monitor lead ID
 ---------------------

 In order to reduce cost, Medusa platforms can only detect bit 0 of the
 monitor lead ID.

 The tables below show the old and the new mappings from monitor lead ID to
 monitor type, mode and sync type.

 Mapping for existing machines
 -----------------------------

 ID Bits
 3210   Description     Monitor Screen  Sync
                        type    mode    type

 X101   Mono VGA        3       27      0
 X110   Colour VGA      3       27      0
 X010   Colour SVGA     1       27      0
 XH11   Comp.Multisync  1       27      1
 X11H   TV standard     0       12      1
 Other  ?               0       12      1

 Mapping for Medusa series machines
 ----------------------------------

 ID Bit
    0   Description     Monitor Screen  Sync
                        type    mode    type

    0   VGA capable     3       27      0
    H   TV standard     0       12      1
    1   TV standard     0       12      1
 Other  TV standard     0       12      1

 Because of the existence of the ScreenModes module, determining the monitor
 type from the monitor lead ID is much less important.

 Effectively the ID is only useful in setting up an initial screen mode,
 before the ModeInfo file for the user's monitor has been loaded.

 5.8 Grey-scale modes
 --------------------

 The RISC OS kernel will not provide any extra support for grey-scale modes.
 The WindowManager module will be extended to allow the selection of 16- and
 256-level grey scale modes in the desktop - this will be implemented by the
 Wimp explicitly programming the palette after the mode change. In the
 256-level case it will have to select a 256-colour mode with a fully
 programmable palette by the means described in section 5.1.1.


 5.9 Gamma correction
 --------------------

 RISC OS now allows an application to supply tables to perform gamma
 correction on RGB values being programmed into the palette. There are three
 256-byte tables, one for each of red, green and blue.

 Before being output to VIDC, the red component of the physical colour (in
 the range 0 to 255) is used as an index into the red gamma correction
 table - the value obtained is the gamma corrected red value to be
 programmed into VIDC.

 In a similar fashion the green and blue components are looked up in their
 respective tables.

 The contents of the tables are set up by a call to PaletteV, as follows:-

  On entry:     r0 -> gamma-correction table for red (must be word-aligned)
                r1 -> gamma-correction table for green (--------""--------)
                r2 -> gamma-correction table for blue (---------""--------)
                r4 = 9 (reason code)

  On exit:      r4 = 0 => the video drivers support gamma correction, and
                          the tables have been copied into system workspace

                r4 <> 0 => the video drivers do not support gamma correction


 5.10 External video cards
 -------------------------

 No additional support is provided in RISC OS for video cards. It is
 believed that the existing interfaces provide enough hooks for these to be
 added.

 The main requirement that an external video card has is to be able to
 redirect RISC OS's bitmap to an area of RAM on an expansion card. This
 would be in EASI space, and consequently it can allow full 32-bit access.

 This means that provided that RISC OS's screen address can be changed to
 point to somewhere in EASI space, the normal graphics primitives will work
 correctly.

 It is envisaged that the mechanism used to change screen address would be
 to switch VDU output into a sprite, where the sprite is situated in EASI
 space. This would require that there is some RAM immediately before the
 start of the bitmap, to hold the sprite area and sprite headers.

 An additional complication is the mouse pointer: its position can be polled
 on vsync by the external card drivers, and then whatever hardware on
 the card is producing the screen pointer can be updated with its new
 position.


 6. Data formats
 ===============

 6.1 File format for filetype ModeInfo
 -------------------------------------

 Files of type ModeInfo contain definitions of all the screen modes
 available on a particular monitor. The mode definitions are written in
 plain text, so the files can be edited using !Edit.

 Spaces and tab characters (&09) are allowed anywhere in the file except in
 the middle of keywords or numbers.

 Lines starting with any number of spaces followed by the hash character "#"
 are treated as comments and ignored.

 The file consists of the following two lines:

        file_format: <format>
        monitor_title: <title>

 followed by any number of mode definitions, where

  <format> must be 1 for this format file
  <title> is a textual description for this type of monitor

 and a mode definition is as follows:

        startmode
            x_res: <x-resolution>
            y_res: <y-resolution>
            h_timings: <hsync>, <hbpch>, <hlbdr>, <hdisp>, <hrbdr>, <hfpch>
            v_timings: <vsync>, <vbpch>, <vtbdr>, <vdisp>, <vbbdr>, <vfpch>
            pixel_rate: <pixel rate>
            sync_pol: <sync polarities>
            mode_name: <mode name>
        endmode

where

 <x-resolution>  is the number of pixels displayed across the screen
 <y-resolution>  is the number of displayed rasters

 The h_timings line controls the horizontal timings, as follows:

 <hsync> is the width of the hsync pulse in pixels
 <hbpch> is the width of the horizontal back porch in pixels
 <hlbdr> is the width of the left hand border in pixels
 <hdisp> is the number of displayed pixels horizontally (normally the same
          as <x-resolution>)
 <hrbdr> is the width of the right hand border in pixels
 <hfpch> is the width of the horizontal front porch in pixels

 The v_timings line controls the vertical timings, as follows:

 <vsync> is the width of the vsync pulse in rasters
 <vbpch> is the width of the vertical back porch in rasters
 <vtbdr> is the width of the top border in rasters
 <vdisp> is the number of displayed rasters vertically (normally the same
          as <y-resolution>)
 <vbbdr> is the width of the bottom border in rasters
 <vfpch> is the width of the vertical front porch in rasters

 <pixel rate> is the pixel rate required, in kHz

 <sync_polarities> is a number indicating what kind of sync signals are
  required, as follows:

        0 => hsync normal, vsync normal
        1 => hsync inverted, vsync normal
        2 => hsync normal, vsync inverted
        3 => hsync inverted, vsync inverted
        4 => composite syncs

 <mode name> is a textual name for the mode for use in menus and such. The
  mode name field must be present, although the <mode name> itself may be
  blank.

Note: VIDC20 imposes restrictions on the above parameters. In particular,
all the horizontal timing values must be multiples of 2, and the horizontal
total = hsync + hbpch + hlbdr + hdisp + hrbdr + hfpch must be a multiple of
4. See the VIDC20 specification for details of further restrictions.


 7. Development test strategy
 ============================

PHTester scripts will be constructed to test the following SWIs/reason
codes:

OS_ScreenMode
 Reason 0
  Mode numbers 0-255 will be tried
  A valid mode selector will be constructed and each of its
   parameters will be adjusted individually to be:
           Completely out of range
           Just out of range
           Just in range
  The mode selector with all parameters in range will also be tried
 Reason 1
  For all the above selections reason 1 will be issued and the results
   displayed assuming the correct behaviour of reason 1.
 Reason 2
  With the machine set up with a known set of screen modes this reason will
   be issued and the results displayed assuming correct behaviour.
 Reason 3
  This reason will be issued with normal values and with -1 and the results
  displayed.

OS_ReadModeVariable
 Two different mode numbers and five different mode specifiers will be
  tried. All mode variables will be obtained using all of these. The
  resulting mode variable values will be displayed. The mode specifiers must
  exercise 16 and 32bpp modes as well as 4 and 8 bpp modes.

OS_CheckModeValid
 The same set of mode selectors as OS_ScreenMode was tried with will be
  tried on OS_CheckModeValid. The results will be displayed.

OS_Byte (&87)
 The same set of mode selectors as OS_ScreenMode was tried with will be
  tried on OS_Byte (&87). The results will be displayed.

Service_ModeExtension
 The same set of mode selectors as OS_ScreenMode was tried with will be
  tried on Service_ModeExtension. The results will be displayed. This will
  be performed with a known machine setup.

Service_EnumerateScreenModes
 With a given machine setup Service_EnumerateScreenModes will be issued to
  obtain all possible screen modes. This will also be issued with a limited
  block size to test that the block doesn't get overflowed.
 A responder to Service_EnumerateScreenModes will be written which will
  generate each of the control indexes with each of the valid values (for
  small range indexes) and control values at each end of the ranges and in
  the middle (for wide range values such as LCD Offset Register 0).

ColourTrans SWIs
 These will be tried with the range of mode specifiers prepared above as
  well as with the full range of mode numbers. The sprite area pointer tests
  are expected to be exercised as part of the general video enhancements
  work.

Wimp_SetMode and *WimpMode
 *WimpMode will be tried with mode numbers - range checking will be tested,
  and mode description strings - a reasonable variety tried.
 Wimp_SetMode will be tested to make sure it generates mode specifiers
  correctly. All mode description string parameters will be tried
  independantly and then mixed in a number of reasonable varieties.

Service_ModeTranslation
 A module will be written to substitute a fixed mode specifier. This will
  check for correct response to this service call.

*LoadModeFile
 Valid ModeInfo files for all the RISC OS 3 monitor types will be prepared
  and tried. One of these will be corrupted with duff field values (each
  field will be corrupted on its own) and tried on *LoadModeFile.

Monitor ID
 CGA, MultiSync, VGA and SVGA monitors will be tried to ensure the monitor
  ID algorithm gives a usable screen mode.

Gamma Correction
 A BASIC application to generate gamma correction tables will be written to
  try this feature. This will be supplied in the Diversions directory.

User Interface
 A mouse script will be prepared to exercise this part of !Configure.
  All buttons will be pressed with both click and adjust. This will be tried
  with a sensible Monitors directory as well as an empty one and a full one.
  It will be tried with both and absent and present defaults file inside
  !Configure. It will be tried with the configured setting being one of
  !Configure's files and with it being another file.


 8. Future enhancements
 ======================

 With the interfaces described above, it is possible to create a module
 which reads screen mode parameters from a file on initialisation. We would
 probably want to include some kind of editor which allows the user to test
 out new modes she has created.

 Medusa RISC OS does not understand VIDC lists type 0 or 1 returned from
 Service_ModeExtension. This may be added at a later date.

-- End of screen mode selection API --